Está en la página 1de 1513

Contents

Xamarin.Android
Primeros pasos
Configuración e instalación
Instalación en el equipo Windows
Configuración de Android SDK
Configuración de Android Emulator
Aceleración de hardware (Hyper-V y HAXM)
Administrador de dispositivos
Propiedades de dispositivos
Solución de problemas
Configuración de dispositivos Android
Vista previa de OpenJDK Mobile de Microsoft
Hello, Android
Parte 1: Inicio rápido
Parte 2: profundización
Multipantalla de Hello, Android
Parte 1: Inicio rápido
Parte 2: profundización
Xamarin para desarrolladores de Java
Principios de la aplicación
Accesibilidad
Niveles de API de Android
Recursos de Android
Conceptos básicos de los recursos de Android
Recursos predeterminados
Recursos alternativos
Creación de recursos para diferentes pantallas
Localización de aplicaciones y recursos de cadena
Uso de recursos de Android
Fuentes
Ciclo de vida de la actividad
Tutorial: guardado del estado de actividad
Servicios de Android
Crear un servicio
Servicios enlazados
Servicios de intención
Servicios iniciados
Servicios de primer plano
Servicios fuera de proceso
Notificaciones del servicio
Receptores de difusión
Localización
Permisos
Gráficos y animación
Arquitecturas de CPU
Control de giro
Audio
Notificaciones
Notificaciones locales
Tutorial de notificaciones local
Entrada táctil
Entrada táctil de Android
Tutorial: uso de la entrada táctil en Android
Seguimiento multitáctil
Pila HttpClient y SSL/TLS
Escritura de aplicaciones con capacidad de respuesta
Interfaz de usuario
Android Designer
Uso de Android Designer
Conceptos básicos de Designer
Calificadores de recursos y opciones de visualización
Vistas de diseños alternativos
Características de Material Design
Tema de materiales
Perfil de usuario
Pantalla de presentación
Diseños
LinearLayout
RelativeLayout
TableLayout
RecyclerView
Elementos y funcionalidad
Ejemplo de RecyclerView
Extensión del ejemplo
ListView
Elementos y funcionalidad de ListView
Relleno de ListView con datos
Personalización de la apariencia de ListView
Uso de CursorAdapters
Uso de ContentProvider
ListView y ciclo de vida de actividad
GridView
GridLayout
Diseños con pestañas
Pestañas de navegación con ActionBar
Controles
ActionBar
Autocompletar
Botones
Radio Button
Botón de alternancia
CheckBox
Botón personalizado
Calendario
CardView
EditText
Galería
Barra de navegación
Selectores
Selector de fecha
Selector de hora
Menú emergente
RatingBar
Spinner
Modificador
TextureView
Barra de herramientas
Reemplazo de la barra de acciones
Adición de una segunda barra de herramientas
Compatibilidad de barra de herramientas
ViewPager
ViewPager con vistas
ViewPager con fragmentos
WebView
Características de la plataforma
Android Beam
Manifiesto de Android
Acceso a archivos con Xamarin.Android
Almacenamiento externo
Autenticación de huella digital
Introducción
Examen de huellas digitales
Creación de CryptoObject
Respuesta a las devoluciones de llamada de autenticación
Guía y resumen
Inscripción de una huella digital
Programador de trabajos de Android
Distribuidor de trabajo de Firebase
Fragmentos
Implementación de fragmentos
Guía detallada sobre los fragmentos: parte 1
Guía detallada sobre los fragmentos: parte 2
Creación de un fragmento
Administración de fragmentos
Clases de fragmentos especializadas
Provisión de compatibilidad con versiones anteriores
Vinculación de aplicaciones
Android 9 Pie
Android 8 Oreo
Android 7 Nougat
Android 6 Marshmallow
Android 5 Lollipop
Android 4.4 KitKat
Android 4.1 Jelly Bean
Android 4.0 Ice Cream Sandwich
Proveedores de contenido
Funcionamiento
Uso de ContentProvider de contactos
Creación de un ContentProvider personalizado
Mapas y ubicación
Ubicación
Asignaciones
Aplicación de mapas
API de Maps
Obtención de una clave de la API de Google Maps
Uso de Android.Speech
Integración con Java
Contenedores que se pueden llamar de Android
Trabajo con JNI
Migración de Java a C#
Enlace de una biblioteca Java
Enlace de un .JAR
Enlace de un .AAR
Enlace de un proyecto de biblioteca de Eclipse
Personalización de enlaces
Metadatos de enlaces Java
Nomenclatura de parámetros con Javadoc
Solución de problemas de enlaces
Uso de bibliotecas nativas
Renderscript
Xamarin.Essentials
Introducción
Compatibilidad de plataforma y características
Acelerómetro
Información de la aplicación:
Barómetro
Batería
Portapapeles
Convertidores de colores
Brújula
Conectividad
Detección de vibraciones
Información de pantalla del dispositivo
Información del dispositivo
Correo electrónico
Asistentes del sistema de archivos
Linterna
Codificación geográfica
Geolocalización
Giroscopio
Selector
Magnetómetro
Subproceso principal
Asignaciones
Apertura del explorador
Sensor de orientación
Marcador telefónico
Extensiones de plataforma (Size, Rect, Point)
Preferencias
Almacenamiento seguro
Compartir
SMS
Texto a voz
Convertidores de unidades
Seguimiento de versiones
Vibración
Solución de problemas
Datos y servicios en la nube
Azure Active Directory
Introducción
Paso 1. Registro
Paso 2. Configurar
Acceso a Graph API
Azure Mobile Apps
Acceso a datos en ASP.NET (Visual Studio)
Introducción
Configuración
Uso de SQLite.NET ORM
Uso de ADO.NET
Uso de datos en una aplicación
Mensajería de Google
Mensajería en la nube de Firebase
Tutorial de notificaciones de FCM
Google Cloud Messaging
Tutorial de notificaciones de GCM
Servicios Web
Implementación y prueba
Tamaño del paquete de la aplicación
Compilar aplicaciones
Proceso de compilación
Compilar APK específicos de ABI
Emulador de la línea de comandos
Depuración
Depurador en el emulador
Depuración en un dispositivo
Registro de depuración de Android
Atributo Debuggable
Entorno
GDB
Configuración personalizada del vinculador
Dispositivos de varios núcleos
Rendimiento
Generación de perfiles
Preparación para la versión
ProGuard
Firmar el APK
Firma manual del APK
Búsqueda de la firma de su almacén de claves
Publicación de una aplicación
Publicación en Google Play
Servicios de licencia de Google
Archivos de expansión de APK
Carga manual del APK
Publicación en Amazon
Publicación de forma independiente
Instalación como aplicación de sistema
Conceptos avanzados y funcionamiento interno
Arquitectura
Ensamblados disponibles
Diseño de API
recolección de elementos no utilizados
Limitaciones
Solución de problemas
Sugerencias para la solución de problemas
Preguntas más frecuentes
¿Qué paquetes de Android SDK debo instalar?
¿Dónde puedo configurar mi ubicaciones de Android SDK?
¿Cómo se puede actualizar la versión del kit de desarrollo de Java (JDK)?
¿Puedo usar la versión 9 del kit de desarrollo de Java (JDK) o una versión
posterior?
¿Cómo instalar manualmente las bibliotecas de compatibilidad de Android que
requieren los paquetes de Xamarin.Android.Support?
¿Qué controladores USB son necesario para depurar Android en Windows?
¿Es posible conectarse a emuladores de Android que se ejecutan en un Mac desde
una máquina virtual de Windows?
¿Cómo se automatiza un proyecto de prueba de NUnit de Android?
¿Por qué no se puede conectar la compilación de versión de Android a Internet?
Paquetes NuGet más inteligentes de Xamarin Android Support v4/v13
¿Cómo se puede resolver una excepción PathTooLongException?
¿Qué versión de Xamarin.Android agrega compatibilidad con Lollipop?
Android.Support.v7.AppCompat: no se encontró ningún recurso que coincida con
el nombre especificado: attr 'android: actionModeShareDrawable'
Ajuste de los parámetros de memoria de Java para Android Designer
Mi archivo Resource.designer.cs de Android no se actualizará
Resolución de errores de instalación de biblioteca
Cambios en las Herramientas de Android SDK
Referencia de errores de Xamarin.Android
Wear
Primeros pasos
Introducción a Android Wear
Configuración e instalación
Hola, Wear
Interfaz de usuario
Controles
GridViewPager
Características de la plataforma
Creación de una esfera del reloj
Tamaños de pantalla
Implementación y pruebas
Depurar en un emulador
Depuración en un dispositivo Wear
Empaquetado
Notas de la versión
Muestras
Introducción a Xamarin.Android
11/07/2019 • 2 minutes to read • Edit Online

Configuración e instalación
Configure Xamarin.Android y ejecútelo en Visual Studio. En esta sección se trata la descarga, la instalación, la
configuración del emulador, el aprovisionamiento de dispositivos, etc.

Hello, Android
Esta guía, que consta de dos partes, le ayudará a compilar su primera aplicación de Xamarin.Android mediante
Visual Studio y a comprender los aspectos básicos del desarrollo de aplicaciones de Android con Xamarin. A lo
largo del proceso, en esta guía se presentan las herramientas, los conceptos y los pasos necesarios para compilar e
implementar una aplicación de Xamarin.Android.

Hello, Android Multiscreen


En esta guía, que consta de dos partes, ampliará la aplicación creada en la guía Hello, Android a fin de implementar
una segunda pantalla. Durante esta guía se presentan los componentes básicos de la aplicación de Android y se
profundiza en la arquitectura de Android a medida que va conociendo mejor la estructura y la funcionalidad de la
aplicación de Android.

Xamarin para desarrolladores de Java


En este artículo se proporciona una introducción a la programación en C# para los desarrolladores de Java y se
centra principalmente en las características del lenguaje C# con las que se encontrarán los desarrolladores de Java
durante el aprendizaje del desarrollo de aplicaciones Xamarin.Android.

Vídeo
Creación de una aplicación de Android por primera vez con Xamarin para Visual Studio
Configuración e instalación
11/07/2019 • 3 minutes to read • Edit Online

En los temas incluidos en esta sección se explica cómo instalar y configurar Xamarin.Android para que funcione
con Visual Studio en Windows y macOS, cómo usar Android SDK Manager para descargar e instalar
herramientas y componentes de Android SDK necesarios para compilar y probar la aplicación, cómo configurar
Android Emulator para la depuración y cómo conectar un dispositivo Android físico al equipo de desarrollo para
depurar la aplicación y realizar las pruebas finales.

Instalación en el equipo Windows


En esta guía se describen los pasos de instalación y los detalles de configuración necesarios para instalar
Xamarin.Android en Windows. Cuando acabe el artículo, tendrá una instalación operativa de Xamarin.Android
integrada en Visual Studio y podrá empezar a compilar su primera aplicación de Xamarin.Android.

Instalación para Mac


En este artículo se describen los pasos de instalación y los detalles de configuración necesarios para instalar
Xamarin.Android en Mac. Cuando acabe el artículo, tendrá una instalación operativa de Xamarin.Android
integrada en Visual Studio para Mac y podrá empezar a compilar su primera aplicación de Xamarin.Android.

Configuración de Android SDK


Visual Studio incluye un Android SDK Manager que reemplaza el Android SDK Manager independiente de
Google. En este artículo se explica cómo usar SDK Manager para descargar herramientas de Android SDK,
plataformas y otros componentes necesarios para desarrollar aplicaciones de Xamarin.Android.

Configuración de Android Emulator


En estos artículos se explica cómo configurar Android Emulator para probar y depurar aplicaciones de
Xamarin.Android.

Configuración de dispositivos Android


En este artículo se explica cómo configurar un dispositivo Android físico y conectarlo a un equipo de desarrollo de
modo que el dispositivo pueda usarse para ejecutar y depurar aplicaciones de Xamarin.Android.

Vista previa de OpenJDK Mobile de Microsoft


En esta guía se describen los pasos para cambiar a la versión preliminar de la distribución de OpenJDK de
Microsoft. Esta distribución de OpenJDK está pensada para el desarrollo móvil.
Instalación en el equipo Windows
11/07/2019 • 11 minutes to read • Edit Online

En esta guía se describen los pasos necesarios para instalar Xamarin.Android para Visual Studio en Windows y se
explica cómo configurar Xamarin.Android para compilar su primera aplicación de Xamarin.Android.

Información general
Gracias a que ahora Xamarin se incluye con todas las ediciones de Visual Studio sin ningún costo adicional y no
requiere ninguna licencia independiente, puede usar el instalador de Visual Studio para descargar e instalar las
herramientas de Xamarin.Android (los pasos relacionados con la instalación manual y la configuración de las
licencias que eran necesarios para las versiones anteriores de Xamarin.Android ya no son necesarios). En esta guía
aprenderá lo siguiente:
Cómo configurar las ubicaciones personalizadas para Java Development Kit, el SDK de Android y el NDK
de Android.
Cómo iniciar Android SDK Manager para descargar e instalar componentes adicionales del SDK de
Android.
Cómo preparar un emulador o dispositivo de Android para la depuración y las pruebas.
Cómo crear el primer proyecto de aplicación de Xamarin.Android.
Cuando acabe esta guía, tendrá una instalación operativa de Xamarin.Android integrada en Visual Studio y podrá
empezar a compilar su primera aplicación de Xamarin.Android.

Instalación
Para obtener información detallada sobre la instalación de Xamarin para su uso con Visual Studio en Windows,
consulte la guía de instalación de Windows.

Configuración
Xamarin.Android usa Java Development Kit (JDK) y el SDK de Android para compilar las aplicaciones. Durante la
instalación, el instalador de Visual Studio coloca estas herramientas en sus ubicaciones predeterminadas y
configura el entorno de desarrollo con la configuración de ruta de acceso adecuada. Puede ver y cambiar estas
ubicaciones haciendo clic en Herramientas > Opciones > Xamarin > Configuración de Android:
Para la mayoría de los usuarios, estas ubicaciones predeterminadas funcionarán correctamente y no habrá que
efectuar más cambios, pero tal vez quiera configurar Visual Studio con unas ubicaciones personalizadas para estas
herramientas (por ejemplo, en el caso de que haya instalado el JDK de Java, el SDK de Android o el NDK en otra
ubicación). Haga clic en Cambiar junto a la ruta de acceso que quiera cambiar; luego, desplácese hasta la nueva
ubicación.
Xamarin.Android usa JDK 8, necesario para el desarrollo en el nivel de API 24 o superior. JDK 8 también admite
niveles de API anteriores al 24. Si está desarrollando contenido específicamente para el nivel de API 23 o uno
anterior, puede continuar usando JDK 7.

IMPORTANT
Xamarin.Android no admite JDK 9.

Administrador de SDK de Android


Android usa varias opciones de nivel de API de Android para determinar la compatibilidad de su aplicación entre
las distintas versiones de Android (para obtener más información sobre los niveles de la API de Android, consulte
Understanding Android API Levels [Información de los niveles de API de Android]). En función de los niveles de
API de Android que quiera establecer como objetivo, es posible que tenga que descargar e instalar componentes
adicionales del SDK de Android. Además, puede que tenga que instalar herramientas opcionales, así como las
imágenes del emulador que se proporcionan en el SDK de Android. Para ello, use Android SDK Manager. Puede
iniciar Android SDK Manager haciendo clic en Herramientas > Android > Android SDK Manager:
De forma predeterminada, Visual Studio instala Android SDK Manager de Google:

Puede usar Android SDK Manager de Google para instalar las versiones del paquete de Android SDK Tools hasta
la versión 25.2.3, pero si necesita usar una versión posterior del paquete de Android SDK Tools, debe instalar el
complemento de Android SDK Manager de Xamarin para Visual Studio (disponible en Visual Studio Marketplace).
Esto es necesario porque el SDK Manager independiente de Google ha quedado en desuso en la versión 25.2.3 del
paquete de Android SDK Tools.
Para más información sobre cómo usar Android SDK Manager de Xamarin, vea Configuración de Android SDK.
Emulador Android
Android Emulator puede ser una herramienta útil para desarrollar y probar una aplicación Xamarin.Android. Por
ejemplo, un dispositivo físico, como una tableta, podría no estar disponible durante el desarrollo o un programador
podría querer ejecutar algunas pruebas de integración en su equipo antes de confirmar el código.
La emulación de un dispositivo Android en un equipo implica a los siguientes componentes:
Google Android Emulator – Se trata de un emulador basado en QEMU que crea un dispositivo virtualizado
que se ejecuta en la estación de trabajo del desarrollador.
Una imagen de emulador – Una imagen de emulador es una plantilla o una especificación del hardware y el
sistema operativo que se va a virtualizar. Por ejemplo, una imagen de emulador identificaría los requisitos de
hardware de un Nexus 5X con Android 7.0 con Google Play Services instalado. Otra imagen de emulador
podría especificar una tableta de 10" con Android 6.0.
Dispositivo virtual Android (AVD ) – Un dispositivo virtual Android es un dispositivo Android emulado
creado a partir de una imagen de emulador. Al ejecutar y probar aplicaciones Android, Xamarin.Android inicia
Android Emulator, inicia un AVD específico, instala el APK y luego ejecuta la aplicación.
Se puede lograr una mejora considerable del rendimiento al desarrollar en equipos basados en x86 mediante
imágenes de emulador especiales optimizadas para la arquitectura x86 y una de entre dos tecnologías de
virtualización:
1. Hyper-V de Microsoft: disponible en equipos con la actualización de abril de 2018 de Windows 10 o una
versión posterior.
2. Hardware Accelerated Execution Manager (HAXM ) de Intel: disponible en equipos x86 con OS X, macOS o
versiones anteriores de Windows.
Para obtener más información sobre Android Emulator, Hyper-V y HAXM, vea la guía Aceleración de hardware
para el rendimiento del emulador.

NOTE
En las versiones de Windows anteriores a la actualización de abril de 2018 de Windows 10, HAXM no es compatible con
Hyper-V. En este escenario es necesario deshabilitar Hyper-V o usar las imágenes de emulador más lentas sin las
optimizaciones de x86.

Dispositivo Android
Si dispone de un dispositivo Android físico para efectuar las pruebas, ahora es un buen momento para
configurarlo para su uso de desarrollo. Consulte Configurar el dispositivo para el desarrollo para configurar el
dispositivo Android para el desarrollo; luego, conéctelo al equipo para ejecutar y depurar aplicaciones de
Xamarin.Android.

Crear una aplicación


Ahora que ha instalado Xamarin.Android, puede iniciar Visual Studio para crear un proyecto. Haga clic en Archivo
> Nuevo > Proyecto para comenzar a crear la aplicación:

En el cuadro de diálogo Nuevo proyecto, seleccione Android en Plantillas y haga clic en Aplicación de
Android en el panel de la derecha. Escriba un nombre para la aplicación (en la siguiente captura de pantalla, la
aplicación se llama MyApp); luego, haga clic en Aceptar:
Ya está. Ahora ya puede usar Xamarin.Android para crear aplicaciones de Android.

Resumen
En este artículo ha aprendido a configurar e instalar la plataforma de Xamarin.Android en Windows, a configurar
(opcional) Visual Studio con ubicaciones de instalación personalizadas de Java JDK y del SDK de Android, a iniciar
SDK Manager para instalar componentes adicionales del SDK de Android, a configurar un emulador o dispositivo
de Android y a empezar a compilar su primera aplicación.
El siguiente paso consiste en echar un vistazo a los tutoriales de Hello, Android para aprender a crear una
aplicación operativa de Xamarin.Android.

Vínculos relacionados
Descarga de Visual Studio
Instalación de Visual Studio Tools para Xamarin
Requisitos del sistema
Configuración de Android SDK
Configuración de Android Emulator
Configurar el dispositivo para el desarrollo
Ejecutar aplicaciones en Android Emulator
Configuración del SDK de Android para
Xamarin.Android
30/07/2019 • 21 minutes to read • Edit Online

Visual Studio incluye Android SDK Manager, que puede usar para descargar herramientas de Android SDK,
plataformas y otros componentes necesarios para desarrollar aplicaciones de Xamarin.Android.

Información general
En esta guía se explica cómo usar Android SDK Manager de Xamarin en Visual Studio y Visual Studio para
Mac.

NOTE
Esta guía se aplica a Visual Studio 2019, Visual Studio 2017 y Visual Studio para Mac.

Android SDK Manager de Xamarin (instalado como parte de la carga de trabajo Desarrollo para
dispositivos móviles con .NET) ayuda a descargar los componentes de Android más recientes que se
necesitan para desarrollar la aplicación de Xamarin.Android. Reemplaza el SDK Manager independiente de
Google, que está en desuso.
Visual Studio
Visual Studio para Mac

Requisitos
Para usar Android SDK Manager de Xamarin, necesita lo siguiente:
Visual Studio 2019 Community, Professional o Enterprise.
O bien, Visual Studio 2017 (edición Community, Professional o Enterprise). Se necesita Visual Studio
2017 versión 15.7 o posterior.
Visual Studio Tools para Xamarin, versión 4.10.0 o posterior (instalada como parte de la carga de
trabajo Desarrollo para dispositivos móviles con .NET).
El Administrador de Android SDK de Xamarin también necesita disponer de Java Development Kit, que se
instala automáticamente con Xamarin.Android. Hay varias alternativas de JDK para elegir:
De forma predeterminada, Xamarin.Android usa JDK 8, necesario para el desarrollo en el nivel de API
24 o superior. JDK 8 también admite niveles de API anteriores al 24.
Si está desarrollando contenido específicamente para el nivel de API 23 o uno anterior, puede continuar
usando JDK 7.
Si usa Visual Studio 15.8, versión preliminar 5 o posterior, puede probar a usar la distribución
OpenJDK Mobile de Microsoft (actualmente en versión preliminar) en lugar de JDK 8.

IMPORTANT
Xamarin.Android no admite JDK 9.
SDK Manager
Para iniciar SDK Manager en Visual Studio, haga clic en Herramientas > Android > Android SDK
Manager:

Android SDK Manager se abre en la pantalla Herramientas y Android SDK. Esta pantalla tiene dos
pestañas: Plataformas y Herramientas:

La pantalla Herramientas y Android SDK se describe con más detalle en las secciones siguientes.
Ubicación de Android SDK
La ubicación de Android SDK está configurada en la parte superior de la pantalla Herramientas y Android
SDK, tal como se muestra en la imagen anterior. Esta ubicación se debe configurar correctamente para que las
pestañas Plataformas y Herramientas funcionen correctamente. Es posible que deba establecer la ubicación
de Android SDK por alguno de los motivos siguientes:
1. Android SDK Manager no pudo encontrar Android SDK.
2. Ha instalado Android SDK en una ubicación alternativa (no predeterminada).
Para establecer la ubicación de Android SDK, haga clic en el botón de puntos suspensivos (…) situado a la
derecha de Ubicación de Android SDK. Se abrirá el cuadro de diálogo Buscar carpeta, que usará para
navegar a la ubicación de Android SDK. En la siguiente captura de pantalla, está seleccionado Android SDK en
Archivos de programa (x86)\Android:
Al hacer clic en Aceptar, SDK Manager administrará el Android SDK instalado en la ubicación seleccionada.
Pestaña Herramientas
En la pestaña Herramientas se muestra una lista de herramientas y extras. Use esta pestaña para instalar las
herramientas de Android SDK, las herramientas de la plataforma y las herramientas de compilación. Además,
puede instalar Android Emulator, el depurador de bajo nivel (LLDB ), el NDK, la aceleración de HAXM y
bibliotecas de Google Play.
Por ejemplo, para descargar el paquete de Android Emulator de Google, haga clic en la marca de verificación
situada junto a Android Emulator y, después, haga clic en el botón Aplicar cambios:

Puede aparecer un diálogo con el mensaje El paquete siguiente requiere que acepte sus términos de licencia
antes de instalarlo:
Haga clic en Aceptar si está de acuerdo con los términos y condiciones. En la parte inferior de la ventana, una
barra de progreso indica el progreso de la descarga y la instalación. Una vez finalizada la instalación, en la
pestaña Herramientas se mostrará que se han instalado las herramientas y los extras seleccionados.
Pestaña Plataformas
En la pestaña Plataformas se muestra una lista de versiones del SDK de la plataforma junto con otros
recursos (por ejemplo, imágenes del sistema) para cada plataforma:

En esta pantalla se muestra la versión de Android (como Android 8.0), el nombre en código (Oreo), el nivel
de API (por ejemplo, 26) y el tamaño de los componentes de esa plataforma (como 1 GB ). Use la pestaña
Plataformas para instalar los componentes correspondientes al nivel de API de Android al que quiera
dirigirse. Para obtener más información sobre las versiones de Android y los niveles de API, vea Descripción
de los niveles de API de Android.
Si están instalados todos los componentes de una plataforma, aparece una marca de verificación junto al
nombre de la plataforma. Si no están instalados todos los componentes de una plataforma, se rellena el
cuadro de dicha plataforma. Puede expandir una plataforma para ver sus componentes (y los componentes
instalados). Para ello, haga en el cuadro + situado a la izquierda de la plataforma. Haga clic en - para contraer
la lista de componentes de una plataforma.
Para agregar otra plataforma al SDK, haga clic en el cuadro situado junto a la plataforma hasta que aparezca la
marca de verificación para instalar todos sus componentes. Después, haga clic en Aplicar cambios:

Para instalar solo componentes específicos, haga clic una vez en el cuadro situado junto a la plataforma.
Después, puede seleccionar los componentes individuales que necesite:
Observe que el número de componentes que se van a instalar aparece junto al botón Aplicar cambios. Tras
hacer clic en el botón Aplicar cambios, verá la pantalla Aceptación de licencia, tal como se muestra
anteriormente. Haga clic en Aceptar si está de acuerdo con los términos y condiciones. Es posible que vea
este cuadro de diálogo más de una vez si se van a instalar varios componentes. En la parte inferior de la
ventana, una barra de progreso indica el progreso de la descarga y la instalación. Cuando se complete el
proceso de descarga e instalación (puede tardar muchos minutos, en función de cuántos componentes deban
descargarse), los componentes agregados se marcarán con una marca de verificación y a su lado se indicará
Instalado.
Selección del repositorio
De forma predeterminada, Android SDK Manager descarga los componentes y las herramientas de la
plataforma desde un repositorio administrado por Microsoft. Si necesita acceso a las plataformas y
herramientas alfa/beta experimentales que todavía no están disponibles en el repositorio de Microsoft, puede
cambiar SDK Manager para que use el repositorio de Google. Para realizar este cambio, haga clic en el icono
de engranaje en la esquina inferior derecha y seleccione Repositorio > Google (no compatible) :

Al seleccionar el repositorio de Google, pueden aparecer paquetes adicionales en la pestaña Plataformas que
no estaban disponibles anteriormente. (En la captura de pantalla anterior, Android SDK Platform 28 se
agregó al cambiar al repositorio de Google.) Tenga en cuenta que el uso del repositorio de Google no es
dispone de soporte técnico y, por tanto, no se recomienda para el desarrollo habitual.
Para volver al repositorio compatible de plataformas y herramientas, haga clic en Microsoft (recomendado)
. Esto restaura la lista de paquetes y las herramientas a la selección predeterminada.

Resumen
En esta guía se explica cómo instalar y usar la herramienta Android SDK Manager de Xamarin en Visual
Studio y Visual Studio para Mac.

Vínculos relacionados
Descripción de los niveles de API de Android
Cambios en las Herramientas de Android SDK
Configuración de Android Emulator
11/07/2019 • 3 minutes to read • Edit Online

En esta guía se explica cómo preparar Android Emulator para probar la aplicación.

Información general
Android Emulator se puede ejecutar en varias configuraciones para simular múltiples dispositivos. Cada
configuración se denomina dispositivo virtual. Al implementar y probar la aplicación en el emulador, debe
seleccionar un dispositivo virtual preconfigurado o personalizado que simule un dispositivo Android físico, como
un teléfono Nexus o Pixel.
En las secciones siguientes se describe cómo acelerar Android Emulator para obtener el máximo rendimiento,
cómo usar Android Device Manager para crear y personalizar dispositivos virtuales y cómo personalizar las
propiedades de perfil de un dispositivo virtual. Además, en la sección de solución de problemas se explican los
problemas más habituales del emulador y sus soluciones.

Secciones
Aceleración de hardware para el rendimiento del emulador
Cómo preparar el equipo para obtener el máximo rendimiento de Android Emulator mediante la tecnología de
virtualización Hyper-V o HAXM. Dado que Android Emulator puede ser excesivamente lento sin la aceleración
de hardware, se recomienda habilitar la aceleración de hardware en el equipo antes de usarlo.
Administración de dispositivos virtuales con Android Device Manager
Describe cómo usar Android Device Manager para crear y personalizar dispositivos virtuales.
Editar las propiedades del dispositivo virtual Android
Describe cómo usar Android Device Manager para editar las propiedades de perfil de un dispositivo virtual.
Solución de problemas de Android Emulator
En este artículo se describen los mensajes de advertencia y los problemas más habituales que se producen al
ejecutar Android Emulator, así como sugerencias y soluciones.
Después de configurar Android Emulator, vea Depuración en Android Emulator para obtener información sobre
cómo iniciar el emulador y usarlo para probar y depurar la aplicación.

NOTE
A partir de la versión 26.0.1 de Android SDK Tools, Google ha quitado la compatibilidad con administradores de AVD/SDK
existentes en favor de las nuevas herramientas de la CLI (interfaz de la línea de comandos). Debido a este cambio de
degradación, ahora se usan administradores de SDK/dispositivos de Xamarin en lugar de administradores de
SDK/dispositivos de Google para las Herramientas de Android 26.0.1 y versiones posteriores. Para obtener más información
sobre Xamarin SDK Manager, vea Configuración del SDK de Android para Xamarin.Android.
Aceleración de hardware para el rendimiento del
emulador (Hyper-V y HAXM)
11/07/2019 • 15 minutes to read • Edit Online

En este artículo se explica cómo usar las características de aceleración de hardware del equipo para maximizar
el rendimiento de Android Emulator.
Visual Studio facilita a los desarrolladores la prueba y depuración de las aplicaciones Xamarin.Android mediante
el uso de Android Emulator en situaciones en las que un dispositivo Android no está disponible o no es práctico.
Aun así, Android Emulator se ejecuta demasiado despacio si la aceleración de hardware no está disponible en el
equipo que lo ejecuta. Es posible mejorar drásticamente el rendimiento de Android Emulator mediante el uso de
imágenes de dispositivo virtual x86 especiales junto con las características de virtualización del equipo.

Aceleración de Android Emulator en Windows


Las tecnologías de virtualización siguientes están disponibles para la aceleración de Android Emulator:
1. Hyper-V y Hypervisor Platform de Microsoft. Hyper-V es una característica de virtualización de
Windows que permite ejecutar sistemas de equipos virtualizados en un equipo host físico.
2. Hardware Accelerated Execution Manager (HAXM ) de Intel. HAXM es un motor de virtualización
para los equipos que ejecutan CPU de Intel.
Para obtener un rendimiento óptimo, se recomienda el uso de Hyper-V para la aceleración de Android Emulator.
Si Hyper-V no está disponible en el equipo, puede utilizarse HAXM. Android Emulator usará automáticamente
la aceleración de hardware si se cumplen los criterios siguientes:
La aceleración de hardware está disponible y habilitada en el equipo de desarrollo.
El emulador ejecuta una imagen del sistema creada para un dispositivo virtual basado en x86.

IMPORTANT
No se puede ejecutar un emulador acelerado por una máquina virtual dentro de otra, como sería el caso de una
hospedada en VirtualBox, VMWare o Docker. Es necesario ejecutar Android Emulator directamente en el hardware del
sistema.

Para obtener información sobre cómo iniciar y depurar con Android Emulator, vea Depuración en Android
Emulator.

Aceleración con Hyper-V


Hyper-V es la opción recomendada para la aceleración de Android Emulator. Antes de habilitar Hyper-V, lea la
sección siguiente para comprobar que su equipo es compatible con Hyper-V.
Comprobación de la compatibilidad con Hyper-V
Hyper-V se ejecuta en Windows Hypervisor Platform. Para usar Android Emulator con Hyper-V, el equipo debe
cumplir los siguientes criterios para admitir Windows Hypervisor Platform:
El hardware del equipo debe cumplir los siguientes requisitos:
Una CPU AMD Ryzen o Intel de 64 bits con SLAT (Traducción de direcciones de segundo nivel).
Compatibilidad de CPU para la extensión de modo de monitor de máquina virtual (VT-c en CPU de
Intel).
4 GB de memoria, como mínimo.
En el BIOS del equipo, deben habilitarse los siguientes elementos:
Tecnología de virtualización (puede tener otra denominación según el fabricante de la placa base).
Prevención de ejecución de datos forzada mediante hardware.
El equipo debe actualizarse a Windows 10, actualización de abril de 2018 (compilación 1803) o una
versión posterior. Puede comprobar que la versión de Windows está actualizada mediante los pasos
siguientes:
1. En el cuadro de búsqueda de Windows, escriba Acerca de.
2. Seleccione About your PC (Acerca del equipo) en los resultados de búsqueda.
3. Desplácese hacia abajo por el cuadro de diálogo Acerca de hasta la sección Especificaciones de
Windows.
4. Compruebe que el número de Versión es al menos 1803:

Para comprobar que el hardware y el software del equipo es compatible con Hyper-V, abra un símbolo del
sistema y escriba el comando siguiente:

systeminfo

Si todos los requisitos de Hyper-V enumerados tienen un valor de Sí, el equipo es compatible con Hyper-V. Por
ejemplo:

Habilitación de la aceleración de Hyper-V


Si el equipo cumple los criterios mencionados anteriormente, siga estos pasos para la aceleración de Android
Emulator con Hyper-V:
1. Escriba características de windows en el cuadro de búsqueda de Windows y seleccione Activar o
desactivar las características de Windows en los resultados de búsqueda. En el cuadro de diálogo
Características de Windows, habilite Hyper-V y Windows Hypervisor Platform:
Después de realizar estos cambios, reinicie el equipo.
2. Instale Visual Studio 15.8 o una versión posterior (esta versión de Visual Studio proporciona
compatibilidad con el IDE para ejecutar Android Emulator con Hyper-V ).
3. Instale el paquete 27.2.7 o posterior de Android Emulator. Para instalar este paquete, vaya a
Herramientas > Android > Android SDK Manager en Visual Studio. Seleccione la pestaña
Herramientas y asegúrese de que la versión de Android Emulator sea como mínimo la 27.2.7. Asegúrese
también de que la versión de Android SDK Tools sea la 26.1.1 o posterior:

Cuando cree un dispositivo virtual (consulte Administración de dispositivos virtuales con Android Device
Manager), no olvide seleccionar una imagen del sistema basada en x86. Si usa una imagen de sistema basada
en ARM, el dispositivo virtual no se acelerará y se ejecutará con lentitud.

Aceleración con HAXM


Utilice HAXM para la aceleración de Android Emulator si su equipo no es compatible con Hyper-V. Debe
deshabilitar Device Guard si desea usar HAXM.
Comprobación de la compatibilidad con HAXM
Para determinar si el hardware es compatible con HAXM, siga los pasos detallados en ¿Admite mi procesador la
Tecnología de virtualización Intel? . Si el hardware es compatible con HAXM, puede comprobar si HAXM ya está
instalado mediante los pasos siguientes:
1. Abra una ventana de símbolo de sistema y escriba el siguiente comando:

sc query intelhaxm

2. Examine la salida para ver si se está ejecutando el proceso de HAXM. Si es así, debería ver que la salida
indica el estado intelhaxm como RUNNING . Por ejemplo:

Si STATE no está establecido en RUNNING , HAXM no está instalado.

Si el equipo es compatible con HAXM pero HAXM no está instalado, siga los pasos de la sección siguiente para
instalar HAXM.
Instalación de HAXM
En la página de Intel Hardware Accelerated Execution Manager hay disponibles paquetes de instalación de
HAXM para Windows. Siga estos pasos para descargar e instalar HAXM:
1. En el sitio web de Intel, descargue la última versión del instalador del motor de virtualización de HAXM
para Windows. La ventaja de descargar el instalador de HAXM directamente desde el sitio web de Intel es
que se asegura de que esté usando la versión más reciente.
2. Ejecute intelhaxm -android.exe para iniciar el instalador de HAXM. Acepte los valores predeterminados
en los cuadros de diálogo del instalador:
Cuando cree un dispositivo virtual (consulte Administración de dispositivos virtuales con Android Device
Manager), no olvide seleccionar una imagen del sistema basada en x86. Si usa una imagen de sistema basada
en ARM, el dispositivo virtual no se acelerará y se ejecutará con lentitud.

Solución de problemas
Para obtener ayuda con la solución de problemas de aceleración de hardware, consulte la guía de solución de
problemas de Android Emulator.

Aceleración de Android Emulator en macOS


Las tecnologías de virtualización siguientes están disponibles para la aceleración de Android Emulator:
1. Plataforma Hypervisor de Apple. Hypervisor es una característica de macOS 10.10 y versiones
posteriores que permite ejecutar máquinas virtuales en un equipo Mac.
2. Hardware Accelerated Execution Manager (HAXM ) de Intel. HAXM es un motor de virtualización
para los equipos que ejecutan CPU de Intel.
Para obtener un rendimiento óptimo, se recomienda el uso de la plataforma Hypervisor para la aceleración de
Android Emulator. Si la plataforma Hypervisor no está disponible en el equipo Mac, se puede usar HAXM.
Android Emulator usará automáticamente la aceleración de hardware si se cumplen los criterios siguientes:
La aceleración de hardware está disponible y habilitada en el equipo de desarrollo.
El emulador ejecuta una imagen del sistema creada para un dispositivo virtual basado en x86.

IMPORTANT
No se puede ejecutar un emulador acelerado por una máquina virtual dentro de otra, como sería el caso de una
hospedada en VirtualBox, VMware o Docker. Es necesario ejecutar Android Emulator directamente en el hardware del
sistema.

Para obtener información sobre cómo iniciar y depurar con Android Emulator, vea Depuración en Android
Emulator.

Aceleración con la plataforma Hypervisor


Para usar Android Emulator con la plataforma Hypervisor, el equipo Mac debe cumplir los siguientes criterios:
El equipo Mac debe ejecutar macOS 10.10 o versiones posteriores.
La CPU del equipo Mac debe ser compatible con la plataforma Hypervisor.
Si el equipo Mac cumple estos criterios, Android Emulator usará automáticamente la plataforma Hypervisor
para la aceleración (incluso si HAXM está instalado). Si no está seguro de si el equipo Mac admite la plataforma
Hypervisor, consulte en la guía de solución de problemas las distintas formas de comprobar que el equipo Mac
es compatible con Hypervisor.
Si el equipo Mac no admite la plataforma Hypervisor, puede usar HAXM para la aceleración de Android
Emulator (el proceso se describe a continuación).

Aceleración con HAXM


Si el equipo Mac no admite la plataforma Hypervisor (o si usa una versión de macOS anterior a la 10.10), puede
usar Hardware Accelerated Execution Manager (HAXM ) de Intel para la aceleración de Android Emulator.
Antes de usar Android Emulator con HAXM por primera vez, conviene comprobar que HAXM esté instalado y
disponible para Android Emulator.
Comprobación de la compatibilidad con HAXM
Puede comprobar si HAXM ya está instalado mediante los pasos siguientes:
1. Abra una sesión de Terminal y escriba el siguiente comando:

~/Library/Developer/Xamarin/android-sdk-macosx/tools/emulator -accel-check

Este comando asume que Android SDK está instalado en la ubicación predeterminada:
~/Biblioteca/Desarrollador/Xamarin/android-sdk-macosx; de lo contrario, modifique la ruta de
acceso anterior para que sea la ubicación del SDK de Android en el equipo Mac.
2. Si HAXM está instalado, el comando anterior devolverá un mensaje similar al siguiente resultado:

HAXM version 7.2.0 (3) is installed and usable.

Si HAXM no está instalado, se devuelve un mensaje similar a la salida siguiente:

HAXM is not installed on this machine (/dev/HAX is missing).

Si HAXM no está instalado, siga los pasos de la sección siguiente para instalar HAXM.
Instalación de HAXM
En la página de Intel Hardware Accelerated Execution Manager hay disponibles paquetes de instalación de
HAXM para macOS. Siga estos pasos para descargar e instalar HAXM:
1. En el sitio web de Intel, descargue la última versión del instalador del motor de virtualización de HAXM
para macOS.
2. Ejecute el instalador de HAXM. Acepte los valores predeterminados en los cuadros de diálogo del
instalador:
Solución de problemas
Para obtener ayuda con la solución de problemas de aceleración de hardware, consulte la guía de solución de
problemas de Android Emulator.

Vínculos relacionados
Ejecutar aplicaciones en Android Emulator
Administración de dispositivos virtuales con
Android Device Manager
11/07/2019 • 30 minutes to read • Edit Online

En este artículo se explica cómo usar Android Device Manager para crear y configurar dispositivos virtuales
Android (AVD ) que emulen dispositivos Android físicos. Puede usar estos dispositivos virtuales para ejecutar y
probar la aplicación sin tener que depender de un dispositivo físico.
Después de comprobar que la aceleración de hardware está habilitada (como se explica en Aceleración de
hardware para el rendimiento del emulador), el siguiente paso es usar Android Device Manager (también
denominado Xamarin Android Device Manager) para crear dispositivos virtuales que se puedan usar para
probar y depurar la aplicación.

Android Device Manager en Windows


En este artículo se explica cómo se usa Android Device Manager para crear, duplicar, personalizar e iniciar
dispositivos virtuales Android.

Android Device Manager se usa para crear y configurar dispositivos virtuales Android (AVD ) que se ejecutan
en Android Emulator. Cada AVD es una configuración del emulador que simula un dispositivo Android físico.
Esto permite ejecutar y probar la aplicación en diversas configuraciones que simulan diferentes dispositivos
Android físicos.

Requisitos
Para usar Android Device Manager, necesita los siguiente elementos:
Visual Studio 2019 Community, Professional o Enterprise.
O bien, se necesita Visual Studio 2017 versión 15.8 o posterior. Se admiten las ediciones Community,
Professional y Enterprise de Visual Studio.
Visual Studio Tools para Xamarin versión 4.9 o posterior.
Debe estar instalado Android SDK (consulte Configuración de Android SDK para Xamarin.Android).
Asegúrese de instalar Android SDK en la ubicación predeterminada (si todavía no lo está): C:\Archivos
de programa (x86)\Android\android-sdk.
Es necesario instalar los siguientes paquetes (a través de Android SDK Manager):
Android SDK Tools versión 26.1.1 o posterior
Herramientas de plataforma de Android SDK 27.0.1 o posterior
Herramientas de compilación de Android SDK 27.0.3 o posterior
Android Emulator 27.2.7 o posterior.
Estos paquetes deberían mostrarse con el estado Instalado, como se muestra en la captura de pantalla
siguiente:

Iniciar el Administrador de dispositivos


Inicie Android Device Manager desde el menú Herramientas. Para ello, haga clic en Herramientas >
Android > Android Device Manager:

Si aparece el siguiente cuadro de diálogo de error al inicio, consulte la sección Solución de problemas para
obtener soluciones alternativas:
Pantalla principal
Cuando inicie el Administrador de dispositivos Android por primera vez, aparecerá una pantalla con todos los
dispositivos virtuales configurados. Para cada dispositivo virtual, se muestran el nombre, el SO (versión de
Android), el procesador, el tamaño de memoria y la resolución de pantalla:

Al seleccionar un dispositivo de la lista, aparece el botón Iniciar a la derecha. Puede hacer clic en el botón
Iniciar para iniciar el emulador con este dispositivo virtual:

Una vez que el emulador se haya iniciado con el dispositivo virtual seleccionado, el botón Iniciar cambiará al
botón Detener, que puede usar para detener el emulador:
Dispositivo nuevo
Para crear un dispositivo, haga clic en el botón Nuevo (situado en la parte superior derecha de la pantalla):

Al hacer clic en Nuevo, aparece la pantalla Nuevo dispositivo:

Para configurar un nuevo dispositivo en la pantalla Nuevo dispositivo, siga estos pasos:
1. Asigne un nuevo nombre al dispositivo. En el ejemplo siguiente, el nuevo dispositivo se denomina
Pixel_API_27:
2. Seleccione el dispositivo físico que quiera emular; para ello, haga clic en el menú desplegable
Dispositivo base:

3. Seleccione un tipo de procesador para este dispositivo virtual; para ello, haga clic en el menú
desplegable Procesador. Si selecciona x86, se proporcionará el mejor rendimiento porque permite que
el emulador aproveche las ventajas de la aceleración de hardware. La opción x86_64 también usará la
aceleración de hardware, pero la ejecución es un poco más lenta que x86 (x86_64 se suele usar para
probar aplicaciones de 64 bits):

4. Seleccione la versión de Android (nivel de API); para ello, haga clic en el menú desplegable SO. Por
ejemplo, seleccione Oreo 8.1 - API 27 para crear un dispositivo virtual de nivel de API 27:
Si selecciona un nivel de API de Android que aún no se ha instalado, Device Manager mostrará el
mensaje A new device will be downloaded (Se descargará un nuevo dispositivo) en la parte inferior
de la pantalla y descargará e instalará los archivos necesarios, además de crear el dispositivo virtual:

5. Si quiere incluir las API de Google Play Services en el dispositivo virtual, habilite la opción Google
APIs (API de Google). Para incluir la aplicación de Google Play Store, habilite la opción Google Play
Store:

Tenga en cuenta que las imágenes de Google Play Store solo están disponibles para algunos tipos de
dispositivos base como Pixel, Pixel 2, Nexus 5 y Nexus 5X.
6. Edite las propiedades que necesite modificar. Para realizar cambios en las propiedades, vea Editing
Android Virtual Device Properties (Editar propiedades de dispositivos virtuales Android).
7. Agregue las propiedades adicionales que necesite establecer explícitamente. En la pantalla Nuevo
dispositivo solo se muestran las propiedades que se modifican con más frecuencia, pero puede hacer
clic en el menú desplegable Agregar propiedad (en la parte inferior) para agregar propiedades
adicionales:
También puede definir una propiedad personalizada si selecciona Personalizado... en la parte superior
de la lista de propiedades.
8. Haga clic en el botón Crear (esquina inferior derecha) para crear el dispositivo:

9. Es posible que aparezca la pantalla Aceptación de licencia. Haga clic en Aceptar si está de acuerdo
con los términos de licencia:

10. Android Device Manager agrega el nuevo dispositivo a la lista de dispositivos virtuales instalados, con
el indicador de progreso Creando mientras crea el dispositivo:
11. Una vez finalizado el proceso de creación, el nuevo dispositivo se muestra en la lista de dispositivos
virtuales instalados con el botón Iniciar, listo para su inicio:

Editar dispositivo
Para editar un dispositivo virtual existente, selecciónelo y haga clic en el botón Editar (situado en la esquina
superior derecha de la pantalla):

Al hacer clic en Editar, se inicia el editor de dispositivos para el dispositivo virtual seleccionado:

En la pantalla del editor de dispositivos se muestran las propiedades del dispositivo virtual en la columna
Propiedad, con los valores correspondientes de cada propiedad en la columna Valor. Cuando se selecciona
una propiedad, aparece una descripción detallada de dicha propiedad a la derecha.
Para cambiar una propiedad, edite su valor en la columna Valor. Por ejemplo, en la siguiente captura de
pantalla, la propiedad hw.lcd.density se cambia de 480 a 240:
Después de realizar los cambios de configuración necesarios, haga clic en el botón Guardar. Para obtener más
información sobre cómo cambiar las propiedades del dispositivo virtual, vea Editing Android Virtual Device
Properties (Editar propiedades de dispositivos virtuales Android).
Opciones adicionales
En el menú desplegable Opciones adicionales (…) que está situado en la esquina superior derecha, hay
opciones adicionales para trabajar con dispositivos:

El menú de opciones adicionales contiene los elementos siguientes:


Duplicate and Edit (Duplicar y editar): duplica el dispositivo seleccionado actualmente y lo abre en la
pantalla Nuevo dispositivo con otro nombre exclusivo. Por ejemplo, al seleccionar Pixel_API_27 y
hacer clic en Duplicar y editar, se anexa un contador al nombre:
Mostrar en el Explorador: se abre una ventana del Explorador de Windows en la carpeta que contiene
los archivos del dispositivo virtual. Por ejemplo, al seleccionar Pixel_API_27 y hacer clic en Mostrar en
el Explorador, se abre una ventana como en el ejemplo siguiente:

Restablecimiento de fábrica: restablece el dispositivo seleccionado a sus valores predeterminados,


para lo cual borra los cambios de usuario realizados en el estado interno del dispositivo mientras estaba
en ejecución (esto también borra la captura de pantalla Arranque rápido actual, si existe). Este cambio
no altera las modificaciones que realice en el dispositivo virtual durante la creación y la edición.
Aparecerá un cuadro de diálogo que le recordará que este restablecimiento no se puede deshacer. Haga
clic en Restablecimiento de fábrica para confirmar el restablecimiento:

Eliminar: elimina de forma permanente el dispositivo virtual seleccionado. Aparecerá un cuadro de


diálogo que le recordará que la eliminación de un dispositivo no se puede deshacer. Haga clic en
Eliminar si está seguro de que quiere eliminar el dispositivo.
Android Device Manager en macOS
En este artículo se explica cómo se usa Android Device Manager para crear, duplicar, personalizar e iniciar
dispositivos virtuales Android.

NOTE
Esta guía solo se aplica a Visual Studio para Mac. Xamarin Studio no es compatible con Android Device Manager.

Android Device Manager se usa para crear y configurar dispositivos virtuales Android (AVD ) que se ejecutan
en Android Emulator. Cada AVD es una configuración del emulador que simula un dispositivo Android físico.
Esto permite ejecutar y probar la aplicación en diversas configuraciones que simulan diferentes dispositivos
Android físicos.

Requisitos
Para usar Android Device Manager, necesita los siguiente elementos:
Visual Studio para Mac 7.6 o posterior.
Debe estar instalado Android SDK (consulte Configuración de Android SDK para Xamarin.Android).
Es necesario instalar los siguientes paquetes (a través de Android SDK Manager):
SDK Tools versión 26.1.1 o posterior
Herramientas de plataforma de Android SDK 28.0.1 o posterior
Herramientas de compilación de Android SDK 26.0.3 o posterior
Estos paquetes deberían mostrarse con el estado Instalado, como se muestra en la captura de pantalla
siguiente:

Iniciar el Administrador de dispositivos


Para iniciar Android Device Manager, haga clic en Herramientas > Device Manager:

Si aparece el siguiente cuadro de diálogo de error al inicio, consulte la sección Solución de problemas para
obtener soluciones alternativas:
Pantalla principal
Cuando inicie el Administrador de dispositivos Android por primera vez, aparecerá una pantalla con todos los
dispositivos virtuales configurados. Para cada dispositivo virtual, se muestran el nombre, el SO (versión de
Android), el procesador, el tamaño de memoria y la resolución de pantalla:

Al seleccionar un dispositivo de la lista, aparece el botón Reproducir a la derecha. Puede hacer clic en el botón
Reproducir para iniciar el emulador con este dispositivo virtual:
Una vez que el emulador se haya iniciado con el dispositivo virtual seleccionado, el botón Reproducir
cambiará al botón Detener, que puede usar para detener el emulador:

Al detener el emulador, puede que aparezca un aviso en el que se le pregunta si quiere guardar el estado actual
para el siguiente arranque rápido:

Si guarda el estado actual, el emulador se iniciará con mayor rapidez cuando este dispositivo virtual se vuelva
a iniciar. Para obtener más información sobre el inicio rápido, consulte Arranque rápido.
Dispositivo nuevo
Para crear un dispositivo, haga clic en el botón Nuevo dispositivo (situado en la parte superior izquierda de
la pantalla):
Al hacer clic en Nuevo dispositivo, aparece la pantalla Nuevo dispositivo:

Siga estos pasos para configurar un nuevo dispositivo en la pantalla Nuevo dispositivo:
1. Asigne un nuevo nombre al dispositivo. En el ejemplo siguiente, el nuevo dispositivo se denomina
Pixel_API_27:
2. Seleccione el dispositivo físico que quiera emular; para ello, haga clic en el menú desplegable
Dispositivo base:

3. Seleccione un tipo de procesador para este dispositivo virtual; para ello, haga clic en el menú
desplegable Procesador. Si selecciona x86, se proporcionará el mejor rendimiento porque permite que
el emulador aproveche las ventajas de la aceleración de hardware. La opción x86_64 también usará la
aceleración de hardware, pero la ejecución es un poco más lenta que x86 (x86_64 se suele usar para
probar aplicaciones de 64 bits):
4. Seleccione la versión de Android (nivel de API); para ello, haga clic en el menú desplegable SO. Por
ejemplo, seleccione Oreo 8.1 - API 27 para crear un dispositivo virtual de nivel de API 27:

Si selecciona un nivel de API de Android que aún no se ha instalado, Device Manager mostrará el
mensaje A new device will be downloaded (Se descargará un nuevo dispositivo) en la parte inferior
de la pantalla y descargará e instalará los archivos necesarios, además de crear el dispositivo virtual:

5. Si quiere incluir las API de Google Play Services en el dispositivo virtual, habilite la opción Google
APIs (API de Google). Para incluir la aplicación de Google Play Store, habilite la opción Google Play
Store:

Tenga en cuenta que las imágenes de Google Play Store solo están disponibles para algunos tipos de
dispositivos base como Pixel, Pixel 2, Nexus 5 y Nexus 5X.
6. Edite las propiedades que necesite modificar. Para realizar cambios en las propiedades, vea Editing
Android Virtual Device Properties (Editar propiedades de dispositivos virtuales Android).
7. Agregue las propiedades adicionales que necesite establecer explícitamente. En la pantalla Nuevo
dispositivo solo se muestran las propiedades que se modifican con más frecuencia, pero puede hacer
clic en el menú desplegable Agregar propiedad (en la parte inferior) para agregar propiedades
adicionales:

También puede definir una propiedad personalizada si hace clic en Personalizado... en la parte
superior de esta lista de propiedades.
8. Haga clic en el botón Crear (esquina inferior derecha) para crear el dispositivo:

9. Android Device Manager agrega el nuevo dispositivo a la lista de dispositivos virtuales instalados, con
el indicador de progreso Creando mientras crea el dispositivo:

10. Una vez finalizado el proceso de creación, el nuevo dispositivo se muestra en la lista de dispositivos
virtuales instalados con el botón Iniciar, listo para su inicio:
Editar dispositivo
Para editar un dispositivo virtual existente, seleccione el menú desplegable Opciones adicionales (icono de
engranaje) y haga clic en Editar:

Al hacer clic en Editar, se inicia el editor de dispositivos para el dispositivo virtual seleccionado:
En la pantalla del editor de dispositivos se muestran las propiedades del dispositivo virtual en la columna
Propiedad, con los valores correspondientes de cada propiedad en la columna Valor. Cuando se selecciona
una propiedad, aparece una descripción detallada de dicha propiedad a la derecha.
Para cambiar una propiedad, edite su valor en la columna Valor. Por ejemplo, en la siguiente captura de
pantalla, la propiedad hw.lcd.density se cambia de 480 a 240:

Después de realizar los cambios de configuración necesarios, haga clic en el botón Guardar. Para obtener más
información sobre cómo cambiar las propiedades del dispositivo virtual, vea Editing Android Virtual Device
Properties (Editar propiedades de dispositivos virtuales Android).
Opciones adicionales
En el menú desplegable situado a la izquierda del botón Reproducir hay opciones adicionales para trabajar
con dispositivos:
El menú de opciones adicionales contiene los elementos siguientes:
Editar: abre el dispositivo seleccionado actualmente en el editor de dispositivos, tal como se ha descrito
anteriormente.
Duplicate and Edit (Duplicar y editar): duplica el dispositivo seleccionado actualmente y lo abre en la
pantalla Nuevo dispositivo con otro nombre exclusivo. Por ejemplo, al seleccionar Pixel 2 API 28 y
hacer clic en Duplicar y editar, se anexa un contador al nombre:

Mostrar en Finder: se abre una ventana del Finder de macOS en la carpeta que contiene los archivos
del dispositivo virtual. Por ejemplo, al seleccionar Pixel 2 API 28 y hacer clic en Mostrar en Finder, se
abre una ventana como en el ejemplo siguiente:
Restablecimiento de fábrica: restablece el dispositivo seleccionado a sus valores predeterminados,
para lo cual borra los cambios de usuario realizados en el estado interno del dispositivo mientras estaba
en ejecución (esto también borra la captura de pantalla Arranque rápido actual, si existe). Este cambio
no altera las modificaciones que realice en el dispositivo virtual durante la creación y la edición.
Aparecerá un cuadro de diálogo que le recordará que este restablecimiento no se puede deshacer. Haga
clic en Restablecimiento de fábrica para confirmar el restablecimiento.

Eliminar: elimina de forma permanente el dispositivo virtual seleccionado. Aparecerá un cuadro de


diálogo que le recordará que la eliminación de un dispositivo no se puede deshacer. Haga clic en
Eliminar si está seguro de que quiere eliminar el dispositivo.

Solución de problemas
En las secciones siguientes se explica cómo diagnosticar y solucionar los problemas que pueden producirse al
usar Android Device Manager para configurar dispositivos virtuales.
Visual Studio
Visual Studio para Mac
Android SDK en ubicación no estándar
Normalmente, Android SDK se instala en la siguiente ubicación:
C:\Archivos de programa (x86)\Android\android-sdk
Si el SDK no está instalado en esta ubicación, puede obtener este error al iniciar Android Device Manager:

Para evitar este problema, siga estos pasos:


1. En el escritorio de Windows, vaya a C:\Usuarios\nombre de
usuario\AppData\Roaming\XamarinDeviceManager:

2. Haga doble clic para abrir uno de los archivos de registro y busque la ruta de acceso del archivo de
configuración. Por ejemplo:

3. Vaya a esta ubicación y haga doble clic en user.config para abrirlo.


4. En user.config, busque el elemento <UserSettings> y agréguele un atributo AndroidSdkPath.
Establezca este atributo en la ruta de acceso en la que está instalado Android SDK en el equipo y guarde
el archivo. Por ejemplo, <UserSettings> tendrá el aspecto siguiente si Android SDK se ha instalado en
C:\Programas\Android\SDK:

<UserSettings SdkLibLastWriteTimeUtcTicks="636409365200000000" AndroidSdkPath="C:ProgramsAndroidSDK"


/>

Después de realizar este cambio en user.config, podrá iniciar Android Device Manager.
Versión incorrecta de Android SDK Tools
Si no está instalado, podría ver este cuadro de diálogo de error en el inicio:

Si ve este cuadro de diálogo de error, haga clic en Abrir SDK Manager para abrir Android SDK Manager. En
Android SDK Manager, haga clic en la pestaña Herramientas e instale los siguientes paquetes:
Android SDK Tools 26.1.1 o posterior
Herramientas de plataforma de Android SDK 27.0.1 o posterior
Herramientas de compilación de Android SDK 27.0.3 o posterior
La instantánea deshabilita la conexión WiFi en Android Oreo
Si tiene un AVD configurado para Android Oreo con acceso Wi-Fi simulado, el reinicio del AVD después de
una instantánea puede provocar la deshabilitación del acceso Wi-Fi.
Para evitar este problema:
1. Seleccione el AVD en Android Device Manager.
2. En el menú de opciones adicionales, haga clic en Mostrar en el Explorador.
3. Vaya a snapshots > default_boot.
4. Elimine el archivo snapshot.pb:

5. Reinicie el AVD.
Una vez realizados estos cambios, se reiniciará el AVD en un estado que permita que la conexión Wi-Fi vuelva
a funcionar.
Generación de informes de errores
Visual Studio
Visual Studio para Mac
Si encuentra algún problema con Android Device Manager que no pueda resolver con los pasos anteriores
para solucionar problemas, informe del error. Para ello, haga clic con el botón derecho en la barra del título y
seleccione Generate Bug Report (Generar informe de errores):
Resumen
En esta guía se presenta la versión de Android Device Manager disponible en Visual Studio Tools para
Xamarin y Visual Studio para Mac. Se explican características esenciales, como iniciar y detener el emulador de
Android, seleccionar un dispositivo virtual Android (AVD ) para su ejecución, crear dispositivos virtuales y
editar un dispositivo virtual. Se explica cómo editar propiedades de hardware de generación de perfiles para
aumentar la personalización, y se proporcionan sugerencias para solucionar problemas comunes.

Vínculos relacionados
Cambios en las Herramientas de Android SDK
Depuración en Android Emulator
Notas de la versión de SDK Tools (Google)
avdmanager
sdkmanager

Vídeo relacionado

Encuentre más vídeos de Xamarin en Channel 9 y YouTube.


Editar las propiedades del dispositivo virtual
Android
11/07/2019 • 34 minutes to read • Edit Online

En este artículo se describe cómo usar Android Device Manager para editar las propiedades de perfil de un
dispositivo virtual Android.

Android Device Manager en Windows


Android Device Manager es compatible con la edición de propiedades de perfil de dispositivos virtuales
Android individuales. En las pantallas Nuevo dispositivo y Edición de dispositivos se muestran las
propiedades del dispositivo virtual en la primera columna, con los valores correspondientes de cada propiedad
en la segunda columna (como se ve en este ejemplo):

Cuando se selecciona una propiedad, aparece una descripción detallada de dicha propiedad a la derecha. Puede
modificar las propiedades de perfil de hardware y las propiedades de AVD. Las propiedades de perfil de
hardware (como hw.ramSize y hw.accelerometer ) describen las características físicas del dispositivo emulado.
Estas características incluyen el tamaño de pantalla, la cantidad de memoria RAM disponible y si hay un
acelerómetro o no. Las propiedades de AVD especifican el funcionamiento del AVD durante su ejecución. Por
ejemplo, se pueden configurar las propiedades de AVD para especificar la forma en que el AVD usa la tarjeta
gráfica del equipo de desarrollo para la representación.
Puede cambiar las propiedades de la manera siguiente:
Para cambiar una propiedad booleana, haga clic en la marca de verificación situada a la derecha de la
propiedad booleana:
Para cambiar una propiedad enum (enumerada), haga clic en la flecha abajo situada a la derecha de la
propiedad y seleccione un nuevo valor.

Para cambiar una propiedad de cadena o entero, haga doble clic en la configuración actual de la cadena o
del entero en la columna de valor y especifique un nuevo valor.

Android Device Manager en macOS


Android Device Manager es compatible con la edición de propiedades de perfil de dispositivos virtuales
Android individuales. En las pantallas Nuevo dispositivo y Edición de dispositivos se muestran las
propiedades del dispositivo virtual en la primera columna, con los valores correspondientes de cada propiedad
en la segunda columna (como se ve en este ejemplo):

Cuando se selecciona una propiedad, aparece una descripción detallada de dicha propiedad a la derecha. Puede
modificar las propiedades de perfil de hardware y las propiedades de AVD. Las propiedades de perfil de
hardware (como hw.ramSize y hw.accelerometer ) describen las características físicas del dispositivo emulado.
Estas características incluyen el tamaño de pantalla, la cantidad de memoria RAM disponible y si hay un
acelerómetro o no. Las propiedades de AVD especifican el funcionamiento del AVD durante su ejecución. Por
ejemplo, se pueden configurar las propiedades de AVD para especificar la forma en que el AVD usa la tarjeta
gráfica del equipo de desarrollo para la representación.
Puede cambiar las propiedades de la manera siguiente:
Para cambiar una propiedad booleana, haga clic en la marca de verificación situada a la derecha de la
propiedad booleana:

Para cambiar una propiedad enum (enumerada), haga clic en el menú desplegable situado a la derecha de
la propiedad y seleccione un nuevo valor.

Para cambiar una propiedad de cadena o entero, haga doble clic en la configuración actual de la cadena o
del entero en la columna de valor y especifique un nuevo valor.

En la tabla siguiente se proporciona una explicación detallada de las propiedades enumeradas en las pantallas
Nuevo dispositivo y Edición de dispositivos:

PROPIEDAD. DESCRIPCIÓN OPCIONES

abi.type Tipo de ABI– especifica el tipo de ABI x86, x86_64, armeabi-v7a, arm64-v8a
(interfaz binaria de aplicaciones) del
dispositivo emulado. La opción x86 es
para el conjunto de instrucciones que
suele denominarse "x86" o "IA-32". La
opción x86_64 es para el conjunto de
instrucciones x86 de 64 bits. La opción
armeabi-v7a es para el conjunto de
instrucciones de ARM con extensiones
de ARM v7-a. La opción arm64 v8a es
para el conjunto de instrucciones de
ARM que admite AArch64.

disk.cachePartition Partición de caché– determina si el sí, no


dispositivo emulado usará una
partición /caché en el dispositivo. La
partición /caché (que inicialmente está
vacía) es la ubicación donde Android
almacena datos de acceso frecuente y
componentes de aplicación. Si se
establece en no, el emulador no usará
una partición /cache y se omitirán los
demás valores de disk.cache .
PROPIEDAD. DESCRIPCIÓN OPCIONES

disk.cachePartition.path Ruta de acceso de la partición de


caché– especifica un archivo de
imagen de la partición de caché en el
equipo de desarrollo. El emulador
usará este archivo para la partición
/caché. Escriba una ruta de acceso
absoluta o una ruta de acceso relativa
al directorio data del emulador. Si no se
establece, el emulador crea un archivo
temporal vacío denominado
cache.img en el equipo de desarrollo.
Si el archivo no existe, se crea como un
archivo vacío. Esta opción se omite si
disk.cachePartition está
establecido en no.

disk.cachePartition.size Tamaño de la partición de caché– el


tamaño del archivo de partición de
caché (en megabytes). Normalmente
no es necesario establecer esta opción,
a menos que la aplicación vaya a
descargar archivos mayores que el
tamaño de caché predeterminado, de
66 megabytes. Esta opción se omite si
disk.cachePartition está
establecido en no. Si el valor es un
entero, se especifica el tamaño en
bytes. También se puede especificar el
tamaño en kilobytes, megabytes y
gigabytes. Para ello, anexe K, M o G al
valor. El tamaño mínimo es 9 M y el
tamaño máximo es 1023 G.

disk.dataPartition.initPath Ruta de acceso inicial a la partición


de datos– especifica el contenido
inicial de la partición de datos. Después
de borrar datos de usuario, el
emulador copia el contenido del
archivo especificado en los datos de
usuario (de forma predeterminada,
userdata-qemu.img) en lugar de usar
userdata.img como versión inicial.
PROPIEDAD. DESCRIPCIÓN OPCIONES

disk.dataPartition.path Ruta de acceso a la partición de


datos– especifica el archivo de
partición de datos de usuario. Para
configurar un archivo de datos de
usuario persistentes, escriba un
nombre de archivo y una ruta de
acceso en el equipo de desarrollo. Si el
archivo no existe, el emulador crea una
imagen a partir del archivo
predeterminado userdata.img, lo
almacena en el nombre de archivo
especificado por
disk.dataPartition.path y
conserva los datos de usuario en él
cuando el emulador se cierra. Si no se
especifica una ruta de acceso, el
archivo predeterminado se denomina
userdata-qemu.img. El valor especial
<temp> hace que el emulador cree y
use un archivo temporal. Si se
establece
disk.dataPartition.initPath , se
copia el contenido en el archivo
disk.dataPartition.path en tiempo
de arranque. Tenga en cuenta que esta
opción no puede dejarse en blanco.

disk.dataPartition.size Tamaño de la partición de datos–


especifica el tamaño de la partición de
datos de usuario en bytes. Si el valor es
un entero, se especifica el tamaño en
bytes. También se puede especificar el
tamaño en kilobytes, megabytes y
gigabytes. Para ello, anexe K, M o G al
valor. El tamaño mínimo es 9 M y el
tamaño máximo es 1023 G.

disk.ramdisk.path Ruta de acceso de disco RAM– ruta


de acceso a la imagen de la partición
de arranque (de disco RAM). La imagen
de disco RAM es un subconjunto de la
imagen del sistema que el kernel carga
antes de que se monte la imagen del
sistema. La imagen de disco RAM suele
contener archivos binarios de tiempo
de arranque y scripts de inicialización.
Si no se especifica esta opción, el valor
predeterminado es ramdisk.img en el
directorio del sistema del emulador.
PROPIEDAD. DESCRIPCIÓN OPCIONES

disk.snapStorage.path Ruta de acceso de almacenamiento


de instantáneas– ruta de acceso al
archivo de almacenamiento de
instantáneas donde se almacenan
todas las instantáneas. En este archivo
se guardarán todas las instantáneas
realizadas durante la ejecución.
Únicamente se pueden restaurar
durante la ejecución del emulador las
instantáneas guardadas en este
archivo. Si no se especifica esta opción,
el valor predeterminado es
snapshots.img en el directorio de datos
del emulador.

disk.systemPartition.initPath Ruta de acceso init a la partición


del sistema– ruta de acceso a la copia
de solo lectura del archivo de imagen
del sistema; en concreto, la partición
que contiene las bibliotecas del sistema
y los datos correspondientes al nivel de
API y cualquier variante. Si no se
especifica esta ruta de acceso, el valor
predeterminado es system.img en el
directorio del sistema del emulador.

disk.systemPartition.path Ruta de acceso a la partición del


sistema– ruta de acceso a la imagen
de la partición del sistema de
lectura/escritura. Si no se establece
esta ruta de acceso, se crea un archivo
temporal y se inicializa con el
contenido del archivo especificado por
disk.systemPartition.initPath .

disk.systemPartition.size Tamaño de la partición del sistema–


tamaño ideal de la partición del
sistema (en megabytes). El tamaño se
omite si la imagen de la partición del
sistema real es mayor que esta
configuración; en caso contrario, se
especifica el tamaño máximo que
puede alcanzar el archivo de partición
del sistema. Si el valor es un entero, se
especifica el tamaño en bytes. También
se puede especificar el tamaño en
kilobytes, megabytes y gigabytes. Para
ello, anexe K, M o G al valor. El tamaño
mínimo es 9 M y el tamaño máximo es
1023 G.
PROPIEDAD. DESCRIPCIÓN OPCIONES

hw.accelerometer Acelerómetro– determina si el sí, no


dispositivo emulado contiene un
sensor de acelerómetro. El
acelerómetro ayuda al dispositivo a
determinar orientación (usada para el
giro automático). El acelerómetro
informa de la aceleración del
dispositivo a través de tres ejes de
sensor.

hw.audioInput Compatibilidad con la grabación sí, no


de audio– determina si el dispositivo
emulado puede grabar audio.

hw.audioOutput Compatibilidad con la sí, no


reproducción de audio– determina si
el dispositivo emulado puede
reproducir audio.

hw.battery Compatibilidad con batería– sí, no


determina si el dispositivo emulado
puede ejecutarse con batería.

hw.camera Compatibilidad con cámara– sí, no


determina si el dispositivo emulado
tiene una cámara.

hw.camera.back Cámara trasera– configura la cámara emulado, ninguno, webcam0


trasera (la lente deja de enfocar al
usuario). Si usa una cámara web en el
equipo de desarrollo para simular la
cámara trasera del dispositivo
emulado, este valor debe establecerse
en webcamn, donde n selecciona la
cámara web (si solo tiene una,
seleccione webcam0). Si se establece
en emulado, el emulador simula la
cámara a través de software. Para
deshabilitar la cámara trasera,
establezca este valor en ninguno. Si
habilita la cámara trasera, asegúrese de
habilitar también hw.camera .

hw.camera.front Cámara frontal– configura la cámara emulado, ninguno, webcam0


frontal (la lente enfoca al usuario). Si
usa una cámara web en el equipo de
desarrollo para simular la cámara
frontal del dispositivo emulado, este
valor debe establecerse en webcamn,
donde n selecciona la cámara web (si
solo tiene una, seleccione webcam0).
Si se establece en emulado, el
emulador simula una cámara a través
de software. Para deshabilitar la
cámara frontal, establezca este valor en
ninguno. Si habilita la cámara frontal,
asegúrese de habilitar también
hw.camera .
PROPIEDAD. DESCRIPCIÓN OPCIONES

hw.camera.maxHorizontalPixels Píxeles horizontales máximos de la


cámara– configura la resolución
horizontal máxima de la cámara del
dispositivo emulado (en píxeles).

hw.camera.maxVerticalPixels Píxeles verticales máximos de la


cámara– configura la resolución
vertical máxima de la cámara del
dispositivo emulado (en píxeles).

hw.cpu.arch Arquitectura de CPU– arquitectura x86, x86_64, arm, arm64


de CPU que el dispositivo virtual va a
emular. Si usa Intel HAXM para la
aceleración de hardware, seleccione
x86 para una CPU de 32 bits.
Seleccione x86_64 para un dispositivo
acelerado por HAXM de 64 bits.
(Asegúrese de instalar la imagen del
sistema x86 de Intel correspondiente
en SDK Manager; por ejemplo, Intel
x86 Atom o Intel x86 Atom_64). Para
simular una CPU de ARM, seleccione
arm para 32 bits o arm64 para una
CPU de ARM de 64 bits. Tenga en
cuenta que los dispositivos virtuales
basados en ARM se ejecutarán mucho
más lentamente que los basados en
x86, ya que la aceleración de hardware
no está disponible para ARM.

hw.cpu.model Modelo de CPU– este valor suele


dejarse sin establecer (se establecerá
en un valor derivado de hw.cpu.arch
si no se establece explícitamente). A
pesar de ello, se puede establecer en
una cadena específica del emulador
para su uso experimental.

hw.dPad Teclas de DPad– determina si el sí, no


dispositivo emulado admite teclas del
mando de dirección (DPad). Un DPad
suele tener cuatro teclas para indicar el
control direccional.

hw.gps Compatibilidad con GPS– determina sí, no


si el dispositivo emulado tiene un
receptor GPS (sistema de
posicionamiento global).
PROPIEDAD. DESCRIPCIÓN OPCIONES

hw.gpu.enabled Emulación de GPU– determina si el sí, no


dispositivo emulado admite la
emulación de GPU. Cuando está
habilitada, la emulación de GPU usa
OpenGL para sistemas incrustados
(OpenGL ES) para representar gráficos
2D y 3D en la pantalla, y la
configuración del modo de emulación
de GPU asociada determina cómo se
implementa la emulación de GPU.

hw.gpu.mode Modo de emulación de GPU– automático, host, mesa, ángulo,


determina la manera en que el swiftshader, desactivado
emulador implementa la emulación de
GPU. Si selecciona el valor automático,
el emulador elegirá la aceleración de
hardware y software según la
configuración del equipo de desarrollo.
Si selecciona host, el emulador usará el
procesador de gráficos del equipo de
desarrollo para realizar la emulación de
GPU para un procesamiento más
rápido. Si la GPU no es compatible con
el emulador y se encuentra en
Windows, puede usar el valor ángulo
en lugar de host. El modo de ángulo
usa DirectX para ofrecer un
rendimiento similar a host. Si
selecciona mesa, el emulador usará la
biblioteca de software 3D de Mesa
para representar gráficos. Seleccione
mesa si tiene problemas de
representación con el procesador de
gráficos del equipo de desarrollo.
Puede usar el modo swiftshader para
representar gráficos mediante software
con un rendimiento ligeramente
inferior que el que ofrece el uso de la
GPU del equipo. La opción desactivado
(que deshabilita la emulación de
hardware de gráficos) está en desuso,
ya que puede producir la
representación incorrecta de algunos
elementos, por lo que no se
recomienda.

hw.gsmModem Compatibilidad con módem GSM– sí, no


determina si el dispositivo emulado
incluye un módem que admite el
sistema de radio de telefonía GSM
(sistema global para las
comunicaciones móviles).
PROPIEDAD. DESCRIPCIÓN OPCIONES

hw.initialOrientation Orientación inicial de la pantalla– vertical, horizontal


configura la orientación inicial de la
pantalla en el dispositivo emulado
(modo vertical u horizontal). En el
modo vertical, la pantalla es más alta
que ancha. En el modo horizontal, la
pantalla es más ancha que alta.
Cuando se ejecuta el dispositivo
emulado, puede cambiar la orientación
si se admiten en el perfil del dispositivo
el modo vertical y horizontal.

hw.keyboard Compatibilidad con teclado– sí, no


determina si el dispositivo emulado
admite un teclado QWERTY.

hw.keyboard.charmap Nombre del mapa de caracteres


del teclado– nombre del mapa de
caracteres de hardware para este
dispositivo. NOTA: Debe ser siempre el
valor predeterminado qwerty2, a
menos que haya modificado la imagen
del sistema en consecuencia. Este
nombre se envía al kernel en el
momento del arranque. Si se especifica
un nombre incorrecto, el dispositivo
virtual no se podrá usar.

hw.keyboard.lid Compatibilidad con tapa del sí, no


teclado– si está habilitada la
compatibilidad con el teclado, esta
configuración determina si el teclado
QWERTY puede estar cerrado/oculto o
abierto/visible. Esta opción se omitirá si
hw.keyboard está establecido en false.
NOTA: El valor predeterminado es false
si el dispositivo emulado tiene como
destino el nivel de API 12 o superior.

hw.lcd.backlight Luz de fondo de LCD– determina si el sí, no


dispositivo emulado simula una luz de
fondo de LCD.

hw.lcd.density Densidad de LCD– densidad de la 120, 160, 240, 213, 320


pantalla LCD emulada, expresada en
píxeles independientes de la densidad,
o dp (dp es una unidad píxeles de
virtuales). Si el valor es 160 dp, cada dp
se corresponde con un píxel físico. En
tiempo de ejecución, Android usa este
valor para seleccionar y escalar los
recursos/activos adecuados para la
representación correcta de la pantalla.
PROPIEDAD. DESCRIPCIÓN OPCIONES

hw.lcd.depth Profundidad de color de LCD– 16, 32


profundidad de bits de color del búfer
de fotogramas emulado que contiene
el mapa de bits para controlar la
pantalla LCD. Este valor puede ser 16
bits (65 536 colores posibles) o 32 bits
(16 777 216 colores más
transparencia). El valor de 32 bits
puede hacer que el emulador se
ejecute un poco más lentamente, pero
con una mayor precisión del color.

hw.lcd.height Altura de píxeles de LCD– número


de píxeles que componen la dimensión
vertical de la pantalla LCD emulada.

hw.lcd.width Anchura de píxeles de LCD– número


de píxeles que componen la dimensión
horizontal de la pantalla LCD emulada.

hw.mainKeys Teclas de hardware Atrás/Inicio– sí, no


determina si el dispositivo emulado
admite los botones de navegación de
hardware Atrás e Inicio. Puede
establecer este valor en sí si los
botones solo se implementan
mediante software. Si hw.mainKeys
está establecido en sí, el emulador no
mostrará los botones de navegación
en la pantalla, pero puede usar el panel
lateral del emulador para "presionar"
estos botones.

hw.ramSize Tamaño de RAM de dispositivo–


cantidad de RAM física en el dispositivo
emulado, en megabytes. El valor
predeterminado se calcula a partir del
tamaño de la pantalla o de la versión
de la máscara. Si se aumenta el
tamaño, el emulador puede funcionar
más rápidamente, pero a cambio
solicitará más recursos al equipo de
desarrollo.

hw.screen Tipo de pantalla táctil– define el tipo táctil, multitáctil, no táctil


de pantalla del dispositivo emulado.
Una pantalla multitáctil puede seguir
dos o más dedos en la interfaz táctil.
Una pantalla táctil puede detectar
únicamente eventos de entrada táctil
de un solo dedo. Una pantalla no táctil
no detecta eventos de entrada táctil.
PROPIEDAD. DESCRIPCIÓN OPCIONES

hw.sdCard Compatibilidad con SDCard– sí, no


determina si el dispositivo emulado
admite la inserción y la eliminación de
tarjetas SD (Secure Digital) virtuales. El
emulador usa las imágenes de disco
montables almacenadas en el equipo
de desarrollo para simular las
particiones de los dispositivos de
tarjeta SD reales (vea hw.sdCard.path).

sdcard.size Tamaño de SDCard– especifica el


tamaño del archivo de tarjeta SD
virtual en la ubicación especificada por
hw.sdCard.path . disponible en el
dispositivo (en bytes). Si el valor es un
entero, se especifica el tamaño en
bytes. También se puede especificar el
tamaño en kilobytes, megabytes y
gigabytes. Para ello, anexe K, M o G al
valor. El tamaño mínimo es 9 M y el
tamaño máximo es 1023 G.

hw.sdCard.path Ruta de acceso a la imagen de


SDCard– especifica el nombre de
archivo y la ruta de acceso al archivo
de imagen de la partición de una
tarjeta SD en el equipo de desarrollo.
Por ejemplo, esta ruta de acceso se
podría establecer en
C:\sd\sdcard.img en Windows.

hw.sensors.magnetic_field Sensor de campo magnético– sí, no


determina si el dispositivo emulado
admite un sensor de campo
magnético. El sensor de campos
magnético (también conocido como
magnetómetro) notifica el campo
geomagnético ambiental según las
mediciones de tres ejes del sensor.
Habilite esta opción para las
aplicaciones que necesiten tener acceso
a las lecturas de una brújula. Por
ejemplo, una aplicación de navegación
podría usar este sensor para detectar
en qué dirección está orientado el
usuario.

hw.sensors.orientation Sensor de orientación– determina si sí, no


el dispositivo emulado proporciona
valores del sensor de orientación. El
sensor de orientación mide los grados
de rotación que realiza un dispositivo
en torno a tres físicos ejes (x, y, z).
Tenga en cuenta que el sensor de
orientación está en desuso a partir de
Android 2.2 (nivel de API 8).
PROPIEDAD. DESCRIPCIÓN OPCIONES

hw.sensors.proximity Sensor de proximidad– determina si sí, no


el dispositivo emulado admite un
sensor de proximidad. Este sensor
mide la proximidad de un objeto con
respecto a la pantalla de un dispositivo.
Este sensor suele usarse para
determinar si se está sujetando un
auricular junto a la oreja de una
persona.

hw.sensors.temperature Sensor de temperatura– determina si sí, no


el dispositivo emulado admite un
sensor de temperatura. Este sensor
mide la temperatura del dispositivo en
grados centígrados (°C).

hw.touchScreen Compatibilidad con pantalla táctil– sí, no


determina si el dispositivo emulado
admite una pantalla táctil. La pantalla
táctil se usa para la manipulación
directa de los objetos en la pantalla.

hw.trackBall Compatibilidad con bola de sí, no


seguimiento– determina si el
dispositivo emulado admite una bola
de seguimiento.

hw.useext4 Compatibilidad con sistema de No


archivos EXT4– determina si el
dispositivo emulado usa el sistema de
archivos de Linux EXT4 para las
particiones. Dado que el tipo de
sistema de archivos ahora se detecta
automáticamente, esta opción está en
desuso y se omite.

kernel.newDeviceNaming Nueva nomenclatura de dispositivo detección automática, sí, no


de kernel– se usa para especificar si el
kernel requiere un nuevo esquema de
nomenclatura de dispositivo. Se suele
usar con kernels de Linux 3.10 y
versiones posteriores. Si se establece
en detección automática, el
emulador detectará automáticamente
si el kernel requiere un nuevo esquema
de nomenclatura de dispositivo.

kernel.parameters Parámetros de kernel– especifica la


cadena de parámetros de arranque del
kernel de Linux. De forma
predeterminada, este valor se deja en
blanco.

kernel.path Ruta de acceso al kernel– especifica


la ruta de acceso al kernel de Linux. Si
no se especifica esta ruta de acceso, el
emulador busca kernel-ranchu en el
directorio del sistema del emulador.
PROPIEDAD. DESCRIPCIÓN OPCIONES

kernel.supportsYaffs2 Compatibilidad con particiones detección automática, sí, no


YAFFS2– determina si el kernel admite
particiones YAFFS2 (Yet Another Flash
File System 2). Normalmente, esto solo
se aplica a los kernels anteriores a
Linux 3.10. Si se establece en
detección automática, el emulador
detectará automáticamente si el kernel
puede montar sistemas de archivos
YAFFS2.

skin.name Nombre de máscara– nombre de


una máscara de Android Emulator. Una
máscara es una colección de archivos
que define los elementos visuales y de
control de una pantalla del emulador y
describe el aspecto que tendrá la
ventana del dispositivo virtual Android
en el equipo de desarrollo. Una
máscara describe el tamaño de la
pantalla, los botones y el diseño global,
pero no afecta al funcionamiento de la
aplicación.

skin.path Ruta de acceso a la máscara– ruta


de acceso al directorio que contiene los
archivos de máscara del emulador
especificados en skin.name. Este
directorio contiene archivos de diseño
hardware.ini y archivos de imagen para
los elementos representados de la
máscara.

skin.dynamic Máscara dinámica– indica si la No


máscara es dinámica o no. La máscara
del emulador es dinámica si el
emulador va a construir una máscara
de un tamaño determinado en función
de una anchura y una altura
especificadas.

Para más información sobre estas propiedades, vea Propiedades de perfil de hardware.
Solución de problemas de Android Emulator
11/07/2019 • 31 minutes to read • Edit Online

En este artículo se describen los mensajes de advertencia y los problemas más comunes que se producen al
configurar y ejecutar Android Emulator. Además, se describen soluciones para resolver estos errores, así como
algunas sugerencias para solucionar problemas que le ayudarán a diagnosticar problemas del emulador.

Problemas de implementación en Windows


El emulador puede mostrar algunos mensajes de error al implementar la aplicación. Aquí se explican los errores
y las soluciones más comunes.
Errores de implementación
Si se ve un error al instalar el APK en el emulador o al ejecutar Android Debug Bridge (adb), compruebe que
Android SDK se pueda conectar con el emulador. Para comprobar la conectividad del emulador, siga estos pasos:
1. Inicie el emulador desde Android Device Manager (seleccione el dispositivo virtual y haga clic en
Iniciar).
2. Abra un símbolo del sistema y vaya a la carpeta donde está instalado adb. Si Android SDK está instalado
en su ubicación predeterminada, adb se encuentra en C:\Archivos de programa
(x86)\Android\android-sdk\platform -tools\adb.exe; de lo contrario, modifique esta ruta de acceso
para la ubicación de Android SDK en el equipo.
3. Escriba el comando siguiente:

adb devices

4. Si el emulador es accesible desde Android SDK, el emulador debe aparecer en la lista de dispositivos
conectados. Por ejemplo:

List of devices attached


emulator-5554 device

5. Si el emulador no aparece en esta lista, inicie Android SDK Manager, aplique todas las actualizaciones e
intente iniciar el emulador de nuevo.
Error de acceso MMIO
Si se muestra el mensaje Se ha producido un error de acceso MMIO, reinicie el emulador.

Ausencia de Google Play Services


Si el dispositivo virtual que se ejecuta en el emulador no tiene instalado Google Play Services o Google Play
Store, esta condición suele deberse a la creación de un dispositivo virtual sin incluir estos paquetes. Cuando cree
un dispositivo virtual (vea Administración de dispositivos virtuales con Android Device Manager ), asegúrese de
seleccionar una de las opciones siguientes, o las dos:
Google APIs – incluye Google Play Services en el dispositivo virtual.
Google Play Store – incluye Google Play Store en el dispositivo virtual.
Por ejemplo, este dispositivo virtual incluirá Google Play Services y Google Play Store:
NOTE
Las imágenes de Google Play Store solo están disponibles para algunos tipos de dispositivos base como Pixel, Pixel 2,
Nexus 5 y Nexus 5X.

Problemas de rendimiento
Los problemas de rendimiento se suelen producir por uno de los problemas siguientes:
El emulador se ejecuta sin aceleración de hardware.
El dispositivo virtual que se ejecuta en el emulador no usa una imagen del sistema basado en x86.
En las secciones siguientes se tratan estos escenarios con más detalle.
La aceleración de hardware no está habilitada
Si la aceleración de hardware no está habilitada, el inicio de un dispositivo virtual desde Device Manager
generará un cuadro de diálogo con un mensaje de error en el que se indica que Windows Hypervisor Platform
(WHPX) no está correctamente configurado:

Si se muestra este mensaje de error, vea Problemas de aceleración de hardware a continuación para obtener los
pasos que se pueden seguir para comprobar y habilitar la aceleración de hardware.
La aceleración está habilitada, pero el emulador se ejecuta con demasiada lentitud
Una causa común de este problema es que no se está usando una imagen basado en x86 en el dispositivo
virtual (AVD ). Cuando cree un dispositivo virtual (vea Administración de dispositivos virtuales con Android
Device Manager), asegúrese de seleccionar una imagen del sistema basado en x86:
Problemas de aceleración de hardware
Si usa Hyper-V o HAXM para la aceleración de hardware, es posible que experimente problemas o conflictos de
configuración con otro software del equipo. Puede comprobar que la aceleración de hardware esté habilitada (y
qué método de aceleración usa el emulador) si abre un símbolo del sistema y escribe el comando siguiente:

"C:\Program Files (x86)\Android\android-sdk\emulator\emulator-check.exe" accel

Este comando asume que Android SDK está instalado en la ubicación predeterminada de C:\Archivos de
programa (x86)\Android\android-sdk; de lo contrario, modifique la ruta de acceso anterior para que sea la
ubicación de Android SDK en el equipo.
La aceleración de hardware no está disponible
Si Hyper-V está disponible, el comando emulator-check.exe accel devolverá un mensaje similar al ejemplo
siguiente:

HAXM is not installed, but Windows Hypervisor Platform is available.

Si HAXM está disponible, se devolverá un mensaje similar al ejemplo siguiente:

HAXM version 6.2.1 (4) is installed and usable.

Si la aceleración de hardware no está disponible, se mostrará un mensaje similar al ejemplo siguiente (el
emulador busca HAXM si no puede encontrar Hyper-V ):

HAXM is not installed on this machine

Si la aceleración de hardware no está disponible, vea Aceleración con Hyper-V para obtener información sobre
cómo habilitar la aceleración de hardware en el equipo.
Configuración del BIOS incorrecta
Si el BIOS no se ha configurado correctamente para admitir la aceleración de hardware, se mostrará un mensaje
similar al siguiente ejemplo al ejecutar el comando emulator-check.exe accel:

VT feature disabled in BIOS/UEFI

Para corregir este problema, reinicie en el BIOS del equipo y habilite las opciones siguientes:
Tecnología de virtualización (puede tener otra etiqueta según el fabricante de la placa base).
Prevención de ejecución de datos forzada mediante hardware.
Si la aceleración de hardware está habilitada y el BIOS está configurado correctamente, el emulador se debería
ejecutar de forma correcta con aceleración de hardware. Pero pueden seguir surgiendo problemas debido a
errores específicos de Hyper-V y HAXM, como se explica a continuación.
Problemas de Hyper-V
En algunos casos, habilitar tanto Hyper-V como Windows Hypervisor Platform en el cuadro de diálogo
Activar o desactivar las características de Windows puede que no habilite Hyper-V correctamente. Para
comprobar que Hyper-V está habilitado, siga estos pasos:
1. En el cuadro de búsqueda de Windows, escriba powershell.
2. Haga clic con el botón derecho en Windows PowerShell en los resultados de la búsqueda y seleccione
Ejecutar como administrador.
3. En la consola de PowerShell, escriba el comando siguiente:

Get-WindowsOptionalFeature -FeatureName Microsoft-Hyper-V-All -Online

Si Hyper-V no está habilitado, se mostrará un mensaje similar al ejemplo siguiente para indicar que el
estado de Hyper-V es Deshabilitado:

FeatureName : Microsoft-Hyper-V-All
DisplayName : Hyper-V
Description : Provides services and management tools for creating and running virtual machines
and their resources.
RestartRequired : Possible
State : Disabled
CustomProperties :

4. En la consola de PowerShell, escriba el comando siguiente:

Get-WindowsOptionalFeature -FeatureName HypervisorPlatform -Online

Si Hypervisor no está habilitado, se mostrará un mensaje similar al ejemplo siguiente para indicar que el
estado de HypervisorPlatform es Deshabilitado:

FeatureName : HypervisorPlatform
DisplayName : Windows Hypervisor Platform
Description : Enables virtualization software to run on the Windows hypervisor
RestartRequired : Possible
State : Disabled
CustomProperties :

Si Hyper-V o HypervisorPlatform no están habilitados, use los comandos de PowerShell siguientes para
habilitarlos:

Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All


Enable-WindowsOptionalFeature -Online -FeatureName HypervisorPlatform -All

Cuando se completen estos comandos, reinicie.


Para obtener más información sobre cómo habilitar Hyper-V (incluidas las técnicas para habilitar Hyper-V
mediante la herramienta de Administración y mantenimiento de imágenes de implementación), vea Instalar
Hyper-V.
Problemas de HAXM
Normalmente los problemas de HAXM son consecuencia de conflictos con otras tecnologías de virtualización,
configuraciones incorrectas o un controlador HAXM que no está actualizado.
No se está ejecutando el proceso de HAXM
Si HAXM está instalado, puede comprobar que el proceso de HAXM se está ejecutando si abre un símbolo del
sistema y escribe el comando siguiente:

sc query intelhaxm

Si el proceso de HAXM se está ejecutando, el resultado debería ser similar al siguiente:

SERVICE_NAME: intelhaxm
TYPE : 1 KERNEL_DRIVER
STATE : 4 RUNNING
(STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
WIN32_EXIT_CODE : 0 (0x0)
SERVICE_EXIT_CODE : 0 (0x0)
CHECKPOINT : 0x0
WAIT_HINT : 0x0

Si STATE no está establecido en RUNNING , vea How to Use the Intel Hardware Accelerated Execution Manager
(Cómo usar Intel Hardware Accelerated Execution Manager) para resolver el problema.
Conflictos de virtualización de HAXM
HAXM puede entrar en conflicto con otras tecnologías que usan la virtualización, como Hyper-V y Windows
Device Guard, y cierto software antivirus:
Hyper-V: si usa una versión de Windows anterior a la actualización de abril de 2018 de Windows 10
(compilación 1803) y Hyper-V está habilitado, siga los pasos indicados en Deshabilitar Hyper-V para
poder habilitar HAXM.
Device Guard: Device Guard y Credential Guard pueden impedir que se deshabilite Hyper-V en
máquinas con Windows. Para deshabilitar Device Guard y Credential Guard, consulte Deshabilitación de
Device Guard.
Software antivirus: si está ejecutando software antivirus que usa la virtualización asistida por hardware
(por ejemplo, Avast), deshabilite o desinstale este software, reinicie el equipo e intente iniciar de nuevo
Android Emulator.
Configuración del BIOS incorrecta
Si está usando HAXM en un equipo con Windows, HAXM no funcionará a menos que la tecnología de
virtualización (Intel VT-x) esté habilitada en el BIOS. Si VT-x está deshabilitada, obtendrá un error similar al
siguiente al intentar iniciar Android Emulator:
This computer meets the requirements for HAXM, but Intel Virtualization Technology (VT-x) is not
turned on. (Este equipo cumple los requisitos de HAXM, pero Intel Virtualization Technology (VT-x) no está
activada.)
Para corregir este error, arranque el equipo en el BIOS, habilite VT-x y SLAT (traducción de direcciones de
segundo nivel) y, después, reinicie el equipo en Windows.
Deshabilitar Hyper-V
Si usa una versión de Windows anterior a la actualización de abril de 2018 de Windows 10 (compilación
1803) y Hyper-V está habilitado, debe deshabilitar Hyper-V y reiniciar el equipo para instalar y usar HAXM. Si
usa la actualización de abril de 2018 de Windows 10 (compilación 1803) o una versión posterior, Android
Emulator versión 27.2.7 o posterior puede usar Hyper-V en lugar de HAXM para la aceleración de hardware, por
lo que no es necesario deshabilitar Hyper-V.
Puede deshabilitar Hyper-V desde el Panel de control mediante estos pasos:
1. Escriba características de windows en el cuadro de búsqueda de Windows y seleccione Activar o
desactivar las características de Windows en los resultados de la búsqueda.
2. Desactive Hyper-V:

3. Reinicie el equipo.
Como alternativa, puede usar el comando de PowerShell siguiente para deshabilitar el hipervisor Hyper-V:
Disable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V-Hypervisor

HAXM de Intel y Microsoft Hyper-V no pueden estar activos al mismo tiempo. Desafortunadamente, no existe
ninguna manera de alternar entre Hyper-V y HAXM sin reiniciar el equipo.
En algunos casos, si Device Guard y Credential Guard están habilitados, con los pasos anteriores no se
deshabilitará Hyper-V correctamente. Si no puede deshabilitar Hyper-V (o parece estar deshabilitado pero sigue
habiendo errores en la instalación de HAXM ), siga los pasos de la sección siguiente para deshabilitar Device
Guard y Credential Guard.
Deshabilitación de Device Guard
Device Guard y Credential Guard pueden evitar que se deshabilite Hyper-V en equipos Windows. Esta situación
suele ser un problema para los equipos unidos a un dominio que se configuran y se controlan mediante una
organización propietaria. En Windows 10, siga estos pasos para comprobar si se está ejecutando Device Guard:
1. Escriba información del sistema en el cuadro de búsqueda de Windows y seleccione Información del
sistema en los resultados de la búsqueda.
2. En Resumen del sistema, compruebe si está presente Seguridad basada en la virtualización de
Device Guard y si su estado es En ejecución:
Si Device Guard está habilitado, siga estos pasos para deshabilitarlo:
1. Asegúrese de que Hyper-V esté deshabilitado (en Activar o desactivar las características de
Windows) como se explica en la sección anterior.
2. En el cuadro de búsqueda de Windows, escriba gpedit y seleccione el resultado de búsqueda Editar
directiva de grupo. Estos pasos inician el Editor de directivas de grupo local.
3. En el Editor de directivas de grupo local, vaya a Configuración del equipo > Plantillas
administrativas > Sistema > Device Guard:

4. Cambie Activar la seguridad basada en la virtualización a Deshabilitado (como se ha indicado


arriba) y salga del Editor de directivas de grupo local.
5. En el cuadro de búsqueda de Windows, escriba cmd. Si aparece Símbolo del sistema en los resultados
de búsqueda, haga clic con el botón derecho en Símbolo del sistema y seleccione Ejecutar como
administrador.
6. Copie y pegue los siguientes comandos en la ventana del símbolo del sistema (si la unidad Z: se está
usando, seleccione una letra de unidad no usada en su lugar):
mountvol Z: /s
copy %WINDIR%\System32\SecConfig.efi Z:\EFI\Microsoft\Boot\SecConfig.efi /Y
bcdedit /create {0cb3b571-2f2e-4343-a879-d86a476d7215} /d "DebugTool" /application osloader
bcdedit /set {0cb3b571-2f2e-4343-a879-d86a476d7215} path "\EFI\Microsoft\Boot\SecConfig.efi"
bcdedit /set {bootmgr} bootsequence {0cb3b571-2f2e-4343-a879-d86a476d7215}
bcdedit /set {0cb3b571-2f2e-4343-a879-d86a476d7215} loadoptions DISABLE-LSA-ISO,DISABLE-VBS
bcdedit /set {0cb3b571-2f2e-4343-a879-d86a476d7215} device partition=Z:
mountvol Z: /d

7. Reinicie el equipo. En la pantalla de arranque, debería ver un mensaje similar al siguiente:


¿Quiere deshabilitar Credential Guard?

Pulse la tecla indicada para deshabilitar Credential Guard como se pide.


8. Una vez reiniciado el equipo, compruebe de nuevo que Hyper-V está deshabilitado (como se ha explicado
en los pasos anteriores).
Si Hyper-V aún no está deshabilitado, es posible que las directivas del equipo unido a dominio eviten que se
deshabiliten Device Guard o Credential Guard. En este caso, puede solicitar una exención al administrador del
dominio que le permita no usar Credential Guard. Como alternativa, puede usar un equipo que no esté unido a
un dominio si tiene que utilizar HAXM.

Otras sugerencias para la de solución de problemas


Las sugerencias siguientes suelen ser útiles para diagnosticar problemas de Android Emulator.
Inicio de Android Emulator desde la línea de comandos
Si el emulador no se está ejecutando, puede iniciarlo desde la línea de comandos (en lugar de desde dentro de
Visual Studio) para ver su salida. Normalmente, las imágenes de AVD de Android Emulator se almacenan en la
siguiente ubicación (reemplace nombre_de_usuario con el nombre de usuario de Windows):
C:\Usuarios\nombre_de_usuario\.android\avd
Puede iniciar el emulador con una imagen de AVD desde esta ubicación si pasa el nombre de la carpeta del AVD.
Por ejemplo, este comando inicia un AVD denominado Pixel_API_27:

"C:\Program Files (x86)\Android\android-sdk\emulator\emulator.exe" -partition-size 512 -no-boot-anim -


verbose -feature WindowsHypervisorPlatform -avd Pixel_API_27 -prop monodroid.avdname=Pixel_API_27

En este ejemplo se asume que Android SDK está instalado en la ubicación predeterminada de C:\Archivos de
programa (x86)\Android\android-sdk; de lo contrario, modifique la ruta de acceso anterior para que sea la
ubicación de Android SDK en el equipo.
Al ejecutar este comando, generará varias líneas de salida mientras se inicia el emulador. En concreto, se
imprimirán líneas como las del ejemplo siguiente si la aceleración de hardware está habilitada y funciona
correctamente (en este ejemplo, se usa HAXM para la aceleración de hardware):

emulator: CPU Acceleration: working


emulator: CPU Acceleration status: HAXM version 6.2.1 (4) is installed and usable.

Visualización de registros de Device Manager


A menudo, se pueden ver los registros de Device Manager para diagnosticar problemas del emulador. Estos
registros se escriben en la ubicación siguiente:
C:\Usuarios\nombre_de_usuario\AppData\Roaming\XamarinDeviceManager
Puede ver cada archivo DeviceManager.log con un editor de texto como Bloc de notas. En la entrada de
registro de ejemplo siguiente se indica que no se encontró HAXM en el equipo:

Component Intel x86 Emulator Accelerator (HAXM installer) r6.2.1 [Extra: (Intel Corporation)] not present on
the system

Problemas de implementación en macOS


El emulador puede mostrar algunos mensajes de error al implementar la aplicación. A continuación se explican
los errores y las soluciones más comunes.
Errores de implementación
Si se ve un error al instalar el APK en el emulador o al ejecutar Android Debug Bridge (adb), compruebe que
Android SDK se pueda conectar con el emulador. Para comprobar la conectividad, siga estos pasos:
1. Inicie el emulador desde Android Device Manager (seleccione el dispositivo virtual y haga clic en
Iniciar).
2. Abra un símbolo del sistema y vaya a la carpeta donde está instalado adb. Si Android SDK está instalado
en su ubicación predeterminada, adb se encuentra en ~/Library/Developer/Xamarin/android-sdk-
macosx/platform -tools/adb; de lo contrario, modifique esta ruta de acceso para la ubicación de
Android SDK en el equipo.
3. Escriba el comando siguiente:

adb devices

4. Si el emulador es accesible desde Android SDK, el emulador debe aparecer en la lista de dispositivos
conectados. Por ejemplo:

List of devices attached


emulator-5554 device

5. Si el emulador no aparece en esta lista, inicie Android SDK Manager, aplique todas las actualizaciones e
intente iniciar el emulador de nuevo.
Error de acceso MMIO
Si se muestra Se ha producido un error de acceso MMIO, reinicie el emulador.

Ausencia de Google Play Services


Si el dispositivo virtual que se ejecuta en el emulador no tiene instalado Google Play Services o Google Play
Store, esta condición suele deberse a la creación de un dispositivo virtual sin incluir estos paquetes. Cuando cree
un dispositivo virtual (vea Administración de dispositivos virtuales con Android Device Manager ), asegúrese de
seleccionar una de las opciones siguientes, o las dos:
Google APIs – incluye Google Play Services en el dispositivo virtual.
Google Play Store – incluye Google Play Store en el dispositivo virtual.
Por ejemplo, este dispositivo virtual incluirá Google Play Services y Google Play Store:
NOTE
Las imágenes de Google Play Store solo están disponibles para algunos tipos de dispositivos base como Pixel, Pixel 2,
Nexus 5 y Nexus 5X.

Problemas de rendimiento
Los problemas de rendimiento se suelen producir por uno de los problemas siguientes:
El emulador se ejecuta sin aceleración de hardware.
El dispositivo virtual que se ejecuta en el emulador no usa una imagen del sistema basado en x86.
En las secciones siguientes se tratan estos escenarios con más detalle.
La aceleración de hardware no está habilitada
Si la aceleración de hardware no está habilitada, es posible que aparezca un cuadro de diálogo con un mensaje
como el dispositivo se ejecutará sin aceleración al implementar la aplicación en Android Emulator. Si no
está seguro de si la aceleración de hardware está habilitada en el equipo (o le gustaría saber qué tecnología
proporciona la aceleración), vea Problemas de aceleración de hardware a continuación para conocer los pasos
que puede seguir para comprobar y habilitar la aceleración de hardware.
La aceleración está habilitada, pero el emulador se ejecuta con demasiada lentitud
Una causa común de este problema es que no se está usando una imagen basada en x86 en el dispositivo
virtual. Cuando cree un dispositivo virtual (vea Administración de dispositivos virtuales con Android Device
Manager), asegúrese de seleccionar una imagen del sistema basada en x86:

Problemas de aceleración de hardware


Con independencia de que use Hypervisor Framework o HAXM para la aceleración de hardware del emulador,
es posible que experimente problemas causados por problemas de instalación o una versión obsoleta de
macOS. Las secciones siguientes pueden ayudarle a resolver este problema.
Problemas de Hypervisor Framework
Si usa macOS 10.10 o una versión posterior en un equipo Mac más reciente, Android Emulator usará
automáticamente Hypervisor Framework para la aceleración de hardware. Pero es posible que algunos equipos
Mac más antiguos o que ejecuten una versión de macOS anterior a 10.10 no proporcionen compatibilidad con
Hypervisor Framework.
Para determinar si el equipo Mac es compatible con Hypervisor Framework, abra una ventana de Terminal y
escriba el comando siguiente:

sysctl kern.hv_support

Si el equipo Mac es compatible con Hypervisor Framework, el comando anterior devolverá el resultado
siguiente:

kern.hv_support: 1

Si Hypervisor Framework no está disponible en el equipo Mac, puede seguir los pasos descritos en Aceleración
con HAXM para usar HAXM para la aceleración en su lugar.
Problemas de HAXM
Si Android Emulator no se inicia correctamente, esto suele deberse a problemas relacionados con HAXM.
Normalmente los problemas de HAXM son consecuencia de conflictos con otras tecnologías de virtualización,
configuraciones incorrectas o un controlador HAXM que no está actualizado. Intente volver a instalar el
controlador HAXM mediante los pasos detallados en Instalación de HAXM.

Otras sugerencias para la de solución de problemas


Las sugerencias siguientes suelen ser útiles para diagnosticar problemas de Android Emulator.
Inicio de Android Emulator desde la línea de comandos
Si el emulador no se está ejecutando, puede iniciarlo desde la línea de comandos (en lugar de desde dentro de
Visual Studio para Mac) para ver su salida. Normalmente, las imágenes de AVD de Android Emulator se
almacenan en la ubicación siguiente:
~/.android/avd
Puede iniciar el emulador con una imagen de AVD desde esta ubicación si pasa el nombre de la carpeta del AVD.
Por ejemplo, este comando inicia un AVD denominado Pixel_2_API_28:

~/Library/Developer/Xamarin/android-sdk-macosx/emulator/emulator -partition-size 512 -no-boot-anim -verbose


-feature WindowsHypervisorPlatform -avd Pixel_2_API_28 -prop monodroid.avdname=Pixel_2_API_28

Si Android SDK está instalado en su ubicación predeterminada, el emulador se encuentra en el directorio


~/Library/Developer/Xamarin/android-sdk-macosx/emulator; de lo contrario, modifique esta ruta de
acceso para la ubicación de Android SDK en el equipo Mac.
Al ejecutar este comando, generará varias líneas de salida mientras se inicia el emulador. En concreto, se
imprimirán líneas como las del ejemplo siguiente si la aceleración de hardware está habilitada y funciona
correctamente (en este ejemplo, se usa Hypervisor Framework para la aceleración de hardware):
emulator: CPU Acceleration: working
emulator: CPU Acceleration status: Hypervisor.Framework OS X Version 10.13

Visualización de registros de Device Manager


A menudo, se pueden ver los registros de Device Manager para diagnosticar problemas del emulador. Estos
registros se escriben en la ubicación siguiente:
~/Library/Logs/XamarinDeviceManager
Puede ver los archivos Android Devices.log si hace doble clic para abrirlos en la aplicación de consola. La
entrada de registro de ejemplo siguiente indica que no se encontró HAXM:

Component Intel x86 Emulator Accelerator (HAXM installer) r6.2.1 [Extra: (Intel Corporation)] not present on
the system
Configurar el dispositivo para el desarrollo
11/07/2019 • 12 minutes to read • Edit Online

En este artículo se explica cómo configurar un dispositivo Android y conectarlo a un equipo de modo que el
dispositivo pueda usarse para ejecutar y depurar aplicaciones de Xamarin.Android.
Después de realizar las pruebas en un emulador de Android, querrá ver y probar la ejecución de sus aplicaciones
en un dispositivo Android. Estos son los pasos que debe llevar a cabo para conectar un dispositivo a un equipo
para la depuración:
1. Habilitar la depuración en el dispositivo: de forma predeterminada, no es posible depurar
aplicaciones en un dispositivo Android.
2. Instalar controladores USB: este paso no es necesario para los equipos macOS. Los equipos de
Windows podrían requerir la instalación de controladores USB.
3. Conectar el dispositivo al equipo: el último paso consiste en conectar el dispositivo al equipo
mediante USB o Wi-Fi.
Cada uno de estos pasos se tratará con más detalle en las secciones siguientes.

Habilitar la depuración en el dispositivo


Puede usar cualquier dispositivo Android para probar una aplicación de Android, pero el dispositivo debe estar
configurado correctamente antes de realizar la depuración. Los pasos que se deben llevar a cabo son
ligeramente diferentes en función de la versión de Android que se ejecute en el dispositivo.
De Android 4.0 a Android 4.1
En las versiones de Android de 4.0.x a 4.1.x, debe seguir estos pasos para habilitar la depuración:
1. Vaya a la pantalla Configuración.
2. Seleccione Opciones del desarrollador.
3. Desactive la opción Depuración de USB.
En esta captura de pantalla se muestra la pantalla Opciones del desarrollador en un dispositivo que ejecuta
Android 4.0.3:
Android 4.2 y versiones posteriores
A partir de Android 4.2 y versiones posteriores, las Opciones del desarrollador están ocultas de forma
predeterminada. Para que estén disponibles, vaya a Ajustes > Acerca del dispositivo y pulse el elemento
Número de compilación siete veces para que se muestre la pestaña Opciones de desarrollador:

Una vez que la pestaña Opciones del desarrollador está disponible en Ajustes > Sistema, ábrala para
mostrar las opciones del desarrollador:
Desde aquí puede habilitar las opciones del desarrollador, como la depuración de USB y el modo Permanecer
activo.

Instalar controladores USB


Este paso no es necesario para macOS. Basta con que conecte el dispositivo al equipo Mac con un cable USB.
Puede que sea necesario instalar algunos controladores adicionales para que un equipo Windows reconozca un
dispositivo Android conectado mediante USB.

NOTE
Estos son los pasos necesarios para configurar un dispositivo Google Nexus y se proporcionan a modo de referencia. Los
pasos correspondientes a su dispositivo específico pueden variar, pero seguirán un patrón similar. Si tiene problemas,
busque su dispositivo en Internet.

Ejecute la aplicación android.bat en el directorio [ruta de instalación de Android SDK]\tools. De forma


predeterminada, el instalador de Xamarin.Android colocará el SDK de Android en la siguiente ubicación de un
equipo de Windows:
C:\Users\[username]\AppData\Local\Android\android-sdk

Descargar los controladores USB


Los dispositivos Google Nexus (a excepción de Galaxy Nexus) requieren el controlador USB de Google. El
controlador para Galaxy Nexus está distribuido por Samsung. Todos los demás dispositivos Android deben usar
el controlador USB de su fabricante correspondiente.
Para instalar el paquete del controlador USB de Google, inicie Android SDK Manager y expanda la carpeta
Extras, como se ve en la captura de pantalla siguiente:

Active el cuadro del controlador USB de Google y haga clic en el botón Instalar. Los archivos del controlador
se descargan en la siguiente ubicación:
[Android SDK install path]\extras\google\usb\_driver

La ruta de acceso predeterminada para efectuar una instalación de Xamarin.Android es la siguiente:


C:\Users\[username]\AppData\Local\Android\android-sdk\extras\google\usb_driver
Instalar el controlador USB
Una vez que haya descargado los controladores USB, deberá instalarlos. Para instalar los controladores en
Windows 7:
1. Conecte el dispositivo al equipo con un cable USB.
2. Haga clic con el botón derecho en el equipo desde el escritorio o el Explorador de Windows y seleccione
Administrar.
3. Seleccione Dispositivos en el panel izquierdo.
4. Busque y expanda Otros dispositivos en el panel derecho.
5. Haga clic con el botón derecho en el nombre del dispositivo y seleccione Actualizar software de
controlador. Se iniciará el Asistente para actualización de hardware.
6. Seleccione Buscar software de controlador en el equipo y haga clic en Siguiente.
7. Haga clic en Examinar y busque la carpeta del controlador USB (el controlador USB de Google se
encuentra en [ruta de instalación de Android SDK]\extras\google\usb_driver).
8. Haga clic en Siguiente para instalar el controlador.
Instalar controladores no comprobados en Windows 8
Puede que sea necesario llevar a cabo pasos adicionales para instalar un controlador no comprobado en
Windows 8. En los pasos siguientes se describe cómo instalar los controladores para un Galaxy Nexus:
1. Obtener acceso a las opciones de arranque avanzadas de Windows 8: este paso consiste en
reiniciar el equipo para tener acceso a las opciones de arranque avanzadas. Inicie un símbolo de la línea
de comandos y reinicie el equipo mediante el comando siguiente:

shutdown.exe /r /o

2. Conectar el dispositivo: conecte el dispositivo al equipo.


3. Iniciar el administrador de dispositivos: ejecute devmgmt.msc; debería ver el dispositivo en la lista
con un triángulo amarillo sobre él.
4. Instalar los controladores del dispositivo: instale los controladores del dispositivo como se describió
anteriormente.

Conectar el dispositivo al equipo


El paso final consiste en conectar el dispositivo al equipo. Hay dos maneras de hacerlo:
Cable USB: esta es la manera más fácil y más común. Basta con que conecte el cable USB al dispositivo
y, después, al equipo.
Wi-Fi: es posible conectar un dispositivo Android a un equipo a través de Wi-Fi, sin usar un cable USB.
Esta técnica requiere algo más de esfuerzo, pero debería ser útil si el dispositivo está demasiado alejado
del equipo como para estar conectado constantemente mediante cable. En la sección siguiente se explica
cómo realizar la conexión a través de Wi-Fi.
Conectar a través de Wi-Fi
De forma predeterminada, Android Debug Bridge (ADB ) está configurado para comunicarse con un dispositivo
Android a través de USB. Es posible volver a configurarlo para que use TCP/IP en lugar de USB. Para ello, tanto
el dispositivo como el equipo deben estar en la misma red Wi-Fi. Para configurar el entorno para depurar
mediante Wi-Fi, siga estos pasos desde la línea de comandos:
1. Determine la dirección IP del dispositivo Android. Una manera de averiguar la dirección IP es mirar en
Ajustes > Wi-Fi y, después, pulsar la red Wi-Fi a la que está conectado el dispositivo. Se abrirá una
pantalla de configuración con información sobre la conexión de red, parecida a la que se muestra en la
siguiente captura de pantalla:
En algunas versiones de Android, la dirección IP no aparecerá ahí, pero se puede encontrar en Ajustes >
Acerca del teléfono > Estado.
2. Conecte el dispositivo Android al equipo a través de USB.
3. Después, reinicie ADB de modo que use TCP en el puerto 5555. En un símbolo del sistema, escriba el
siguiente comando:

adb tcpip 5555

Después de emitir este comando, el equipo no podrá escuchar los dispositivos que están conectados a
través de USB.
4. Desconecte el cable USB que conecta el dispositivo al equipo.
5. Configure ADB para que se conecte al dispositivo Android en el puerto que se especificó en el paso 1
anterior:

adb connect 192.168.1.28:5555

Una vez que se finalice este comando, el dispositivo Android se conecta al equipo a través de Wi-Fi.
Cuando termine la depuración a través de Wi-Fi, puede restablecer ADB al modo USB con el comando
siguiente:

adb usb

Es posible solicitarle a ADB que enumere los dispositivos que están conectados al equipo. Independientemente
de cómo estén conectados los dispositivos, puede emitir el comando siguiente en el símbolo del sistema para
ver qué está conectado:

adb devices

Resumen
En este artículo se ha descrito cómo configurar un dispositivo Android para el desarrollo mediante la
habilitación de la depuración en el dispositivo. Además, también se ha explicado cómo conectar el dispositivo a
un equipo a través de USB o Wi-Fi.

Vínculos relacionados
Android Debug Bridge
Uso de dispositivos de hardware
Descargas de controladores de Samsung
Controladores USB de OEM
Controlador USB de Google
Desarrolladores de XDA: problema del controlador ADB/fastboot resuelto en Windows 8
Distribución de Mobile OpenJDK de Microsoft
11/07/2019 • 4 minutes to read • Edit Online

En esta guía se describen los pasos para cambiar a una distribución interna de OpenJDK. Esta distribución está
pensada para el desarrollo móvil.

Información general
A partir de Visual Studio 15.9 y Visual Studio para Mac 7.7, Visual Studio Tools para Xamarin se ha migrado
desde el JDK de Oracle a una versión ligera de OpenJDK que está diseñada únicamente para el
desarrollo de Android. Esta migración es obligatoria, ya que Oracle dejará de ofrecer soporte técnico para la
distribución comercial de JDK 8 en 2019 y JDK 8 es una dependencia necesaria para todo el desarrollo de
Android.
Las ventajas de esta migración son las siguientes:
Siempre tendrá una versión de OpenJDK que funcione para el desarrollo de Android.
La descarga del JDK 9 de Oracle o versiones superiores no afectará a la experiencia de desarrollo.
Superficie y tamaño de la descarga menores.
No más problemas con instaladores y servidores de terceros.
Si quiere migrar antes a la experiencia mejorada, hay disponibles compilaciones de la distribución de OpenJDK
Mobile para probarlas tanto en Windows como en Mac. A continuación, se describe el proceso de configuración
y puede revertir al JDK de Oracle en cualquier momento.

Descargar
La distribución de Mobile OpenJDK se instala automáticamente si selecciona los paquetes de Android SDK en el
instalador de Visual Studio de Windows.
En Mac, Mobile OpenJDK se instalará como parte de la carga de trabajo de Android en instalaciones nuevas.
Para los usuarios actuales de Visual Studio para Mac, se les solicitará que lo instalen como parte de la
actualización. El IDE le solicitará que cambie al nuevo JDK y a partir del próximo reinicio ya se habrá aplicado el
cambio.

Solución de problemas
Si tiene problemas con la configuración en Mac o Windows, puede seguir estos pasos para realizar una
configuración manual:
Compruebe si OpenJDK está instalado en la máquina en la ubicación correcta:
Mac – $HOME/Library/Developer/Xamarin/jdk/microsoft_dist_openjdk_1.8.0.x
Windows – C:\Program Files\Android\jdk\microsoft_dist_openjdk_1.8.0.x
Dirija el IDE al nuevo JDK:
Mac – Haga clic en Herramientas > SDK Manager > Ubicaciones y cambie la Ubicación del SDK de
Java (SDK) a la ruta de acceso completa de la instalación de OpenJDK. En el ejemplo siguiente, esta ruta de
acceso está establecida en $HOME/Library/Developer/Xamarin/jdk/microsoft_dist_openjdk_1.8.0.9,
pero es posible que su versión sea más reciente.
Windows – Haga clic en Herramientas > Opciones > Xamarin > Configuración de Android y cambie la
Ubicación de Java Development Kit a la ruta de acceso completa de la instalación de OpenJDK. En el
ejemplo siguiente, esta ruta de acceso está establecida en C:\Program
Files\Android\jdk\microsoft_dist_openjdk_1.8.0.9, pero es posible que su versión sea más reciente:

Problemas conocidos
Error al instalar el paquete "OpenJDKV1.RegKey,version=1.8.0.25,chip=x64"
Este problema puede darse en algunos entornos corporativos. OpenJDK ya está en la máquina: siga los pasos de
solución de errores anteriores para indicar la ubicación correcta del IDE. Puede comprobar el estado de los
problemas aquí.

Resumen
En este artículo, ha aprendido a configurar su IDE para usar la distribución de Mobile OpenJDK de Microsoft y a
solucionar problemas que se podría encontrar.
Hello, Android
11/07/2019 • 2 minutes to read • Edit Online

En esta guía de dos partes, compilará su primera aplicación Xamarin.Android mediante Visual Studio para Mac
o Visual Studio y adquirirá una comprensión de los aspectos básicos del desarrollo de aplicaciones Android con
Xamarin. A lo largo del proceso, se presentan las herramientas, los conceptos y los pasos necesarios para
compilar e implementar una aplicación Xamarin.Android.

Parte 1: inicio rápido


En la primera parte de esta guía, creará una aplicación que convierte un número de teléfono alfanumérico
especificado por el usuario en un número de teléfono numérico y, después, llama a ese número.

Parte 2: profundización
En la segunda parte de este documento, revisará lo que ha creado y obtendrá unos conocimientos básicos sobre
el funcionamiento de las aplicaciones de Android.

Vínculos relacionados
Introducción a Android
Depurar en Visual Studio
Recetas de Visual Studio para Mac: Depuración
Hello, Android: Inicio rápido
05/08/2019 • 26 minutes to read • Edit Online

Esta guía, que consta de dos partes, le ayudará a compilar su primera aplicación de Xamarin.Android mediante
Visual Studio y a comprender los aspectos básicos del desarrollo de aplicaciones de Android con Xamarin.

Descargar el ejemplo
Creará una aplicación que convierte un número de teléfono alfanumérico (escrito por el usuario) en un número
de teléfono numérico y muestra ese número al usuario. La aplicación final tiene este aspecto:

Requisitos de Windows
Para seguir este tutorial, necesitará lo siguiente:
Windows 10.
Visual Studio 2019 o Visual Studio 2017 (versión 15.8 o posterior): Community, Professional o
Enterprise.

Requisitos de macOS
Para seguir este tutorial, necesitará lo siguiente:
La versión más reciente de Visual Studio para Mac.
Un equipo Mac que ejecute macOS High Sierra (10.13) o una versión posterior.
En este tutorial se presupone que está instalada la última versión de Xamarin.Android y que se está ejecutando
en la plataforma que ha seleccionado. Para obtener una guía de instalación de Xamarin.Android, vea las guías
Instalación de Xamarin.Android.

Configuración de los emuladores


Si está usando el emulador de Android, le recomendamos que lo configure para usar la aceleración de
hardware. Las instrucciones para configurar la aceleración de hardware están disponibles en Aceleración de
hardware para el rendimiento del emulador.
Crear el proyecto
Inicie Visual Studio. Para crear un proyecto, haga clic en Archivo > Nuevo > Proyecto.
En el cuadro de diálogo Nuevo proyecto, haga clic en la plantilla Aplicación Android. Asigne un nombre al
nuevo proyecto Phoneword y haga clic en Aceptar:

En el cuadro de diálogo New Android App (Nueva aplicación Android), haga clic en Aplicación vacía y en
Aceptar para crear el proyecto nuevo:

Crear un diseño
TIP
Las versiones más recientes de Visual Studio admiten la apertura de archivos .xml dentro de Android Designer.
Android Designer admite tanto archivos .axml como .xml.

Después de que el nuevo proyecto se haya creado, expanda la carpeta Recursos y, después, la carpeta Diseño
en el Explorador de soluciones. Haga doble clic en activity_main.axml para abrirla en Android Designer.
Este es el archivo de diseño para la pantalla de la aplicación:
TIP
Las versiones más recientes de Visual Studio contienen una plantilla de aplicación ligeramente diferente.
1. En lugar de activity_main.axml, el diseño está en content_main.axml.
2. El diseño predeterminado será RelativeLayout . Para que el resto de los pasos de esta página funcionen, debe
cambiar la etiqueta <RelativeLayout> por <LinearLayout> y agregar otro atributo
android:orientation="vertical" a la etiqueta de apertura LinearLayout .

En el Cuadro de herramientas (el área de la izquierda), escriba text en el campo de búsqueda y arrastre un
widget de Texto (grande) a la superficie de diseño (el área del centro):

Con el control de Texto (grande) seleccionado en la superficie de diseño, use el panel Propiedades para
cambiar la propiedad Text del widget de Texto (grande) a Enter a Phoneword: :
Arrastre un widget de Texto sin formato del Cuadro de herramientas a la superficie de diseño y colóquelo
debajo del widget de Texto (grande) . La selección de ubicación del widget no se producirá hasta que mueva el
puntero del mouse a un lugar en el diseño que pueda aceptar el widget. En las capturas de pantalla siguientes,
el widget no se puede colocar (tal y como se muestra en la parte izquierda) hasta que el puntero del mouse se
mueva justo debajo del TextView anterior (como se muestra en la parte derecha):

Cuando el texto sin formato (un widget EditText ) esté colocado correctamente, aparecerá tal y como se
muestra en la captura de pantalla siguiente:
Con el widget de Texto sin formato seleccionado en la superficie de diseño, use el panel Propiedades para
cambiar la propiedad Id del widget de Texto sin formato a @+id/PhoneNumberText y cambiar la propiedad
Text a 1-855-XAMARIN :

Arrastre un Botón del Cuadro de herramientas a la superficie de diseño y colóquelo debajo del widget de
Texto sin formato:

Con el botón seleccionado en la superficie de diseño, use el panel Propiedades para cambiar su propiedad
Text a Translate y cambiar su propiedad Id a @+id/TranslateButton :

Arrastre la vista de texto desde Cuadro de herramientas hasta la superficie de diseño y colóquela debajo del
widget Botón. Cambie la propiedad Text de TextView por una cadena vacía y establezca su propiedad Id en
@+id/TranslatedPhoneword :

Guarde su trabajo presionando CTRL+S.

Escritura de algo de código


El siguiente paso consiste en agregar código para convertir números de teléfono de formato alfanumérico a
numérico. Agregue un nuevo archivo al proyecto haciendo clic con el botón derecho en el proyecto
Phoneword en el panel del Explorador de soluciones y seleccionando Agregar > Nuevo elemento... ,
como se muestra a continuación:

En el cuadro de diálogo Agregar nuevo elemento, seleccione Visual C# > Código > Archivo de código y
asigne al nuevo archivo de código el nombre PhoneTranslator.cs:
Esto crea una nueva clase de C# vacía. Inserte el código siguiente en este archivo:
using System.Text;
using System;
namespace Core
{
public static class PhonewordTranslator
{
public static string ToNumber(string raw)
{
if (string.IsNullOrWhiteSpace(raw))
return "";
else
raw = raw.ToUpperInvariant();

var newNumber = new StringBuilder();


foreach (var c in raw)
{
if (" -0123456789".Contains(c))
{
newNumber.Append(c);
}
else
{
var result = TranslateToNumber(c);
if (result != null)
newNumber.Append(result);
}
// otherwise we've skipped a non-numeric char
}
return newNumber.ToString();
}
static bool Contains (this string keyString, char c)
{
return keyString.IndexOf(c) >= 0;
}
static int? TranslateToNumber(char c)
{
if ("ABC".Contains(c))
return 2;
else if ("DEF".Contains(c))
return 3;
else if ("GHI".Contains(c))
return 4;
else if ("JKL".Contains(c))
return 5;
else if ("MNO".Contains(c))
return 6;
else if ("PQRS".Contains(c))
return 7;
else if ("TUV".Contains(c))
return 8;
else if ("WXYZ".Contains(c))
return 9;
return null;
}
}
}

Guarde los cambios en el archivo PhoneTranslator.cs haciendo clic en Archivo > Guardar (o presionando
CTRL+S ) y, después, cierre el archivo.

Conectar la interfaz de usuario


El siguiente paso consiste en agregar código para conectar la interfaz de usuario al insertar código auxiliar en la
clase MainActivity . Empiece con la conexión del botón Traducir. En la clase MainActivity , busque el método
OnCreate . El siguiente paso consiste en agregar el código de botón dentro de OnCreate , debajo de las llamadas
base.OnCreate(savedInstanceState) y SetContentView(Resource.Layout.activity_main) . En primer lugar,
modifique el código de plantilla para que el método OnCreate sea similar al siguiente:

using Android.App;
using Android.OS;
using Android.Support.V7.App;
using Android.Runtime;
using Android.Widget;

namespace Phoneword
{
[Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)]
public class MainActivity : AppCompatActivity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);

// Set our view from the "main" layout resource


SetContentView(Resource.Layout.activity_main);

// New code will go here


}
}
}

Obtenga una referencia de los controles que se han creado en el archivo de diseño con Android Designer.
Agregue el código siguiente dentro del método OnCreate , después de la llamada a SetContentView :

// Get our UI controls from the loaded layout


EditText phoneNumberText = FindViewById<EditText>(Resource.Id.PhoneNumberText);
TextView translatedPhoneWord = FindViewById<TextView>(Resource.Id.TranslatedPhoneword);
Button translateButton = FindViewById<Button>(Resource.Id.TranslateButton);

Agregue el código que responda a las pulsaciones del usuario del botón Traducir. Agregue el siguiente código
al método OnCreate (después de las líneas que se han agregado en el paso anterior):

// Add code to translate number


translateButton.Click += (sender, e) =>
{
// Translate user's alphanumeric phone number to numeric
string translatedNumber = Core.PhonewordTranslator.ToNumber(phoneNumberText.Text);
if (string.IsNullOrWhiteSpace(translatedNumber))
{
translatedPhoneWord.Text = string.Empty;
}
else
{
translatedPhoneWord.Text = translatedNumber;
}
};

Guarde su trabajo seleccionando Archivo > Guardar todo (o presionando CTRL -MAYÚS -S ) y compile la
aplicación seleccionando Compilar > Recompilar solución (o presionando CTRL -MAYÚS -B ).
Si hay errores, repase los pasos anteriores y corrija cualquier error hasta que la aplicación se compile
correctamente. Si obtiene un error de compilación como El recurso no existe en el contexto actual, compruebe
que el nombre del espacio de nombres en MainActivity.cs coincida con el nombre del proyecto ( Phoneword ) y,
después, recompile completamente la solución. Si sigue obteniendo errores de compilación, compruebe que ha
instalado las últimas actualizaciones de Visual Studio.

Establecer el nombre de la aplicación


Ahora que debería tener una aplicación que funciona, es el momento de establecer su nombre. Expanda la
carpeta valores (dentro de la carpeta Recursos) y abra el archivo strings.xml. Cambie la cadena de nombre de
la aplicación por Phone Word como se muestra aquí:

<resources>
<string name="app_name">Phone Word</string>
<string name="action_settings">Settings</string>
</resources>

Ejecutar la aplicación
Pruebe la aplicación; para ello, ejecútela en un dispositivo o emulador Android. Haga clic en el botón
TRANSLATE para convertir 1-855-XAMARIN en un número de teléfono:

Para ejecutar la aplicación en un dispositivo Android, vea cómo configurar el dispositivo para el desarrollo.
Inicie Visual Studio para Mac desde la carpeta Aplicaciones o desde Spotlight.
Para crear un proyecto, haga clic en Nuevo proyecto...
En el cuadro de diálogo Choose a template for your new project (Elegir una plantilla para el nuevo
proyecto) , haga clic en Android > Aplicación y seleccione la plantilla Aplicación de Android. Haga clic en
Siguiente.
En el cuadro de diálogo Configure su aplicación de Android, asigne a la nueva aplicación el nombre
Phoneword y haga clic en Siguiente.

En el cuadro de diálogo Configure su aplicación de Android, deje los nombres de solución y proyecto
establecidos en Phoneword y haga clic en Crear para crear el proyecto.

Crear un diseño
TIP
Las versiones más recientes de Visual Studio admiten la apertura de archivos .xml dentro de Android Designer.
Android Designer admite tanto archivos .axml como .xml.

Después de que el nuevo proyecto se haya creado, expanda la carpeta Recursos y, después, la carpeta Diseño
en el panel de Solución. Haga doble clic en Main.axml para abrirlo en Android Designer. Este es el archivo de
diseño de la pantalla cuando se visualiza en Android Designer:
Seleccione el botón Hello World, Click Me! (Hola a todos, haz clic aquí) Botón en la superficie de diseño;
pulse la tecla Eliminar para quitarlo.
Desde el Cuadro de herramientas (el área de la derecha), escriba text en el campo de búsqueda y arrastre
un widget de Texto (grande) a la superficie de diseño (el área del centro):

Con el widget de Texto (grande) seleccionado en la superficie de diseño, puede usar el panel Propiedades
para cambiar la propiedad Text del widget de Texto (grande) a Enter a Phoneword: como se muestra a
continuación:
Después, arrastre un widget de Texto sin formato del Cuadro de herramientas a la superficie de diseño y
colóquelo debajo del widget de Texto (grande) . Tenga en cuenta que puede usar el campo de búsqueda para
ayudarle a buscar widgets por el nombre:

Con el widget de Texto sin formato seleccionado en la superficie de diseño, puede usar el panel Propiedades
para cambiar la propiedad Id del widget de Texto sin formato a @+id/PhoneNumberText y cambiar la
propiedad Text a 1-855-XAMARIN :

Arrastre un Botón del Cuadro de herramientas a la superficie de diseño y colóquelo debajo del widget de
Texto sin formato:
Con el Botón seleccionado en la superficie de diseño, puede usar el panel Propiedades para cambiar la
propiedad Id del Botón a @+id/TranslateButton y cambiar la propiedad Text a Translate :

Arrastre la vista de texto desde Cuadro de herramientas hasta la superficie de diseño y colóquela debajo del
widget Botón. Con la vista de texto seleccionada, establezca la propiedad id de la vista de texto en
@+id/TranslatedPhoneWord y cambie el text por una cadena vacía:

Guarde su trabajo presionando ⌘ + S.

Escritura de algo de código


Ahora, agregue código para convertir números de teléfono de formato alfanumérico a numérico. Agregue un
nuevo archivo al proyecto haciendo clic en el icono de engranaje junto al proyecto Phoneword en el panel de
Solución y seleccionando Agregar > Nuevo archivo... :
En el cuadro de diálogo Nuevo archivo, haga clic en General > Clase vacía, asigne al archivo nuevo el
nombre PhoneTranslator y haga clic en Nuevo. Esto crea una nueva clase de C# vacía.
Quite todo el código de plantilla de la clase nueva y reemplácelo por el siguiente código:
using System.Text;
using System;
namespace Core
{
public static class PhonewordTranslator
{
public static string ToNumber(string raw)
{
if (string.IsNullOrWhiteSpace(raw))
return "";
else
raw = raw.ToUpperInvariant();

var newNumber = new StringBuilder();


foreach (var c in raw)
{
if (" -0123456789".Contains(c))
{
newNumber.Append(c);
}
else
{
var result = TranslateToNumber(c);
if (result != null)
newNumber.Append(result);
}
// otherwise we've skipped a non-numeric char
}
return newNumber.ToString();
}
static bool Contains (this string keyString, char c)
{
return keyString.IndexOf(c) >= 0;
}
static int? TranslateToNumber(char c)
{
if ("ABC".Contains(c))
return 2;
else if ("DEF".Contains(c))
return 3;
else if ("GHI".Contains(c))
return 4;
else if ("JKL".Contains(c))
return 5;
else if ("MNO".Contains(c))
return 6;
else if ("PQRS".Contains(c))
return 7;
else if ("TUV".Contains(c))
return 8;
else if ("WXYZ".Contains(c))
return 9;
return null;
}
}
}

Guarde los cambios en PhoneTranslator.cs pulsando Archivo > Guardar (o presionando ⌘ + S ) y cierre el
archivo. Asegúrese de que no hay errores de tiempo de compilación al volver a compilar la solución.

Conectar la interfaz de usuario


El siguiente paso consiste en agregar código para conectar la interfaz de usuario al agregar código auxiliar en la
clase MainActivity . Haga doble clic en el archivo MainActivity.cs en Panel de solución para abrirlo.
Para empezar, agregue un controlador de eventos al botón Traducir. En la clase MainActivity , busque el
método OnCreate . Agregue el código de botón dentro de OnCreate , debajo de las llamadas a
base.OnCreate(bundle) y SetContentView (Resource.Layout.Main) . Quite cualquier código de control de botón
existente (es decir, cualquier código que hace referencia a Resource.Id.myButton y crea un controlador de clic
para él) de manera que el método OnCreate tenga el aspecto siguiente:

using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;

namespace Phoneword
{
[Activity (Label = "Phone Word", MainLauncher = true)]
public class MainActivity : Activity
{
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);

// Set our view from the "main" layout resource


SetContentView (Resource.Layout.Main);

// Our code will go here


}
}
}

Después, se necesita una referencia de los controles que se han creado en el archivo de diseño con Android
Designer. Agregue el código siguiente dentro del método OnCreate (después de la llamada a SetContentView ):

// Get our UI controls from the loaded layout


EditText phoneNumberText = FindViewById<EditText>(Resource.Id.PhoneNumberText);
TextView translatedPhoneWord = FindViewById<TextView>(Resource.Id.TranslatedPhoneWord);
Button translateButton = FindViewById<Button>(Resource.Id.TranslateButton);

Agregue el código que responda a las pulsaciones del usuario del botón Traducir agregando el siguiente
código al método OnCreate (después de las líneas que se han agregado en el último paso):

// Add code to translate number


string translatedNumber = string.Empty;

translateButton.Click += (sender, e) =>


{
// Translate user's alphanumeric phone number to numeric
translatedNumber = PhonewordTranslator.ToNumber(phoneNumberText.Text);
if (string.IsNullOrWhiteSpace(translatedNumber))
{
translatedPhoneWord.Text = string.Empty;
}
else
{
translatedPhoneWord.Text = translatedNumber;
}
};

Guarde el trabajo y compile la aplicación seleccionando Compilar > Compilar todo (o presionando ⌘ + B ).
Si la aplicación se compila, obtendrá un mensaje de operación correcta en la parte superior de Visual Studio
para Mac:
Si hay errores, repase los pasos anteriores y corrija cualquier error hasta que la aplicación se compile
correctamente. Si obtiene un error de compilación como El recurso no existe en el contexto actual, compruebe
que el nombre del espacio de nombres en MainActivity.cs coincida con el nombre del proyecto ( Phoneword ) y,
después, recompile completamente la solución. Si sigue obteniendo errores de compilación, compruebe que ha
instalado las últimas actualizaciones de Xamarin.Android y Visual Studio para Mac.

Establecer la etiqueta y el icono de la aplicación


Ahora que tiene una aplicación que funciona, es el momento de agregar los toques finales. Empiece editando
Label para MainActivity . Label es lo que Android muestra en la parte superior de la pantalla para que los
usuarios conozcan el lugar en el que se encuentran en la aplicación. En la parte superior de la clase
MainActivity , cambie Label por Phone Word como se muestra aquí:

namespace Phoneword
{
[Activity (Label = "Phone Word", MainLauncher = true)]
public class MainActivity : Activity
{
...
}
}

Ahora es el momento de establecer el icono de la aplicación. De forma predeterminada, Visual Studio para Mac
proporcionará un icono predeterminado para el proyecto. Elimine estos archivos de la solución y reemplácelos
por otro icono. Expanda la carpeta Recursos en Panel de solución. Observe que hay cinco carpetas que tienen
el prefijo mipmap- y que cada una de estas carpetas contiene un archivo Icon.png:
Es necesario eliminar del proyecto todos estos archivos de icono. Haga clic con el botón derecho en cada uno
de los archivos Icon.png y haga clic en Quitar en el menú contextual:
Haga clic en el botón Eliminar en el cuadro de diálogo.
Luego, descargue y descomprima el conjunto de iconos de aplicación de Xamarin. Este archivo ZIP contiene los
iconos de la aplicación. Todos los iconos son idénticos visualmente, pero se representan correctamente con
resoluciones diferentes en distintos dispositivos con distintas densidades de pantalla. El conjunto de archivos
debe copiarse en el proyecto Xamarin.Android. En Visual Studio para Mac, en Panel de solución, haga clic con
el botón derecho en la carpeta mipmap-hdpi y seleccione Agregar > Agregar archivos:
En el cuadro de diálogo de selección, vaya al directorio descomprimido de los iconos de aplicación de Xamarin
y abra la carpeta mipmap-hdpi. Seleccione Icon.png y haga clic en Abrir.
En el cuadro de diálogo Add File to Folder (Agregar archivo a carpeta) , seleccione Copy the file into the
directory (Copiar el archivo en el directorio) y haga clic en Aceptar:

Repita estos pasos para cada una de las carpetas mipmap- hasta que el contenido de las carpetas de iconos de
aplicación de Xamarin mipmap- se copie en las carpetas mipmap- equivalentes en el proyecto Phoneword.
Después de copiar todos los iconos en el proyecto de Xamarin.Android, abra el cuadro de diálogo Opciones
del proyecto haciendo clic con el botón derecho en el proyecto en Panel de solución. Haga clic en Compilar
> Aplicación de Android y seleccione @mipmap/icon en el cuadro combinado Icono de aplicación:
Ejecutar la aplicación
Por último, pruebe la aplicación ejecutándola en un dispositivo o emulador Android y traduciendo un
Phoneword:

Para ejecutar la aplicación en un dispositivo Android, vea cómo configurar el dispositivo para el desarrollo.
Ha completado su primera aplicación de Xamarin.Android. Ahora es el momento de analizar las herramientas y
los conocimientos que ha aprendido. Lo siguiente es el Análisis detallado de Hello, Android.

Vínculos relacionados
Iconos de aplicación de Xamarin para Android (ZIP )
Phoneword (ejemplo)
Hello, Android: profundización
05/08/2019 • 38 minutes to read • Edit Online

Esta guía en dos partes le ayudará a compilar su primera aplicación de Xamarin.Android y a comprender los
aspectos básicos del desarrollo de aplicaciones de Android con Xamarin. A lo largo del proceso, le presentaremos
las herramientas, los conceptos y los pasos necesarios para compilar e implementar una aplicación de
Xamarin.Android.
En Hello, Android Quickstart (Guía de inicio rápido de Hello, Android), compiló y ejecutó su primera aplicación de
Xamarin.Android. Ahora ha llegado el momento de que conozca mejor la manera en que funcionan las
aplicaciones de Android para que pueda crear programas más sofisticados. En esta guía se repasan los pasos que
llevó a cabo en el tutorial de Hello, Android para que entienda lo que hizo y empiece a asimilar los aspectos
básicos del desarrollo de aplicaciones de Android.
En esta guía se tratan los temas siguientes:
Introducción a Visual Studio: Introducción a Visual Studio y creación de una aplicación de
Xamarin.Android.
Anatomía de una aplicación de Xamarin.Android: Paseo por las partes esenciales de una aplicación de
Xamarin.Android.
Aspectos básicos de la arquitectura y la aplicación: Introducción a las actividades, el manifiesto de
Android y la esencia del desarrollo de Android.
Interfaz de usuario (UI ) : Creación de interfaces de usuario con Android Designer.
Actividades y ciclo de vida de la actividad: Una introducción al ciclo de vida de la actividad y a la
inserción de la interfaz de usuario en el código.
Pruebas, implementación y toques finales: Finalización de la aplicación con consejos sobre pruebas,
implementación, generación de material gráfico y mucho más.
Introducción a Visual Studio para Mac: Introducción a Visual Studio para Mac y creación de una nueva
aplicación de Xamarin.Android.
Anatomía de una aplicación de Xamarin.Android: Paseo por las partes esenciales de una aplicación de
Xamarin.Android.
Aspectos básicos de la arquitectura y la aplicación: Introducción a las actividades, el manifiesto de
Android y la esencia del desarrollo de Android.
Interfaz de usuario (UI ) : Creación de interfaces de usuario con Android Designer.
Actividades y ciclo de vida de la actividad: Una introducción al ciclo de vida de la actividad y a la
inserción de la interfaz de usuario en el código.
Pruebas, implementación y toques finales: Finalización de la aplicación con consejos sobre pruebas,
implementación, generación de material gráfico y mucho más.
Esta guía le ayuda a desarrollar las habilidades y los conocimientos necesarios para compilar una aplicación de
Android de una sola pantalla. Cuando la haya finalizado, podrá comprender las diferentes partes de una
aplicación de Xamarin.Android y cómo encajan entre sí.

Introducción a Visual Studio


Introducción a Visual Studio
Visual Studio es un IDE muy completo de Microsoft. Incluye un diseñador visual completamente integrado, un
editor de texto con herramientas de refactorización, un explorador de ensamblados, integración de código fuente
y mucho más. Con esta guía, aprenderá a usar algunas características básicas de Visual Studio con el
complemento Xamarin.
Visual Studio organiza el código en soluciones y proyectos. Una solución es un contenedor que puede incluir uno
o varios proyectos. Un proyecto puede ser una aplicación (por ejemplo, para iOS o Android), una biblioteca
auxiliar, una aplicación de prueba, etc. En la aplicación Phoneword, ha agregado un nuevo proyecto de Android
con la plantilla Aplicación de Android a la solución Phoneword creada en la guía de Hello, Android.

Introducción a Visual Studio para Mac


Visual Studio para Mac es un IDE gratuito y de código abierto similar a Visual Studio. Incluye un diseñador visual
completamente integrado, un editor de texto completo con herramientas de refactorización, un explorador de
ensamblados, integración de código fuente y mucho más. Con esta guía aprenderá a usar algunas características
básicas de Visual Studio para Mac. Si no está familiarizado con Visual Studio para Mac, tal vez le interese
consultar Introduction to Visual Studio for Mac (Introducción a Visual Studio para Mac), que incluye información
más detallada.
Visual Studio para Mac sigue la práctica de Visual Studio consistente en organizar el código en soluciones y
proyectos. Una solución es un contenedor que puede incluir uno o varios proyectos. Un proyecto puede ser una
aplicación (por ejemplo, para iOS o Android), una biblioteca auxiliar, una aplicación de prueba, etc. En la aplicación
Phoneword, ha agregado un nuevo proyecto de Android con la plantilla Aplicación de Android a la solución
Phoneword creada en la guía de Hello, Android.

Anatomía de una aplicación de Xamarin.Android


En la captura de pantalla siguiente se muestra el contenido de la solución. Este es el Explorador de soluciones, que
contiene la estructura de directorios y todos los archivos asociados a la solución:

En la captura de pantalla siguiente se muestra el contenido de la solución. Este es el Panel de solución, que
contiene la estructura de directorios y todos los archivos asociados a la solución:
Se ha creado una solución denominada Phoneword y se ha colocado dentro el proyecto de Android
Phoneword.
Observe los elementos situados dentro del proyecto y fíjese en cada carpeta y su finalidad:
Propiedades: Contiene el archivo AndroidManifest.xml, que describe todos los requisitos de la aplicación
de Xamarin.Android, incluidos el nombre, el número de versión y los permisos. La carpeta Propiedades
también contiene AssemblyInfo.cs, un archivo de metadatos de ensamblado .NET. Se recomienda que
incluya en este archivo información básica sobre la aplicación.
Referencias: Contiene los ensamblados necesarios para compilar y ejecutar la aplicación. Si expande el
directorio Referencias, verá referencias a ensamblados .NET, como System, System.Core y System.Xml, así
como una referencia al ensamblado Mono.Android de Xamarin.
Activos: Contiene los archivos que la aplicación necesita para ejecutarse, como fuentes, archivos de datos
locales y archivos de texto. Se puede acceder a los archivos incluidos aquí mediante la clase generada
Assets . Para obtener más información sobre los activos de Android, consulte la guía de Xamarin Using
Android Assets (Uso de activos de Android).
Recursos: Contiene recursos de la aplicación, como cadenas, imágenes y diseños. Puede tener acceso a
estos recursos en el código mediante la clase generada Resource . La guía Android Resources (Recursos de
Android) proporciona información detallada sobre el directorio Recursos. La plantilla de aplicación
también incluye una guía concisa sobre los recursos en el archivo AboutResources.txt.
Recursos
El directorio Recursos contiene cuatro carpetas denominadas drawable, layout, mipmap y values, así como un
archivo llamado Resource.designer.cs.
Los elementos se resumen en la tabla siguiente:
drawable: El directorio drawable contiene recursos que se pueden dibujar, como imágenes y mapas de
bits.
mipmap: El directorio mipmap contiene archivos drawable para distintas densidades de los iconos de
iniciadores. En la plantilla predeterminada, el directorio drawable contiene el archivo del icono de la
aplicación, Icon.png.
layout: El directorio layout contiene archivos de Android Designer (.axml), que definen la interfaz de usuario
de cada pantalla o actividad. La plantilla crea un diseño predeterminado denominado activity_main.axml.
layout: El directorio layout contiene archivos de Android Designer (.axml), que definen la interfaz de usuario
de cada pantalla o actividad. La plantilla crea un diseño predeterminado denominado Main.axml.
values: Este directorio contiene archivos XML que almacenan valores simples, como cadenas, enteros y
colores. La plantilla crea un archivo para almacenar valores de cadena denominado Strings.xml.
Resource.designer.cs: También conocido como la clase Resource , este archivo es una clase parcial que
contiene los identificadores únicos asignados a cada recurso. Lo crean automáticamente las herramientas
de Xamarin.Android y se vuelve a generar según sea necesario. Este archivo no se debe editar
manualmente, ya que Xamarin.Android sobrescribirá todos los cambios manuales que se realicen en él.

Aspectos básicos de la arquitectura y la aplicación


Las aplicaciones de Android no tienen un solo punto de entrada, es decir, no hay una única línea de código en la
aplicación que el sistema operativo llame para iniciar la aplicación. En su lugar, una aplicación se inicia cuando
Android crea una instancia de una de sus clases, durante lo cual Android carga el proceso completo de la
aplicación en la memoria.
Esta función exclusiva de Android puede ser muy útil al diseñar aplicaciones complicadas o interactuar con el
sistema operativo Android. Pero estas opciones también hacen que Android sea complejo cuando se trabaja con
un escenario básico como la aplicación Phoneword. Por este motivo, la exploración de la arquitectura de Android
se divide en dos partes. En esta guía se analiza una aplicación que usa el punto de entrada más común de una
aplicación de Android: la primera pantalla. En Hello, Android Multiscreen se exploran todas las complejidades de
la arquitectura de Android a medida que se describen las distintas formas de iniciar una aplicación.
Escenario de Phoneword: empezar con una actividad
Cuando se abre la aplicación Phoneword por primera vez en un emulador o un dispositivo, el sistema operativo
crea la primera actividad. Una actividad es una clase especial de Android que se corresponde con una sola
pantalla de la aplicación y es responsable de dibujar y activar la interfaz de usuario. Cuando Android crea la
primera actividad de la aplicación, carga toda la aplicación:
Dado que no existe una progresión lineal en una aplicación de Android (puede iniciar la aplicación desde varios
puntos), Android tiene una sola manera de realizar un seguimiento de las clases y los archivos que componen una
aplicación. En el ejemplo de Phoneword, todas las partes que componen la aplicación se registran con un archivo
XML especial denominado manifiesto de Android. La función del manifiesto de Android consiste en realizar
un seguimiento del contenido, las propiedades y los permisos de una aplicación y comunicárselos al sistema
operativo Android. La aplicación Phoneword puede considerarse como una sola actividad (pantalla) y una
colección de archivos del asistente y de recursos unidos mediante el archivo de manifiesto de Android, como se
muestra en el diagrama siguiente:
En las secciones siguientes se exploran las relaciones entre las distintas partes de la aplicación Phoneword, para
que entienda mejor el diagrama anterior. Esta exploración comienza con la interfaz de usuario y analiza cuestiones
como los archivos de diseño y Android Designer.

Interfaz de usuario
TIP
Las versiones más recientes de Visual Studio admiten la apertura de archivos .xml dentro de Android Designer.
Android Designer admite tanto archivos .axml como .xml.

activity_main.axml es el archivo de diseño de la interfaz de usuario de la primera pantalla de la aplicación. La


extensión .axml indica que se trata de un archivo de Android Designer (AXML significa XML de Android). El
nombre Main es arbitrario desde el punto de vista de Android, es decir, el archivo de diseño podría tener otro
nombre. Cuando se abre activity_main.axml en el IDE, aparece el editor visual de los archivos de diseño de
Android, denominado Android Designer:
En la aplicación Phoneword, el identificador de TranslateButton está establecido en @+id/TranslateButton :

Main.axml es el archivo de diseño de la interfaz de usuario de la primera pantalla de la aplicación. La extensión


.axml indica que se trata de un archivo de Android Designer (AXML significa XML de Android). El nombre Main
es arbitrario desde el punto de vista de Android, es decir, el archivo de diseño podría tener otro nombre. Cuando
se abre Main.axml en el IDE, aparece el editor visual de los archivos de diseño de Android, denominado Android
Designer:
En la aplicación Phoneword, el identificador de TranslateButton está establecido en @+id/TranslateButton :

Al establecer la propiedad id de TranslateButton, Android Designer asigna el control TranslateButton a la


clase Resource y le asigna un identificador de recurso de TranslateButton . Esta asignación de un control visual a
una clase hace posible la ubicación y el uso de TranslateButton y otros controles en el código de la aplicación.
Esto se explicará con más detalle cuando se analice el código que activa los controles. Lo único que necesita saber
por ahora es que la representación del código de un control está vinculada a la representación visual del control
en el diseñador mediante la propiedad id .
Vista Código fuente
Todos los elementos definidos en la superficie de diseño se traducen a XML para que Xamarin.Android los pueda
usar. Android Designer proporciona una vista de código fuente que contiene el XML que se generó desde el
diseñador visual. Para ver este código XML, cambie al panel de código fuente situado en la parte inferior
izquierda de la vista del diseñador, como se muestra en la siguiente captura de pantalla:
Este código fuente XML debe contener cuatro elementos de control: dos TextView, un EditText y un Button.
Para obtener más información sobre Android Designer, consulte la guía Designer Overview (Introducción al
diseñador) de Xamarin Android.
Ya hemos visto las herramientas y los conceptos relacionados con la parte visual de la interfaz de usuario. Ahora
veremos el código que activa la interfaz de usuario mientras exploramos las actividades y el ciclo de vida de la
actividad.

Actividades y ciclo de vida de actividad


La clase Activity contiene el código que activa la interfaz de usuario. La actividad es responsable de responder a
la interacción del usuario y de crear una experiencia de usuario dinámica. En esta sección se presenta la clase
Activity , se describe el ciclo de vida de la actividad y se analiza el código que activa la interfaz de usuario de la
aplicación Phoneword.
Clase de la actividad
La aplicación Phoneword tiene una sola pantalla (actividad). La clase que activa la pantalla se denomina
MainActivity y se encuentra en el archivo MainActivity.cs. El nombre MainActivity no tiene especial
importancia en Android: aunque la convención es que el nombre de la primera actividad de una aplicación sea
MainActivity , a Android no le importa si se le asigna otro nombre.

Al abrir MainActivity.cs, puede ver que la clase MainActivity es una subclase de la clase Activity y que la
actividad está adornada con el atributo Activity:

[Activity (Label = "Phone Word", MainLauncher = true)]


public class MainActivity : Activity
{
...
}

El atributo Activity registra la actividad con el manifiesto de Android, lo que permite a Android saber que esta
clase forma parte de la aplicación Phoneword administrada por este manifiesto. La propiedad Label establece
el texto que se mostrará en la parte superior de la pantalla.
La propiedad MainLauncher le indica a Android que debe mostrar esta actividad cuando se inicia la aplicación.
Esta propiedad cobra importancia a medida que se agregan más actividades (pantallas) a la aplicación, como se
explica en la guía Hello, Android Multiscreen.
Ahora que ya hemos visto los aspectos básicos de MainActivity , vamos a profundizar en el código de la
actividad. Para ello, introduciremos el ciclo de vida de la actividad.
Ciclo de vida de la actividad
En Android, las actividades pasan por distintas fases de un ciclo de vida en función de sus interacciones con el
usuario. Las actividades se pueden crear, iniciar, pausar, reanudar, destruir, etc.La clase Activity contiene
métodos que el sistema llama en determinados momentos del ciclo de vida de la pantalla. En el diagrama
siguiente se ilustra la vida típica de una actividad, así como algunos de los métodos correspondientes del ciclo de
vida:
Si invalida los métodos Activity del ciclo de vida, puede controlar cómo se carga la actividad, cómo reacciona al
usuario e incluso qué sucede después de que desaparezca de la pantalla del dispositivo. Por ejemplo, puede
invalidar los métodos del ciclo de vida del diagrama anterior para realizar algunas tareas importantes:
OnCreate: Crea vistas, inicializa las variables y realiza otras tareas de preparación que se deben realizar
antes de que el usuario vea la actividad. Solo se llama una vez a este método cuando la actividad se carga
en memoria.
OnResume: Realiza las tareas que se deben llevar a cabo cada vez que la actividad vuelve a la pantalla del
dispositivo.
OnPause: Realiza las tareas que se deben llevar a cabo cada vez que la actividad sale de la pantalla del
dispositivo.
Al agregar código personalizado a un método del ciclo de vida en Activity , invalida la implementación base de
dicho método. Pulse el método del ciclo de vida existente (que ya tiene código asociado) y amplíe dicho método
con su propio código. Llame a la implementación base desde dentro del método para asegurarse de que el código
original se ejecuta antes que el código nuevo. En la sección siguiente se muestra un ejemplo.
El ciclo de vida de la actividad es una parte importante y compleja de Android. Si quiere obtener más información
sobre las actividades cuando finalice la serie de introducción, lea la guía Activity Lifecycle (Ciclo de vida de la
actividad). En esta guía, el aspecto siguiente en el que nos centraremos es la primera fase del ciclo de vida de la
actividad, OnCreate .
OnCreate
Android llama al método OnCreate de Activity cuando crea la actividad (antes de que se muestre la pantalla al
usuario). Puede invalidar el método OnCreate del ciclo de vida para crear vistas y preparar la actividad para el
usuario:

protected override void OnCreate (Bundle bundle)


{
base.OnCreate (bundle);

// Set our view from the "main" layout resource


SetContentView (Resource.Layout.Main);
// Additional setup code will go here
}

En la aplicación Phoneword, lo primero que hay que hacer en OnCreate es cargar la interfaz de usuario creada
en Android Designer. Para cargar la interfaz de usuario, llame a SetContentView y pásele el nombre del diseño de
recursos para el archivo de diseño: activity_main.axml. El diseño se encuentra en Resource.Layout.activity_main
:

SetContentView (Resource.Layout.activity_main);

Cuando MainActivity se inicia, crea una vista que se basa en el contenido del archivo activity_main.axml.
En la aplicación Phoneword, lo primero que hay que hacer en OnCreate es cargar la interfaz de usuario creada
en Android Designer. Para cargar la interfaz de usuario, llame a SetContentView y pásele el nombre del diseño de
recursos para el archivo de diseño: Main.axml. El diseño se encuentra en Resource.Layout.Main :

SetContentView (Resource.Layout.Main);

Cuando MainActivity se inicia, crea una vista que se basa en el contenido del archivo Main.axml. Tenga en
cuenta que el nombre del archivo de diseño se hace coincidir con el nombre de la actividad (Main.axml es el
diseño de MainActivity). Esto no es necesario desde el punto de vista de Android, pero a medida que agregue más
pantallas a la aplicación, descubrirá que esta convención de nomenclatura permite que sea más fácil hacer
coincidir el archivo de código con el archivo de diseño.
Después de preparar el archivo de diseño, puede empezar a buscar los controles. Para buscar un control, llame a
FindViewById y pase el identificador de recurso del control:

EditText phoneNumberText = FindViewById<EditText>(Resource.Id.PhoneNumberText);


Button translateButton = FindViewById<Button>(Resource.Id.TranslateButton);
TextView translatedPhoneWord = FindViewById<TextView>(Resource.Id.TranslatedPhoneWord);

Ahora que tiene referencias a los controles en el archivo de diseño, puede empezar a programarlos para que
respondan a la interacción del usuario.
Responder a la interacción del usuario
En Android, el evento Click escucha la entrada táctil del usuario. En esta aplicación, el evento Click se ha
controlado con una expresión lambda, pero en su lugar se podría usar un delegado o un controlador de eventos
con nombre. El código final de TranslateButton se parece a lo siguiente:

translateButton.Click += (sender, e) =>


{
// Translate user's alphanumeric phone number to numeric
translatedNumber = PhonewordTranslator.ToNumber(phoneNumberText.Text);
if (string.IsNullOrWhiteSpace(translatedNumber))
{
translatedPhoneWord.Text = string.Empty;
}
else
{
translatedPhoneWord.Text = translatedNumber;
}
};

Pruebas, implementación y toques finales


Tanto Visual Studio para Mac como Visual Studio ofrecen numerosas opciones para probar e implementar una
aplicación. En esta sección se incluyen las opciones de depuración, se muestra cómo probar las aplicaciones en un
dispositivo y se presentan herramientas para crear iconos de aplicación personalizados para densidades de
pantalla diferentes.
Herramientas de depuración
Los problemas relacionados con el código de la aplicación pueden ser difíciles de diagnosticar. Para ayudar a
diagnosticar problemas de código complejo, puede establecer un punto de interrupción, examinar el código o
enviar información a la ventana de registro.
Implementar en un dispositivo
El emulador es un buen punto de partida para implementar y probar una aplicación, pero los usuarios no usarán
la aplicación final en un emulador. Conviene probar las aplicaciones en un dispositivo real desde una fase inicial y
con frecuencia.
Para que un dispositivo Android se pueda usar para probar aplicaciones, debe estar configurado para el
desarrollo. En la guía Set Up Device for Development (Configurar el dispositivo para el desarrollo) se
proporcionan instrucciones precisas sobre cómo preparar un dispositivo para el desarrollo.
Una vez que haya configurado el dispositivo, puede implementar en él. Para ello, conéctelo, selecciónelo en el
cuadro de diálogo Seleccionar dispositivo e inicie la aplicación:
Una vez que haya configurado el dispositivo, puede implementar en él. Para ello, conéctelo, pulse Inicio
(Reproducir) , selecciónelo en el cuadro de diálogo Seleccionar dispositivo y pulse Aceptar:

De este modo se inicia la aplicación en el dispositivo:

Establecer iconos para densidades de pantalla diferentes


Los dispositivos Android tienen tamaños de pantalla y resoluciones diferentes, y no todas las imágenes se
muestran correctamente en todas las pantallas. Por ejemplo, a continuación se muestra una captura de pantalla de
un icono de baja densidad en un Nexus 5 de alta densidad. Observe lo borroso que se ve en comparación con los
iconos que lo rodean:

Para resolverlo, se recomienda agregar iconos de distintas resoluciones en la carpeta Recursos. Android
proporciona versiones diferentes de la carpeta mipmap para gestionar los iconos de los iniciadores de
densidades diferentes: mdpi para pantallas de densidad media, hdpi para pantallas de alta densidad y xhdpi,
xxhdpi y xxxhdpi para pantallas de muy alta densidad. Los iconos de tamaños diferentes se almacenan en las
carpetas mipmap- correspondientes:
Android seleccionará el icono de la densidad adecuada:
Generar iconos personalizados
No todos tienen a su disposición un diseñador para crear los iconos e imágenes de inicio personalizados que una
aplicación necesita para destacar. A continuación se indican varios enfoques alternativos para generar material
gráfico personalizado para la aplicación:
Android Asset Studio: Se trata de un generador dentro del explorador y basado en web para todo tipo de
iconos de Android, con vínculos a otras herramientas útiles de la comunidad. Funciona mejor en Google
Chrome.
Visual Studio: Puede usarlo para crear un conjunto de iconos sencillo para la aplicación directamente en el
IDE.
Glyphish: Conjuntos de iconos prediseñados de alta calidad que se pueden comprar o descargar de forma
gratuita.
Fiverr: Elija entre diversos diseñadores para que creen para usted un conjunto de iconos a partir de 5 $.
Probablemente elegirá un diseñador al azar, pero se trata de un buen recurso si necesita que le diseñen
iconos sobre la marcha.
Android Asset Studio: Se trata de un generador dentro del explorador y basado en web para todo tipo de
iconos de Android, con vínculos a otras herramientas útiles de la comunidad. Funciona mejor en Google
Chrome.
Sketch 3: Sketch es una aplicación de Mac para diseñar interfaces de usuario, iconos y mucho más. Es la
aplicación que se usó para diseñar el conjunto de iconos de aplicación e imágenes de inicio de Xamarin.
Sketch 3 está disponible en App Store y cuesta aproximadamente 80 $. También puede probar la versión
gratuita Sketch Tool.
Pixelmator: Una aplicación versátil de edición de imágenes para Mac que cuesta aproximadamente 30 $.
Glyphish: Conjuntos de iconos prediseñados de alta calidad que se pueden comprar o descargar de forma
gratuita.
Fiverr: Elija entre diversos diseñadores para que creen para usted un conjunto de iconos a partir de 5 $.
Probablemente elegirá un diseñador al azar, pero se trata de un buen recurso si necesita que le diseñen
iconos sobre la marcha.
Para obtener más información sobre los tamaños de icono y los requisitos, consulte la guía Android Resources
(Recursos de Android).
Agregar paquetes de Google Play Services
Google Play Services es un conjunto de bibliotecas de complementos que permite a los desarrolladores de
Android aprovechar las características más recientes de Google, como Google Maps, Google Cloud Messaging e
In-App Billing. Antes, Xamarin proporcionaba enlaces a todas las bibliotecas de Google Play Services en forma de
un único paquete, pero a partir de Visual Studio para Mac, hay un nuevo cuadro de diálogo de proyecto para
seleccionar los paquetes de Google Play Services que se incluyen en la aplicación.
Para agregar una o más bibliotecas de Google Play Services, haga clic con el botón derecho en el nodo Paquetes
del árbol del proyecto y haga clic en Add Google Play Services… (Agregar Google Play Services…):

Cuando aparezca el cuadro de diálogo Add Google Play Services… (Agregar Google Play Services…),
seleccione los paquetes (NuGet) que quiere agregar al proyecto:

Al seleccionar un servicio y hacer clic en Agregar paquete, Visual Studio para Mac descarga e instala el paquete
que seleccione, así como los paquetes dependientes de Google Play Services que requiere. En algunos casos,
podría ver un cuadro de diálogo de Aceptación de la licencia que le solicita que haga clic en Aceptar para que
se instalen los paquetes:

Resumen
¡ Enhorabuena! Ahora ya debería conocer bien los componentes de una aplicación de Xamarin.Android, así como
las herramientas necesarias para crearla.
En el siguiente tutorial de la serie de introducción, podrá ampliar la aplicación para que controle varias pantallas a
medida que explora la arquitectura y conceptos más avanzados de Android.
Multipantalla de Hello, Android
18/07/2019 • 2 minutes to read • Edit Online

En esta guía de dos partes, ampliará la aplicación Phoneword que ha creado en la guía Hello, Android a fin de
administrar una segunda pantalla. A lo largo de esta guía se ofrecen los componentes básicos de la aplicación
Android y se profundiza en la arquitectura Android a medida que conoce mejor la estructura y la funcionalidad
de la aplicación Android.

Parte 1: inicio rápido


En la primera parte de esta guía, agregará una segunda pantalla a la aplicación Phoneword para realizar un
seguimiento del historial de los números a los que se ha llamado mediante la aplicación. La aplicación final
mostrará una segunda pantalla en que se enumera el historial de llamadas.

Parte 2: profundización
En la segunda parte de este documento, revisaremos lo que ha creado y explicaremos la arquitectura, la
navegación y otros conceptos nuevos de Android que surjan durante el proceso.

Vínculos relacionados
Introducción a Android
Depurar en Visual Studio
Recetas de Visual Studio para Mac: Depuración
Hello, Android Multiscreen: Inicio rápido
05/08/2019 • 13 minutes to read • Edit Online

Esta guía de dos partes expande la aplicación Phoneword para controlar una segunda pantalla. Por el camino, se
presentan bloques de creación básicos de aplicaciones Android con un análisis más profundo de la arquitectura
de Android.
En la parte del tutorial de esta guía agregará una segunda pantalla a la aplicación Phoneword para realizar un
seguimiento del historial de números traducidos mediante la aplicación. La aplicación final tendrá una segunda
pantalla en la que se mostrarán los números "traducidos", como se muestra en la captura de pantalla de la
derecha:

La sección complementaria Análisis detallado revisa lo que se creó y describe la arquitectura, la navegación y
otros conceptos de Android nuevos que encontrará en el camino.

Requisitos
Dado que esta guía continúa desde donde lo deja Hello, Android, requiere la finalización de Hello, Android: inicio
rápido. Si quiere pasar directamente al tutorial siguiente, puede descargar la versión completa de Phoneword (de
Hello, Android: inicio rápido) y usarla para empezar el tutorial.

Tutorial
En este tutorial agregará una pantalla Translation History (Historial de traducciones) a la aplicación
Phoneword.
Para empezar, abra la aplicación Phoneword en Visual Studio y edite el archivo Main.axml en el Explorador de
soluciones.

TIP
Las versiones más recientes de Visual Studio admiten la apertura de archivos .xml dentro de Android Designer.
Android Designer admite tanto archivos .axml como .xml.

Actualización del diseño


En el cuadro de herramientas, arrastre un botón hasta la superficie de diseño y colóquelo debajo de la vista de
texto TranslatedPhoneWord. En el panel Propiedades, cambie el Id del botón por
@+id/TranslationHistoryButton .

Establezca la propiedad Text del botón en @string/translationHistory . Android Designer lo interpretará


literalmente, pero va a realizar algunos cambios para que el texto del botón se muestre correctamente:

Expanda el nodo valores bajo la carpeta Recursos en el Explorador de soluciones y haga doble clic en el
archivo de recursos de cadena, Strings.xml:
Agregue el nombre y el valor de cadena translationHistory al archivo Strings.xml y guárdelo:

<?xml version="1.0" encoding="utf-8"?>


<resources>
<string name="translationHistory">Translation History</string>
<string name="ApplicationName">Phoneword</string>
</resources>

El texto del botón Translation History (Historial de traducciones) debería actualizarse para reflejar el nuevo valor
de cadena:

Con el botón Translation History (Historial de traducciones) seleccionado en la superficie de diseño, busque el
ajuste enabled en el panel Propiedades y establezca su valor en false para deshabilitar el botón. Esto hará que
el botón se vuelva más oscuro en la superficie de diseño:
Creación de la segunda actividad
Cree una segunda actividad para activar la segunda pantalla. En el Explorador de soluciones, haga clic con el
botón derecho en el proyecto Phoneword y seleccione Agregar > Nuevo elemento... :

En el cuadro de diálogo Agregar nuevo elemento, seleccione Visual C# > Actividad y asigne al archivo de
actividad el nombre TranslationHistoryActivity.cs.
Reemplace el código de plantilla de TranslationHistoryActivity.cs por lo siguiente:

using System;
using System.Collections.Generic;
using Android.App;
using Android.OS;
using Android.Widget;
namespace Phoneword
{
[Activity(Label = "@string/translationHistory")]
public class TranslationHistoryActivity : ListActivity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Create your application here
var phoneNumbers = Intent.Extras.GetStringArrayList("phone_numbers") ?? new string[0];
this.ListAdapter = new ArrayAdapter<string>(this, Android.Resource.Layout.SimpleListItem1,
phoneNumbers);
}
}
}
En esta clase, se crea una ListActivity y se rellena mediante programación, por lo que no es necesario crear un
nuevo archivo de diseño para esta actividad. Esto se explica con más detalle en Hello, Android Multiscreen:
análisis detallado.
Adición de una lista
Esta aplicación recopila números de teléfono (que el usuario ha traducido en la primera pantalla) y los pasa a la
segunda pantalla. Los números de teléfono se almacenan como una lista de cadenas. Para admitir listas (y
también Intents, que se usan más adelante), agregue las directivas using siguientes a la parte superior de
MainActivity.cs:

using System.Collections.Generic;
using Android.Content;

Después, cree una lista vacía que se pueda rellenar con números de teléfono. La clase MainActivity tendrá este
aspecto:

[Activity(Label = "Phoneword", MainLauncher = true)]


public class MainActivity : Activity
{
static readonly List<string> phoneNumbers = new List<string>();
...// OnCreate, etc.
}

En la clase MainActivity , agregue el código siguiente para registrar el botón Translation History (Historial de
traducciones) (coloque esta línea después de la declaración translateButton ):

Button translationHistoryButton = FindViewById<Button> (Resource.Id.TranslationHistoryButton);

Agregue el código siguiente al final del método OnCreate para conectar el botón Translation History (Historial
de traducciones):

translationHistoryButton.Click += (sender, e) =>


{
var intent = new Intent(this, typeof(TranslationHistoryActivity));
intent.PutStringArrayListExtra("phone_numbers", phoneNumbers);
StartActivity(intent);
};

Actualice el botón Traducir para agregar el número de teléfono a la lista de phoneNumbers . El controlador Click
de translateButton debería ser similar al código siguiente:
// Add code to translate number
string translatedNumber = string.Empty;
translateButton.Click += (sender, e) =>
{
// Translate user's alphanumeric phone number to numeric
translatedNumber = PhonewordTranslator.ToNumber(phoneNumberText.Text);
if (string.IsNullOrWhiteSpace(translatedNumber))
{
translatedPhoneWord.Text = "";
}
else
{
translatedPhoneWord.Text = translatedNumber;
phoneNumbers.Add(translatedNumber);
translationHistoryButton.Enabled = true;
}
};

Guarde y compile la aplicación para asegurarse de que no existen errores.


Ejecutar la aplicación
Implemente la aplicación en un dispositivo o emulador. En las siguientes capturas de pantalla se muestra la
aplicación Phoneword en ejecución:

Para empezar, abra el proyecto Phoneword en Visual Studio para Mac y edite el archivo Main.axml en Panel de
solución.

TIP
Las versiones más recientes de Visual Studio admiten la apertura de archivos .xml dentro de Android Designer.
Android Designer admite tanto archivos .axml como .xml.

Actualización del diseño


En el cuadro de herramientas, arrastre un botón hasta la superficie de diseño y colóquelo debajo de la vista de
texto TranslatedPhoneWord. En el panel Propiedades, cambie el Id. del botón por
@+id/TranslationHistoryButton :

Establezca la propiedad Text del botón en @string/translationHistory . Android Designer lo interpretará


literalmente, pero va a realizar algunos cambios para que el texto del botón se muestre correctamente:

Expanda el nodo values situado debajo de la carpeta Recursos en Panel de solución y haga doble clic en el
archivo de recursos de cadena, Strings.xml:
Agregue el nombre y el valor de cadena translationHistory al archivo Strings.xml y guárdelo:

<?xml version="1.0" encoding="utf-8"?>


<resources>
<string name="translationHistory">Translation History</string>
<string name="ApplicationName">Phoneword</string>
</resources>

El texto del botón Translation History (Historial de traducciones) debería actualizarse para reflejar el nuevo valor
de cadena:

Con el botón Translation History (Historial de traducciones) seleccionado en la superficie de diseño, abra la
pestaña Comportamiento en el Panel de propiedades y haga doble clic en la casilla Habilitado para
deshabilitar el botón. Esto hará que el botón se vuelva más oscuro en la superficie de diseño:
Creación de la segunda actividad
Cree una segunda actividad para activar la segunda pantalla. En el Panel de solución, haga clic en el icono de
engranaje de color gris junto al proyecto Phoneword y seleccione Agregar > Nuevo archivo... :
En el cuadro de diálogo Nuevo archivo, elija Android > Actividad, asigne a la actividad el nombre
TranslationHistoryActivity y haga clic en Agregar.

Reemplace el código de plantilla de TranslationHistoryActivity con lo siguiente:

using System;
using System.Collections.Generic;
using Android.App;
using Android.OS;
using Android.Widget;
namespace Phoneword
{
[Activity(Label = "@string/translationHistory")]
public class TranslationHistoryActivity : ListActivity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Create your application here
var phoneNumbers = Intent.Extras.GetStringArrayList("phone_numbers") ?? new string[0];
this.ListAdapter = new ArrayAdapter<string>(this, Android.Resource.Layout.SimpleListItem1,
phoneNumbers);
}
}
}

En esta clase, se crea una ListActivity y se rellena mediante programación, por lo que no es necesario crear un
nuevo archivo de diseño para esta actividad. Esto se explica con más detalle en la Hello, Android Multiscreen:
análisis detallado.
Adición de una lista
Esta aplicación recopila números de teléfono (que el usuario ha traducido en la primera pantalla) y los pasa a la
segunda pantalla. Los números de teléfono se almacenan como una lista de cadenas. Para admitir listas (y
también Intents, que se usan más adelante), agregue las directivas using siguientes a la parte superior de
MainActivity.cs:

using System.Collections.Generic;
using Android.Content;

Después, cree una lista vacía que se pueda rellenar con números de teléfono. La clase MainActivity tendrá este
aspecto:

[Activity(Label = "Phoneword", MainLauncher = true)]


public class MainActivity : Activity
{
static readonly List<string> phoneNumbers = new List<string>();
...// OnCreate, etc.
}

En la clase MainActivity , agregue el código siguiente para registrar el botón TranslationHistory (coloque esta
línea después de la declaración TranslationHistoryButton ):
Button translationHistoryButton = FindViewById<Button> (Resource.Id.TranslationHistoryButton);

Agregue el código siguiente al final del método OnCreate para conectar el botón Translation History (Historial
de traducciones):

translationHistoryButton.Click += (sender, e) =>


{
var intent = new Intent(this, typeof(TranslationHistoryActivity));
intent.PutStringArrayListExtra("phone_numbers", phoneNumbers);
StartActivity(intent);
};

Actualice el botón Traducir para agregar el número de teléfono a la lista de phoneNumbers . El controlador Click
de TranslateHistoryButton debería ser similar al código siguiente:

translateButton.Click += (sender, e) =>


{
// Translate user's alphanumeric phone number to numeric
translatedNumber = PhonewordTranslator.ToNumber(phoneNumberText.Text);
if (string.IsNullOrWhiteSpace(translatedNumber))
{
translatedPhoneWord.Text = "";
}
else
{
translatedPhoneWord.Text = translatedNumber;
phoneNumbers.Add(translatedNumber);
translationHistoryButton.Enabled = true;
}
};

Ejecutar la aplicación
Implemente la aplicación en un dispositivo o emulador. En las siguientes capturas de pantalla se muestra la
aplicación Phoneword en ejecución:
Enhorabuena por completar su primera aplicación multipantalla de Xamarin.Android. Ahora es el momento de
analizar minuciosamente las herramientas y los conocimientos que acaba de aprender – a continuación Hello,
Android Multiscreen: análisis detallado.

Vínculos relacionados
Iconos de aplicación y pantallas de inicio (ZIP ) de Xamarin
Phoneword (ejemplo)
PhonewordMultiscreen (ejemplo)
Hello, Android Multiscreen: análisis detallado
11/07/2019 • 13 minutes to read • Edit Online

En esta guía de dos partes, ampliaremos la aplicación Phoneword básica creada en la guía Hello, Android a fin
de controlar una segunda pantalla. Durante el proceso, presentaremos los bloques de compilación de
aplicaciones de Android básicos. Se incluye un análisis más profundo de la arquitectura de Android como ayuda
para entender mejor la funcionalidad y la estructura de las aplicaciones de Android.
En Hello, Android Multiscreen Quickstart (Guía de inicio rápido de Hello, Android Multiscreen), compiló y ejecutó
su primera aplicación de Xamarin.Android.
En esta guía explorará una arquitectura de Android más avanzada. Se explica la navegación de Android con
intenciones y se describen las opciones de navegación del hardware de Android. Además, se analizan las nuevas
adiciones a la aplicación Phoneword a medida que se desarrolla una perspectiva integral de la relación de la
aplicación con el sistema operativo y otras aplicaciones.

Conceptos básicos de la arquitectura de Android


En Análisis detallado de Hello, Android, aprendió que las aplicaciones de Android son programas únicos porque
no tienen un único punto de entrada. En su lugar, el sistema operativo (u otra aplicación) inicia cualquiera de las
actividades registradas de la aplicación que, a su vez, inicia el proceso de la aplicación. Este análisis detallado de la
arquitectura de Android amplía sus conocimientos sobre cómo se construyen las aplicaciones de Android. Para
ello, presenta los bloques de creación de aplicaciones de Android y sus funciones.
Bloques de compilación de aplicaciones de Android
Una aplicación de Android consta de una colección de clases de Android especiales denominadas bloques de
aplicación, empaquetados con una serie de recursos de la aplicación (imágenes, temas, clases del asistente, etc.).
Estos se coordinan mediante un archivo XML denominado manifiesto de Android.
Los bloques de aplicación son la espina dorsal de las aplicaciones de Android, ya que permiten hacer cosas que
normalmente no se pueden hacer con una clase normal. Los dos más importantes son las actividades y los
servicios:
Actividad: una actividad se corresponde con una pantalla con una interfaz de usuario, y como concepto se
parece a una página web de una aplicación web. Por ejemplo, en una aplicación de suministro de noticias,
la pantalla de inicio de sesión será la primera actividad, la lista desplazable de noticias sería otra actividad y
la página de detalles de cada elemento sería la tercera actividad. Puede obtener más información sobre las
actividades en la guía Activity Lifecycle (Ciclo de vida de la actividad).
Servicio: los servicios de Android admiten actividades. Para ello, asumen tareas de ejecución prolongada
y las ejecutan en segundo plano. Los servicios no tiene una interfaz de usuario y se usan para controlar las
tareas que no están vinculadas a pantallas – (por ejemplo, reproducir una canción en segundo plano o
cargar fotografías en un servidor). Para obtener más información sobre los servicios, consulte las guías
Creating Services (Crear servicios) y Android Services (Servicios de Android).
Una aplicación de Android podría no usar todos los tipos de bloques y, a menudo, tiene varios bloques de un
mismo tipo. Por ejemplo, la aplicación Phoneword creada en Hello, Android Quickstart (Guía de inicio rápido de
Hello, Android) estaba formada por una sola actividad (pantalla) y algunos archivos de recursos. Una aplicación
sencilla de reproductor de música podría tener varias actividades y un servicio para reproducir música cuando la
aplicación está en segundo plano.
Intenciones
Otro concepto fundamental en las aplicaciones de Android es la intención. El diseño de Android se basa en el
principio de privilegios mínimos, es decir, las aplicaciones tienen acceso únicamente a los bloques que necesitan
para funcionar y tienen un acceso limitado a los bloques que componen el sistema operativo u otras aplicaciones.
De forma similar, los bloques tienen un acoplamiento flexible, lo que significa que están diseñados para tener un
conocimiento reducido y un acceso limitado a otros bloques (incluso a los bloques que forman parte de la misma
aplicación).
Para comunicarse, los bloques de aplicación envían mensajes asincrónicos denominados intenciones de un lado a
otro. Las intenciones contienen información sobre el bloque de recepción y, en ocasiones, algunos datos. Una
intención que se envía desde un componente de una aplicación desencadena un evento que se produce en otro
componente de la aplicación, lo que vincula a ambos componentes y les permite comunicarse. Mediante el envío
de intenciones de un lado a otro, puede conseguir que los bloques coordinen acciones complejas, como iniciar la
aplicación de cámara para que saque una fotografía y la guarde, recopilar información de ubicación o desplazarse
de una pantalla a la siguiente.
AndroidManifest.XML
Cuando se agrega un bloque a la aplicación, se registra con un archivo XML especial denominado manifiesto de
Android. El manifiesto realiza un seguimiento de todos los bloques de una aplicación, así como de los requisitos
de la versión, los permisos y las bibliotecas – vinculadas, es decir, todo lo que el sistema operativo necesita saber
para que la aplicación se ejecute. El manifiesto de Android también funciona con las actividades y las
intenciones para controlar qué acciones son apropiadas para una actividad determinada. Estas características
avanzadas del manifiesto de Android se tratan en la guía Working with the Android Manifest (Trabajar con el
manifiesto de Android).
En la versión de una sola pantalla de la aplicación Phoneword, solo se usaron una actividad, una intención y
AndroidManifest.xml , junto con recursos adicionales como iconos. En la versión de varias pantallas de
Phoneword se agregó una actividad adicional, que se inició desde la primera actividad mediante una intención.
En la sección siguiente se describe cómo ayudan las intenciones a crear la navegación en aplicaciones de
Android.

Navegación de Android
Para ir de una pantalla a otra se han empleado intenciones. Es el momento de profundizar en este código para
ver cómo funcionan las intenciones y entender su función en la navegación de Android.
Iniciar una segunda actividad con una intención
En la aplicación Phoneword, se usó una intención para iniciar una segunda pantalla (actividad). En primer lugar,
cree una intención. Para ello, pase el contexto actual ( this , que hace referencia al contexto actual) y el tipo de
bloque de aplicación que busca ( TranslationHistoryActivity ):

Intent intent = new Intent(this, typeof(TranslationHistoryActivity));

El contexto es una interfaz para la información global sobre el entorno de aplicación. Permite a los objetos
recién creados saber lo que pasa con la aplicación. Considere la intención como un mensaje: es como si
proporcionara el nombre del destinatario del mensaje ( TranslationHistoryActivity ) y la dirección del receptor (
Context ).

Android proporciona una opción para asociar datos simples a una intención (los datos complejos se controlan de
forma distinta). En el ejemplo de Phoneword, se usa PutStringArrayExtra para asociar una lista de números de
teléfono a la intención y se llama a StartActivity en el destinatario de la intención. El código completo es similar
al siguiente:
translationHistoryButton.Click += (sender, e) =>
{
var intent = new Intent(this, typeof(TranslationHistoryActivity));
intent.PutStringArrayListExtra("phone_numbers", _phoneNumbers);
StartActivity(intent);
};

Otros conceptos presentados en Phoneword


La aplicación Phoneword presentó varios conceptos que no se tratan en esta guía. Entre estos conceptos se
incluyen los siguientes:
Recursos de cadena: en la aplicación Phoneword, el texto de TranslationHistoryButton se estableció en
"@string/translationHistory" . La sintaxis @string significa que el valor de la cadena se almacena en el archivo
de recursos de cadena, Strings.xml. Se agregó en Strings.xml el valor siguiente para la cadena
translationHistory :

<?xml version="1.0" encoding="utf-8"?>


<resources>
<string name="translationHistory">Call History</string>
</resources>

Para obtener más información sobre los recursos de cadena y otros recursos de Android, consulte la guía
Android Resources (Recursos de Android).
ListView y ArrayAdapter: ListView es un componente de interfaz de usuario que proporciona una manera
sencilla de presentar una lista desplazable de filas. Una instancia ListView necesita un adaptador para llenarlo
con los datos que contienen las vistas de la fila. Se usó la siguiente línea de código para rellenar la interfaz de
usuario de TranslationHistoryActivity :

this.ListAdapter = new ArrayAdapter<string>(this, Android.Resource.Layout.SimpleListItem1, phoneNumbers);

Los elementos ListView y los adaptadores están fuera del ámbito de este documento, pero se tratan de manera
exhaustiva en la guía ListViews and Adapters (Elementos ListView y adaptadores). En Relleno de ListView con
datos se trata específicamente el uso de las clases ListActivity y ArrayAdapter integradas para crear y rellenar
un elemento ListView sin definir un diseño personalizado, como se hizo en el ejemplo de Phoneword.

Resumen
Enhorabuena, ha completado su primera aplicación multipantalla de Android. En esta guía se presentaron los
bloques de creación de aplicaciones de Android y las intenciones, y se usaron para compilar una aplicación
multipantalla de Android. Ahora tiene la base necesaria para empezar a desarrollar sus propias aplicaciones de
Xamarin.Android.
Después, aprenderá a compilar aplicaciones multiplataforma con Xamarin con la guía Building Cross-Platform
Applications (Compilar aplicaciones multiplataforma).
Xamarin para desarrolladores de Java
05/08/2019 • 51 minutes to read • Edit Online

Si es usted es desarrollador de Java, ya tiene la posibilidad de empezar a aprovechar sus habilidades y el código
existente de Xamarin en la plataforma Xamarin, al tiempo que disfruta de los beneficios de reutilizar código de C#.
Observará que la sintaxis de C# es muy similar a la sintaxis de Java y que ambos lenguajes ofrecen características
muy similares. Además, encontrará características exclusivas de C# que facilitarán el trabajo a los desarrolladores.

Información general
En este artículo se proporciona una introducción a la programación en C# para los desarrolladores de Java y se
centra principalmente en las características del lenguaje C# con las que se encontrará al desarrollar aplicaciones
Xamarin.Android. Además, en este artículo se explican las diferencias de estas características con respecto a las de
Java y, además, se presentan características importantes de C# (relevantes para Xamarin.Android) que no se
encuentran disponibles en Java. Se incluyen vínculos a material de referencia adicional, para que pueda usar este
artículo como un punto de partida para obtener más información sobre C# y .NET.
Si está familiarizado con Java, no tardará en sentirse cómodo con la sintaxis de C#. La sintaxis de C# es muy
similar a la de Java – C# es un lenguaje "de apertura" como Java, C y C++. En muchos sentidos, la sintaxis de C#
se lee como un superconjunto de la sintaxis de Java, pero con algunas palabras clave agregadas y con el nombre
cambiado.
Muchas características clave de Java pueden encontrarse en C#:
Programación orientada a objetos basados en clases
Tipado fuerte
Compatibilidad con interfaces
Genéricos
Recolección de elementos no utilizados
Compilación en tiempo de ejecución
Java y C# se compilan en un lenguaje intermedio que se ejecuta en un entorno de ejecución administrado. C# y
Java son tipos estáticos, y ambos lenguajes tratan las cadenas como tipos inmutables. Ambos lenguajes utilizan
una jerarquía de clases de raíz única. Al igual que Java, C# solo admite una herencia única y no acepta los métodos
globales. En ambos lenguajes, los objetos se crean en el montón con la palabra clave new y se recoleccionan los
objetos no utilizados cuando ya no se utilizan. Ambos lenguajes ofrecen una compatibilidad formal con el control
de excepciones mediante la semántica try / catch . Los dos ofrecen también compatibilidad con la sincronización
y administración de subprocesos.
No obstante, existen muchas diferencias entre Java y C#. Por ejemplo:
Java no admite las variables locales con tipo implícito (C# admite la palabra clave var ).
En Java, puede pasar parámetros solo por valor, mientras que en C# puede pasarlos tanto por referencia
como por valor. (C# ofrece las palabras clave ref y out para pasar los parámetros por referencia; no hay
ningún equivalente en Java).
Java no admite las directivas de preprocesador como #define .
Java no admite los tipos de enteros sin signo, mientras que C# sí admite los tipos de enteros sin signo como
ulong , uint , ushort y byte .

Java no es compatible con la sobrecarga de operador; en C# se pueden sobrecargar operadores y


conversiones.
En una instrucción Java switch , el código puede pasar a la siguiente sección del modificador; sin embargo,
en C#, el final de cada sección switch debe terminar el modificador (el final de cada sección debe cerrarse
con una instrucción break ).
En Java, puede especificar las excepciones generadas por un método con la palabra clave throws , pero C#
no tiene ningún concepto de excepciones comprobadas; la palabra clave throws no se admite en C#.
C# admite Language Integrated Query (LINQ ), que permite usar las palabras reservadas from , select y
where para escribir consultas de colecciones de forma similar a las consultas de bases de datos.

Por supuesto, hay muchas más diferencias entre C# y Java que pueden tratarse en este artículo. Además, Java y
C# continúan evolucionando (por ejemplo, Java 8, que aún no se encuentra en la cadena de herramientas de
Android, admite expresiones lambda del estilo de C#), por lo que estas diferencias seguirán evolucionando. Aquí
solo se destacan las diferencias más importantes que han detectado los desarrolladores de Java que son nuevos
en Xamarin.Android.
En Pasar del desarrollo en Java al desarrollo en C# se ofrece una introducción a las diferencias
fundamentales entre C# y Java.
En Características de la programación orientada a objetos se explican las diferencias más importantes de la
característica orientada a objetos entre ambos lenguajes.
En Diferencias de palabras claves se ofrece una lista de equivalentes de palabras claves útiles, solo palabras
claves de C# y vínculos a las definiciones de las palabras claves de C#.
C# proporciona muchas características claves de Xamarin.Android que actualmente no están disponibles para los
desarrolladores de Java en Android. Estas características pueden ayudarle a escribir código mejor y en menos
tiempo:
Propiedades – Con el sistema de propiedades de C#, puede acceder a las variables de miembros de forma
segura y directa sin tener que escribir métodos de establecedor y captador.
Expresiones lambda – En C# puede usar métodos anónimos (también denominados lambdas) para
expresar la funcionalidad de forma más sucinta y eficaz. Puede evitar la sobrecarga de tener que escribir
objetos de un solo uso, y puede pasar el estado local a un método sin tener que agregar parámetros.
Control de eventos – C# ofrece compatibilidad a nivel de lenguaje para la programación orientada a
eventos, donde se puede registrar un objeto para recibir una notificación cuando se produzca algún evento
de interés. La palabra clave event define un mecanismo de multidifusión que una clase de publicador
puede usar para informar a los suscriptores de eventos.
Programación asincrónica – Las características de la programación asincrónica de C# ( async / await )
mantienen la capacidad de respuesta de las aplicaciones. La compatibilidad a nivel de lenguaje de esta
característica permite que la programación asincrónica resulte fácil de implementar y que sea menos
propensa a errores.
Además, Xamarin le permite aprovechar los recursos de Java existentes mediante una tecnología que se conoce
como enlaces. Puede llamar al código, los marcos de trabajo y las bibliotecas de Java existentes desde C# con el
uso de generadores de enlaces automáticos de Xamarin. Para ello, basta con crear una biblioteca estática en Java y
exponerla en C# mediante un enlace.
Pasar del desarrollo en Java al desarrollo en C#
En las secciones siguientes se describen las diferencias básicas de "introducción" entre C# y Java; en una sección
posterior se describen las diferencias orientadas a objetos entre estos lenguajes.
Diferencia entre bibliotecas y Ensamblados
Java suele empaquetar clases relacionadas en archivos .jar. Sin embargo, en C# and .NET, los bits reutilizables de
código precompilado se empaquetan en ensamblados, que suelen empaquetarse como archivos .dll. Un
ensamblado es una unidad de implementación de código de C#/.NET, y cada ensamblado suele asociarse con un
proyecto de C#. Los ensamblados contienen código intermedio que se compilan Just-In-Time en tiempo de
ejecución.
Para obtener más información sobre los ensamblados, vea el tema Ensamblados y caché global de ensamblados.
Diferencias entre paquetes y Espacios de nombres
C# usa la palabra clave namespace para agrupar tipos relacionados; es similar a la palabra clave package de Java.
Normalmente, una aplicación de Xamarin.Android residirá en un espacio de nombres creado para esa aplicación.
Por ejemplo, el siguiente código de C# declara el contenedor del espacio de nombres WeatherApp para un
aplicación de información meteorológica:

namespace WeatherApp
{
...

Importación de tipos
Al usar tipos definidos en los espacios de nombres externos, importe estos tipos con una instrucción using (que
es muy similar a la instrucción import de Java). En Java, puede importar un solo tipo con una instrucción similar a
la siguiente:

import javax.swing.JButton

Puede importar un paquete de Java completo con una instrucción como esta:

import javax.swing.*

La instrucción using de C# funciona de forma muy similar, pero permite importar un paquete completo sin
especificar un carácter comodín. Por ejemplo, a menudo verá una serie de instrucciones using al principio de los
archivos de origen de Xamarin.Android, como se observa en este ejemplo:

using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using System.Net;
using System.IO;
using System.Json;
using System.Threading.Tasks;

Estas instrucciones importan la funcionalidad desde los espacios de nombres System , Android.App ,
Android.Content , etc.
Genéricos
Tanto Java como C# admiten genéricos, que son marcadores de posición que permiten conectar diferentes tipos en
tiempo de compilación. Sin embargo, los genéricos funcionan de forma algo diferente en C#. En Java, el borrado
de tipos habilita la información sobre tipos solo en tiempo de compilación, pero no en tiempo de ejecución. Por el
contrario, .NET Common Language Runtime (CLR ) proporciona compatibilidad explícita para los tipos genéricos,
lo que significa que C# tiene acceso a información sobre tipos en tiempo de ejecución. En el desarrollo diario de
Xamarin.Android, la importancia de esta distinción no suele ser evidente, pero si usa la reflexión, dependerá de
esta característica para acceder a la información sobre tipos en tiempo de ejecución.
En Xamarin.Android, verá con frecuencia el método genérico FindViewById utilizado para obtener una referencia a
un control de diseño. Este método acepta un parámetro de tipo genérico que especifica el tipo de control que se
buscará. Por ejemplo:

TextView label = FindViewById<TextView> (Resource.Id.Label);

En este ejemplo de código, FindViewById obtiene una referencia al control TextView que se define en el diseño
como etiqueta; a continuación, se devuelve como un tipo TextView .
Para obtener más información sobre los genéricos, vea el tema Genéricos. Tenga en cuenta que existen algunas
limitaciones en la compatibilidad de Xamarin.Android con las clases genéricas de C#; para más información, vea
Limitaciones.

Características de la programación orientada a objetos


Java y C# utilizan expresiones de programación orientada a objetos muy similares:
Todas las clases derivan en última instancia de un objeto de raíz única; todos los objetos de Java derivan de
java.lang.Object , mientras que los de C# derivan de System.Object .

Las instancias de clases son tipos de referencia.


Cuando acceda a las propiedades y los métodos de una instancia, use el operador " . ".
Todas las instancias de clases se crean en el montón mediante el operador new .
Debido a que ambos lenguajes utilizan la recolección de elementos no utilizados, no hay ningún método
para liberar de forma explícita los objetos no utilizados (es decir, que no hay ninguna palabra clave delete
como hay en C++).
Puede extender las clases mediante la herencia, y ambos lenguajes solo permiten una única clase base por
tipo.
Puede definir interfaces y una clase puede heredar de (es decir, implementar) varias definiciones de interfaz.
Sin embargo, también hay algunas diferencias importantes:
Java tiene dos características eficaces que C# no admite: las clases anónimas y las clases internas. (Sin
embargo, C# permite el anidamiento de las definiciones de clases; las clases anidadas de C# son similares a
las clases anidadas estáticas de Java).
C# admite tipos de estructuras del estilo de C ( struct ), pero Java no.
En C#, puede implementar una definición de clase en los archivos de código fuente independientes
mediante la palabra clave partial .
Las interfaces de C# no pueden declarar campos.
C# utiliza la sintaxis de destructores de estilo de C++ para expresar los finalizadores. La sintaxis es diferente
del método finalize de Java, pero la semántica es prácticamente la misma. (Tenga en cuenta que, en C#,
los destructores llaman automáticamente al destructor de clase base –, a diferencia de Java, donde se usa
una llamada explícita a super.finalize ).
Herencia de clases
Para extender una clase de Java, utilice la palabra clave extends . Para extender una clase de C#, utilice dos puntos
( : ) para indicar la derivación. Por ejemplo, en aplicaciones de Xamarin.Android, a menudo verá derivaciones de
clases que se parecen al fragmento de código siguiente:

public class MainActivity : Activity


{
...

En este ejemplo, MainActivity hereda de la clase Activity .


Para declarar la compatibilidad con una interfaz en Java, use la palabra clave implements . Sin embargo, en C#, solo
tiene que agregar nombres de interfaz a la lista de clases de la que se hereda, como se muestra en este fragmento
de código:

public class SensorsActivity : Activity, ISensorEventListener


{
...

En este ejemplo, SensorsActivity hereda de Activity e implementa la funcionalidad declarada en la interfaz


ISensorEventListener . Tenga en cuenta que la lista de interfaces debe aparecer después de la clase base o, de lo
contrario, se producirá un error en tiempo de compilación. Por convención, los nombres de interfaz de C# van
precedidos de una letra mayúscula "I"; esto permite determinar qué clases son interfaces sin requerir una palabra
clave implements .
Si desea impedir que una clase derive en subclases en C#, coloque sealed delante del nombre de clase; en Java,
coloque final delante del nombre de clase.
Para obtener más información sobre las definiciones de clases de C#, vea los temas Clases y Herencia.
Propiedades
En Java, los métodos mutadores (establecedores) y los métodos de inspector (captadores) a menudo se utilizan
para controlar cómo se realizan los cambios en los miembros de clase al ocultarlos y protegerlos del código
externo. Por ejemplo, la clase TextView de Android proporciona los métodos getText y setText . C# proporciona
un mecanismo similar pero más directo conocido como propiedades. Los usuarios de una clase de C# pueden
acceder a una propiedad de la misma manera en que accederían a un campo, pero cada acceso realmente produce
una llamada de método que es transparente para el autor de la llamada. Este método "pormenorizado" puede
implementar los efectos secundarios, como establecer otros valores, realizar conversiones o cambiar el estado del
objeto.
Las propiedades suelen utilizarse para acceder a los miembros de objetos de la interfaz de usuario y para
modificarlos. Por ejemplo:

int width = rulerView.MeasuredWidth;


int height = rulerView.MeasuredHeight;
...
rulerView.DrawingCacheEnabled = true;

En este ejemplo, se leen los valores de anchura y altura del objeto rulerView mediante el acceso a sus
propiedades MeasuredWidth y MeasuredHeight . Cuando se leen estas propiedades, los valores de sus valores de
campos asociados, pero ocultos, se capturan en segundo plano y se devuelven al autor de la llamada. El objeto
rulerView puede almacenar los valores de anchura y altura en una unidad de medida (es decir, píxeles) y
convertirlos sobre la marcha en una unidad de medida distinta (por ejemplo, milímetros) al acceder a las
propiedades MeasuredWidth y MeasuredHeight .
El objeto rulerView también tiene una propiedad denominada DrawingCacheEnabled ; el código de ejemplo
establece esta propiedad en true para habilitar la caché de dibujo en rulerView . En segundo plano, se actualiza
un campo oculto asociado con el nuevo valor y es posible que se modifiquen otros aspectos del estado rulerView .
Por ejemplo, cuando DrawingCacheEnabled está establecido en false , rulerView también puede borrar cualquier
información de la caché de dibujo ya acumulada en el objeto.
El acceso a las propiedades puede ser de lectura/escritura, solo lectura o solo escritura. Además, puede usar
distintos modificadores de acceso para leer y escribir. Por ejemplo, puede definir una propiedad que tenga acceso
de lectura público, pero acceso de escritura privado.
Para obtener más información sobre las propiedades de C#, vea el tema Propiedades.
Llamar a métodos de clase base
Para llamar a un constructor de clase base en C#, utilice dos puntos ( : ) seguidos de la palabra clave base y una
lista de inicializadores; esta llamada al constructor base se coloca inmediatamente después de la lista de
parámetros del constructor derivada. Se llama al constructor de clase base al introducir el constructor derivado; el
compilador inserta la llamada en el constructor base al inicio del cuerpo del método. El siguiente fragmento de
código muestra un constructor base llamado desde un constructor derivado en una aplicación de
Xamarin.Android:

public class PictureLayout : ViewGroup


{
...
public class PictureLayout (Context context)
: base (context)
{
...
}
...
}

En este ejemplo, la clase PictureLayout se deriva de la clase ViewGroup . El constructor PictureLayout que se
muestra en este ejemplo acepta un argumento context y lo pasa al constructor ViewGroup mediante la llamada
base(context) .

Para llamar a un método de clase base en C#, use la palabra clave base . Por ejemplo, las aplicaciones de
Xamarin.Android suelen realizar llamadas a los métodos base, como se muestra aquí:

public class MainActivity : Activity


{
...
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);

En este caso, el método OnCreate definido por la clase derivada ( MainActivity ) llama al método OnCreate de la
clase base ( Activity ).
Modificadores de acceso
Java y C# admiten los modificadores de acceso public , private y protected . Sin embargo, C# admite dos
modificadores de acceso adicionales:
internal – Al miembro de clase se puede acceder únicamente dentro del ensamblado actual.
protected internal – Al miembro de clase se puede acceder dentro del ensamblado de definición, de la
clase de definición y de las clases derivadas (tienen acceso las clases derivadas dentro y fuera del
ensamblado).
Para obtener más información sobre los modificadores de acceso de C#, vea el tema Modificadores de acceso.
Métodos virtuales y de invalidación
Java y C# admiten el polimorfismo, que es la capacidad de tratar objetos relacionados de la misma manera. En
ambos lenguajes, se puede usar una referencia de clase base para hacer referencia a un objeto de clases derivada,
y los métodos de una clase derivada pueden invalidar los métodos de sus clases base. Ambos lenguajes tienen el
concepto de un método virtual, que es un método de una clase base diseñado para sustituirse por un método de
una clase derivada. Al igual que Java, C# admite clases y métodos abstract .
Sin embargo, hay algunas diferencias entre Java y C# en cómo declarar métodos virtuales e invalidarlos:
En C#, los métodos son no virtuales de forma predeterminada. Las clases principales deben etiquetar de
forma explícita qué métodos deben invalidarse con el uso de la palabra clave virtual . Por el contrario,
todos los métodos de Java son virtuales de forma predeterminada.
Para evitar la invalidación de un método en C#, solo tiene que excluir la palabra clave virtual . Por el
contrario, Java usa la palabra clave final para marcar un método con "override is not allowed" (No se
permite la invalidación).
Las clases derivadas de C# deben usar la palabra clave override para indicar de forma explícita que se va a
anular un método de clase base virtual.
Para obtener más información sobre la compatibilidad de C# con el polimorfismo, vea el tema Polimorfismo.

Expresiones lambda
C# permite crear clausuras: métodos anónimos insertados que pueden acceder al estado del método en que están
incluidos. Con el uso de expresiones lambda, puede escribir menos líneas de código para implementar la misma
funcionalidad que hubiera implementado en Java con muchas más líneas de código.
Las expresiones lambda permiten omitir los pasos adicionales necesarios para crear una clase de un solo uso o
una clase anónima que debería aplicar en Java; en su lugar, solo puede escribir la lógica de negocios del código del
método insertado. Además, como las expresiones lambda tienen acceso a las variables del método adyacente, no
tiene que crear una lista larga de parámetros para pasar el estado al código del método.
En C#, las expresiones lambda se crean con el operador => , como se muestra a continuación:

(arg1, arg2, ...) => {


// implementation code
};

En Xamarin.Android, a menudo se usan expresiones lambda para definir controladores de eventos. Por ejemplo:

button.Click += (sender, args) => {


clickCount += 1; // access variable in surrounding code
button.Text = string.Format ("Clicked {0} times.", clickCount);
};

En este ejemplo, el código de la expresión lambda (el código encerrado entre llaves) incrementa un recuento de
clics y actualiza el texto button para mostrar el recuento de clics. Esta expresión lambda se registra con el objeto
button como un controlador de eventos de clics al que se llama cada vez que se pulsa un botón. ( Los
controladores de eventos se explican con más detalle a continuación). En este ejemplo, el código de la expresión
lambda no usa los parámetros sender y args , pero sí son necesarios en la expresión lambda para satisfacer los
requisitos de firma del método para el registro del evento. En segundo plano, el compilador de C# convierte la
expresión lambda en un método anónimo al que se llama cada vez que se hace clic en un botón.
Para obtener más información sobre C# y las expresiones lambda, vea el tema Expresiones lambda.

Control de eventos
Un eventos es la forma en que un objeto notifica a los suscriptores registrados cuándo sucede algo interesante a
dicho objeto. A diferencia de Java, donde un suscriptor que suele implementar una interfaz Listener que contiene
un método de devolución de llamada, C# ofrece compatibilidad a nivel de lenguaje para el control de eventos
mediante delegados. Un delegado es similar a un puntero de función con seguridad de tipos orientado a objetos;
encapsula una referencia de objeto y un token de método. Si un objeto de cliente desea suscribirse a un evento,
crea un delegado y pasa el delegado al objeto notificador. Cuando se produce el evento, el objeto notificador
invoca el método representado por el objeto delegado, para notificar al objeto de cliente de suscripción del evento.
En C#, los controladores de eventos básicamente no son más que métodos que se invocan mediante delegados.
Para obtener más información sobre los delegados, vea el tema Delegados.
En C#, los eventos son multidifusión; esto quiere decir que se puede notificar a más de un agente de escucha
cuando se produce un evento. Esta diferencia se observa al tener en cuenta las diferencias sintácticas entre el
registro de eventos de Java y C#. En Java, se llama a SetXXXListener para registrar notificaciones de eventos; en
C#, se usa el operador += para registrar notificaciones de eventos al "agregar" el delegado a la lista de agentes de
escucha de eventos. En Java, se llama a SetXXXListener para anular el registro, mientras que en C# se utiliza -=
para "restar" el delegado de la lista de agentes de escucha.
En Xamarin.Android, los eventos se usan con frecuencia para informar a los objetos cuando un usuario realiza una
acción en un control de interfaz de usuario. Normalmente, un control de interfaz de usuario tendrá miembros que
se definen con la palabra clave event ; asocie los delegados con estos miembros para suscribirse a eventos de ese
control de interfaz de usuario.
Para suscribirse a un evento:
1. Cree un objeto delegado que haga referencia al método que desea invocar cuando se produce el evento.
2. Use el operador += para asociar el delegado al evento al que se va a suscribir.

En el ejemplo siguiente se define un delegado (con el uso explícito de la palabra clave delegate ) para suscribirse a
los clics de botón. Este controlador de clics de botón inicia una nueva actividad:

startActivityButton.Click += delegate {
Intent intent = new Intent (this, typeof (MyActivity));
StartActivity (intent);
};

Sin embargo, también puede utilizar una expresión lambda para registrar eventos, omitiendo por completo la
palabra clave delegate . Por ejemplo:
startActivityButton.Click += (sender, e) => {
Intent intent = new Intent (this, typeof (MyActivity));
StartActivity (intent);
};

En este ejemplo, el objeto startActivityButton tiene un evento que espera un delegado con una firma de método
determinada: uno que acepta argumentos de remitente y evento y devuelve un valor nulo. No obstante, como no
queremos ocasionar la molestia de definir de forma explícita dicho delegado o su método, declaramos la firma del
método con (sender, e) y usamos una expresión lambda para implementar el cuerpo del controlador de eventos.
Tenga en cuenta que tenemos que declarar esta lista de parámetros aunque usemos los parámetros sender y e .
Es importante recordar que se puede anular la suscripción de un delegado (con el operador -= ), pero no se puede
anular la suscripción de una expresión lambda; tratar de hacerlo puede causar fugas de memoria. Use la forma de
expresión lambda del registro de eventos solo si no se anula la suscripción del controlador al evento.
Normalmente, las expresiones lambda se usan para declarar controladores de eventos en el código de
Xamarin.Android. Esta forma abreviada de declarar controladores de eventos puede parecer críptica al principio,
pero ahorra una gran cantidad de tiempo al leer y escribir código. Cuando se familiarice más, se habituará a
reconocer este patrón, que ocurre con frecuencia en el código de Xamarin.Android, y podrá dedicar más tiempo a
pensar en la lógica de negocios de su aplicación y menos tiempo a repasar la sobrecarga sintáctica.

Programación asincrónica
La programación asincrónica es una manera de mejorar la capacidad de respuesta general de la aplicación. Las
características de la programación asincrónica permiten que el resto del código de la aplicación continúe
ejecutándose mientras que una operación larga bloquea alguna parte de la aplicación. El acceso a la Web, el
procesamiento de imágenes y la lectura y escritura de archivos son ejemplos de operaciones que pueden causar
que una aplicación parezca inmovilizada si no se escribe de forma asincrónica.
C# incluye compatibilidad a nivel de lenguaje con la programación asincrónica mediante las palabras clave async
y await . Estas características del lenguaje facilitan bastante la escritura de código que realiza tareas de ejecución
prolongada sin bloquear el subproceso principal de la aplicación. En resumen, use la palabra clave async en un
método para indicar que el código del método debe ejecutarse de forma asincrónica y no bloquear el subproceso
del autor de la llamada. Use la palabra clave await para llamar a métodos marcados como async . El compilador
interpreta await como el punto al que se va a mover la ejecución del método a un subproceso en segundo plano
(se devuelve una tarea al autor de la llamada). Una vez completada esta tarea, la ejecución del código se reanuda
en el subproceso del autor de la llamada en el punto await del punto, devolviendo los resultados de la llamada
async . Por convención, los métodos que se ejecutan de forma asincrónica llevan el sufijo Async en sus nombres.

En las aplicaciones de Xamarin.Android, async y await suelen usarse para liberar el subproceso de la interfaz de
usuario, para que pueda responder a la entrada del usuario (como pulsar un botón Cancelar) mientras tiene lugar
una operación de ejecución prolongada en una tarea en segundo plano.
En el ejemplo siguiente, un controlador de eventos de clics de botón resulta en una operación asincrónica para
descargar una imagen de la Web:
downloadButton.Click += downloadAsync;
...
async void downloadAsync(object sender, System.EventArgs e)
{
webClient = new WebClient ();
var url = new Uri ("http://photojournal.jpl.nasa.gov/jpeg/PIA15416.jpg");
byte[] bytes = null;

bytes = await webClient.DownloadDataTaskAsync(url);

// display the downloaded image ...

En este ejemplo, cuando el usuario hace clic en el control downloadButton , el controlador de eventos
downloadAsync crea un objeto WebClient y un objeto Uri para capturar una imagen de la dirección URL
especificada. A continuación, llama al método DownloadDataTaskAsync del objeto WebClient con esta dirección URL
para recuperar la imagen.
Tenga en cuenta que la declaración del método downloadAsync va precedida de la palabra clave async para indicar
que se ejecutará de forma asincrónica y que devolverá una tarea. Tenga en cuenta también que la llamada a
DownloadDataTaskAsync va precedida de la palabra clave await . La aplicación mueve la ejecución del controlador
de eventos (a partir del punto en que await aparece) a un subproceso en segundo plano hasta que
DownloadDataTaskAsync se completa y realiza la devolución. Mientras tanto, el subproceso de la interfaz de usuario
de la aplicación puede responder aún a la entrada del usuario y activar los controladores de eventos para los otros
controles. Cuando DownloadDataTaskAsync se completa (que puede tardar varios segundos), la ejecución se reanuda
donde la variable bytes está establecida en el resultado de la llamada a DownloadDataTaskAsync , y el resto del
código del controlador de eventos muestra la imagen descargada en el subproceso del autor de la llamada
(interfaz de usuario).
Para obtener una introducción a async / await en C#, vea el tema Programación asincrónica con Async y Await.
Para más información sobre la compatibilidad de Xamarin con las características de la programación asincrónica,
vea Información general sobre la compatibilidad con Async.

Diferencias de palabras claves


Muchas de las palabras claves del lenguaje de Java también se usan en C#. También hay una serie de palabras
clave de Java que tienen un equivalente en C# pero con un nombre distinto, como se indica en esta tabla:

JAVA C# DESCRIPCIÓN

boolean bool Se utiliza para declarar los valores


booleanos true y false.

extends : Precede a la clase e interfaces de las que


se hereda.

implements : Precede a la clase e interfaces de las que


se hereda.

import using Importa tipos de un espacio de


nombres, que también se usa para crear
un alias de espacio de nombres.

final sealed Evita la derivación de clase; impide que


se invaliden los métodos y las
propiedades de la clase derivada.
JAVA C# DESCRIPCIÓN

instanceof is Evalúa si un objeto es compatible con


un tipo determinado.

native extern Declara un método que se implementa


externamente.

package namespace Declara un ámbito para un conjunto de


objetos relacionados.

T... params T Especifica un parámetro de método que


toma un número variable de
argumentos.

super base Se usa para acceder a los miembros de


la clase principal desde una clase
derivada.

synchronized lock Ajusta una sección crítica del código con


lanzamiento y adquisición de bloqueo.

Además, hay muchas palabras clave que son exclusivas de C# y que no tienen homólogo en Java. El código de
Xamarin.Android suele usar las siguientes palabras clave de C# (es útil hacer referencia a esta tabla al leer código
de ejemplo de Xamarin.Android):

C# DESCRIPCIÓN

as Realiza conversiones entre tipos de referencia compatibles o


tipos que aceptan valores NULL.

async Especifica que un método o una expresión lambda son


asincrónicos.

await Suspende la ejecución de un método hasta que se completa


una tarea.

byte Tipo entero de 8 bits sin signo.

delegate Se utiliza para encapsular un método o un método anónimo.

enum Declara una enumeración, un conjunto de constantes con


nombre.

event Declara un evento en una clase de publicador.

fixed Impide la reubicación de una variable.

get Define un método de descriptor de acceso que recupera el


valor de una propiedad.

in Permite que un parámetro acepte un tipo menos derivado en


una interfaz genérica.

object Un alias para el tipo Object en .NET Framework.


C# DESCRIPCIÓN

out Modificador de parámetros o declaración de parámetros de


tipo genérico.

override Amplía o modifica la implementación de un miembro


heredado.

partial Declara que una definición se va a dividir en varios archivos o


que se va a separar una definición de método de su
implementación.

readonly Declara que un miembro de clase puede asignarse solo en el


momento de la declaración o mediante el constructor de clase.

ref Hace que un argumento se pase por referencia en lugar de


por valor.

set Define un método de descriptor de acceso que establece el


valor de una propiedad.

string Alias para el tipo String en .NET Framework.

struct Un tipo de valor que encapsula un grupo de variables


relacionadas.

typeof Obtiene el tipo de un objeto.

var Declara una variable local con tipo implícito.

value Hace referencia al valor que el código de cliente desea asignar


a una propiedad.

virtual Permite la invalidación de un método en una clase derivada.

Interoperación con código de Java existente


Si dispone de una funcionalidad de Java existente que no desea convertir a C#, puede volver a usar las bibliotecas
de Java existentes en las aplicaciones de Xamarin.Android con estas dos técnicas:
Crear una biblioteca de enlaces de Java: con este enfoque, se utilizan las herramientas de Xamarin para
generar contenedores de C# que incluyen tipos de Java. Estos contenedores se denominan enlaces. Como
resultado, la aplicación de Xamarin.Android puede usar el archivo .jar con una llamada a estos
contenedores.
Java Native Interface: Java Native Interface (JNI) es un marco de trabajo que permite a las aplicaciones
de C# llamar al código de Java o recibir llamadas de este código.
Para obtener más información sobre estas técnicas, vea Java Integration Overview (Información general sobre la
integración de Java).

Más información
La guía de programación de C# es un recurso muy útil para iniciarse en el aprendizaje del lenguaje de
programación C#, y puede usar la referencia de C# para buscar características particulares del lenguaje C#.
De la misma forma que el conocimiento de Java tiene al menos tanto que ver con la familiaridad con las
bibliotecas de clases de Java como con el conocimiento del lenguaje Java, el conocimiento práctico de C# requiere
alguna familiaridad con .NET Framework. El paquete de aprendizaje Pasar a C# y .NET Framework, para
desarrolladores de Java de Microsoft es un buen recurso para aprender más sobre .NET Framework desde la
perspectiva de Java (al mismo tiempo que se adquiere un conocimiento más profundo de C#).
Cuando esté listo para abordar el primer proyecto de Xamarin.Android en C#, nuestra serie Hello, Android puede
facilitar la compilación de la primera aplicación de Xamarin.Android y ayudar a profundizar los conocimientos de
los aspectos fundamentales del desarrollo de aplicaciones de Android con Xamarin.

Resumen
Este artículo ofrece una introducción al entorno de programación de C# en Xamarin.Android desde la perspectiva
de los desarrolladores de Java. Se indican las similitudes entre C# y Java, además de explicar sus diferencias
prácticas. Aborda los ensamblados y los espacios de nombres, se explica cómo importar tipos externos y se ofrece
información general sobre las diferencias de los modificadores de acceso, los genéricos, la derivación de clases, la
llamada a métodos de clases base, la invalidación de métodos y el control de eventos. Se presentan características
de C# que no están disponibles en Java, como las propiedades, la programación asincrónica de async / await , las
expresiones lambda, los delegados de C# y el sistema de control de eventos de C#. Incluye tablas de palabras
claves importantes de C#, se explica cómo interoperar con bibliotecas de Java existentes y se ofrecen vínculos a
documentación relacionada realizar un estudio adicional.

Vínculos relacionados
Información general sobre la integración de Java
Guía de programación de C#
Referencia de C#
Pasar a C# y .NET Framework, para desarrolladores de Java
Principios de la aplicación de Xamarin.Android
13/07/2019 • 7 minutes to read • Edit Online

En esta sección se proporciona a una guía sobre algunas de las tareas de las cosas o conceptos que los
desarrolladores deben tener en cuenta al desarrollar aplicaciones de Android más comunes.

Accesibilidad
Esta página describe cómo usar las API de accesibilidad de Android para compilar aplicaciones de acuerdo con la
lista de comprobación de accesibilidad.

Descripción de los niveles de API de Android


Esta guía describe cómo Android usa los niveles de API para administrar la compatibilidad de aplicaciones en las
distintas versiones de Android, y se explica cómo configurar los valores de proyecto de Xamarin.Android para
implementar estos niveles de API en su aplicación. Además, esta guía explica cómo escribir código en tiempo de
ejecución que se ocupa de diferentes niveles de API y proporciona una lista de referencia de todos los niveles de
API de Android, números de versión (por ejemplo, Android 8.0), los nombres de código Android (por ejemplo,
Oreo) y códigos de versión de compilación.

Recursos de Android
Este artículo presenta el concepto de recursos de Android en documentos y Xamarin.Android cómo usarlas. Se
describe cómo usar los recursos en la aplicación Android para admitir la localización de aplicaciones y varios
dispositivos, incluidas las densidades y diferentes tamaños de pantalla.

Ciclo de vida de la actividad


Las actividades son un pilar fundamental de las aplicaciones de Android y pueden existir en un número de estados
diferentes. El ciclo de vida de la actividad comienza con la creación de instancias y termina con la destrucción e
incluye muchos Estados entre ellos. Cuando una actividad cambia de estado, se llama al método de evento
adecuado del ciclo de vida, notificar a la actividad de la inminente cambio de estado y lo que le permite ejecutar el
código para adaptarse a ese cambio. En este artículo examina el ciclo de vida de las actividades y se explica la
responsabilidad que tiene una actividad durante cada uno de estos cambios de estado para formar parte de una
aplicación confiable y se comporten correctamente.

Localización
En este artículo se explica cómo localizar Xamarin.Android a otros idiomas mediante la traducción de cadenas y
proporcionar imágenes alternativas.

Servicios
Este artículo tratan los servicios de Android, que son componentes de Android que permiten que el trabajo se
realiza en segundo plano. Explica los diferentes escenarios más adecuados para servicios y muestra cómo se
implementan ambas para llevar a cabo las tareas de larga ejecución en segundo plano, así como para proporcionar
una interfaz para las llamadas a procedimiento remoto.

Receptores de difusión
Esta guía explica cómo crear y usar receptores de difusión, un componente de Android que responde a las
difusiones de todo el sistema, en Xamarin.Android.

Permisos
Puede usar la compatibilidad con las herramientas integrada en Visual Studio para Mac o Visual Studio para crear
y agregar permisos para el manifiesto de Android. Este documento describe cómo agregar permisos de Visual
Studio y Xamarin Studio.

Gráficos y animación
Android proporciona un marco de trabajo muy amplio y diverso para admitir las animaciones y gráficos 2D. Este
documento presenta estos marcos de trabajo y explica cómo crear animaciones y gráficos personalizados y usarlos
en una aplicación de Xamarin.Android.

Arquitecturas de CPU
Xamarin.Android admite varias arquitecturas de CPU, incluidos los dispositivos de 32 bits y 64 bits. En este artículo
se explica cómo elegir como destino una aplicación a una o varias arquitecturas de CPU compatible con Android.

Control de giro
En este artículo se describe cómo controlar los cambios de orientación del dispositivo en Xamarin.Android. Se
describe cómo trabajar con el sistema de recursos de Android para cargar automáticamente los recursos para una
orientación de dispositivo determinado, así cómo controlar mediante programación la orientación cambia. A
continuación, se describen técnicas para mantener el estado cuando se gira un dispositivo.

Audio de Android
El sistema operativo Android proporciona amplia compatibilidad para multimedia, que abarca de audio y vídeo.
Esta guía se centra en audio en Android y reproducir y grabar audio mediante las clases de la grabadora y el
Reproductor de audio integrado, así como la API de audio de bajo nivel. También explica cómo trabajar con
eventos de Audio de difusión por otras aplicaciones, para que los desarrolladores pueden crear aplicaciones y se
comporten correctamente.

Notificaciones
Esta sección explica cómo implementar las notificaciones locales y remotas en Xamarin.Android. Describe los
distintos elementos de interfaz de usuario de una notificación de Android y habla de la API del implicada en crear y
mostrar una notificación. Las notificaciones remotas, se explican tanto Google Cloud Messaging y Firebase Cloud
Messaging. Se incluyen ejemplos de código y tutoriales paso a paso.

Entrada táctil
En esta sección se explica que los conceptos y detalles de implementación de gestos de toque en Android. Las API
de toque se introdujo y explican seguidas de una exploración de los reconocedores de gestos.

Pila HttpClient y SSL/TLS


En esta sección se explica los selectores de pila HttpClient e implementación de SSL/TLS para Android. Esta
configuración determina la implementación de HttpClient y SSL/TLS que se usará en las aplicaciones de
Xamarin.Android.
Escribir aplicaciones con capacidad de respuesta
En este artículo se describe cómo usar el subprocesamiento para que una aplicación de Xamarin.Android siga
respondiendo moviendo las tareas de larga ejecución en un subproceso en segundo plano.
Accesibilidad en Android
11/07/2019 • 6 minutes to read • Edit Online

Esta página describe cómo usar las API de accesibilidad de Android para compilar aplicaciones de acuerdo con la
lista de comprobación de accesibilidad. Hacer referencia a la iOS accesibilidad y accesibilidad OS X páginas para
otra API de plataforma.

Que describe los elementos de interfaz de usuario


Android proporciona un ContentDescription propiedad que se utiliza por las API de lectura de pantalla para
proporcionar una descripción accesible del propósito del control.
La descripción del contenido puede establecerse en C# o en el archivo de diseño AXML.
C#
La descripción se puede establecer en el código para cualquier cadena (o un recurso de cadena):

saveButton.ContentDescription = "Save data";

Diseño AXML
En XML usan diseños el android:contentDescription atributo:

<ImageButton
android:id=@+id/saveButton"
android:src="@drawable/save_image"
android:contentDescription="Save data" />

Use la sugerencia de vista de texto


Para EditText y TextView controles para entrada de datos, utilice el Hint propiedad para proporcionar una
descripción de qué entrada se espera (en lugar de ContentDescription ). Cuando se ha especificado algún texto, el
texto en sí será "de lectura" en lugar de la sugerencia.
C#
Establecer el Hint propiedad en el código:

someText.Hint = "Enter some text"; // displays (and is "read") when control is empty

Diseño AXML
En XML se usan archivos de diseño la android:hint atributo:

<EditText
android:id="@+id/someText"
android:hint="Enter some text" />

Los campos con etiquetas de entrada de LabelFor vínculos


Para asociar una etiqueta con un control de entrada de datos, use el LabelFor propiedad
C#
En C#, establezca el LabelFor propiedad para el identificador de recurso del control que describe este contenido
(normalmente, esta propiedad se establece en una etiqueta y hace referencia a algún otro control de entrada):

EditText edit = FindViewById<EditText> (Resource.Id.editFirstName);


TextView tv = FindViewById<TextView> (Resource.Id.labelFirstName);
tv.LabelFor = Resource.Id.editFirstName;

Diseño AXML
En el diseño del uso de XML en el android:labelFor propiedad para hacer referencia al identificador de otro
control:

<TextView
android:id="@+id/labelFirstName"
android:hint="Enter some text"
android:labelFor="@+id/editFirstName" />
<EditText
android:id="@+id/editFirstName"
android:hint="Enter some text" />

Anunciar para mejorar la accesibilidad


Use el AnnounceForAccessibility método en cualquier control para comunicar un cambio de estado o de eventos a
los usuarios cuando se habilita la accesibilidad de vista. Este método no es necesario para la mayoría de las
operaciones donde la narración integrada proporciona información suficiente, pero se debe usar información
adicional que sería útil para el usuario.
El código siguiente muestra una llamada de ejemplo sencillo AnnounceForAccessibility :

button.Click += delegate {
button.Text = string.Format ("{0} clicks!", count++);
button.AnnounceForAccessibility (button.Text);
};

Cambie la configuración de foco


Navegación accesible se basa en los controles que tienen el foco para ayudar al usuario a comprender qué
operaciones están disponibles. Android proporciona un Focusable propiedad que se puede etiquetar controles
como específicamente capaz de recibir el foco durante la navegación.
C#
Para impedir que un control obtengan el foco con C#, establezca el Focusable propiedad false :

label.Focusable = false;

Diseño AXML
En diseño de conjunto de archivos de XML de la android:focusable atributo:

<android:focusable="false" />

También puede controlar el orden de foco con el nextFocusDown , nextFocusLeft , nextFocusRight , nextFocusUp
atributos, normalmente se establece en el diseño AXML. Use estos atributos para asegurarse de que el usuario
puede navegar fácilmente por los controles de la pantalla.

Localización y accesibilidad
En los ejemplos anteriores está la descripción de la sugerencia y contenido establece directamente en el valor de
presentación. Es preferible utilizar los valores de un Strings.xml archivo, como esto:

<?xml version="1.0" encoding="utf-8"?>


<resources>
<string name="enter_info">Enter some text</string>
<string name="save_info">Save data</string>
</resources>

Mediante el texto de un archivo de cadenas se muestra a continuación en C# y archivos de diseño AXML:


C#
En lugar de literales de cadena en el código, buscar valores traducidos de los archivos de las cadenas con
Resources.GetText :

someText.Hint = Resources.GetText (Resource.String.enter_info);


saveButton.ContentDescription = Resources.GetText (Resource.String.save_info);

AXML
En el diseño XML como atributos de accesibilidad hint y contentDescription se puede establecer en un
identificador de cadena:

<TextView
android:id="@+id/someText"
android:hint="@string/enter_info" />
<ImageButton
android:id=@+id/saveButton"
android:src="@drawable/save_image"
android:contentDescription="@string/save_info" />

La ventaja de almacenar texto en un archivo independiente es que se pueden proporcionar varias traducciones de
lenguaje del archivo en la aplicación. Consulte la guía localización Android para obtener información sobre cómo
agregar archivos de cadena localizada a un proyecto de aplicación.

Probar la accesibilidad
Siga estos pasos para habilitar TalkBack y explorar con el tacto probar la accesibilidad en los dispositivos Android.
Es posible que deba instalar TalkBack desde Google Play si no aparece en configuración > accesibilidad.

Vínculos relacionados
Accesibilidad multiplataforma
API de accesibilidad de Android
Descripción de los niveles de API de Android
16/08/2019 • 39 minutes to read • Edit Online

Xamarin. Android tiene varias configuraciones de nivel de API de Android que determinan la compatibilidad de la
aplicación con varias versiones de Android. En esta guía se explica lo que significan estas opciones de configuración,
cómo configurarlas y el efecto que tienen en la aplicación en tiempo de ejecución.

Inicio rápido
Xamarin. Android expone tres configuraciones de proyecto de nivel de API de Android:
Plataforma de destino – Especifica el marco que se va a usar para compilar la aplicación. Xamarin. Android usa este
nivel de API en tiempo de compilación .
Versión mínima de Android – Especifica la versión de Android más antigua que quiere que admita su aplicación.
Android usa este nivel de API en tiempo de ejecución .
Versión de Android de destino – Especifica la versión de Android en la que se va a ejecutar la aplicación. Android
usa este nivel de API en tiempo de ejecución .
Para poder configurar un nivel de API para el proyecto, debe instalar los componentes de la plataforma SDK para ese
nivel de API. Para obtener más información acerca de cómo descargar e instalar los componentes de Android SDK,
consulte Android SDK Setup.

NOTE
A partir de agosto de 2018, la consola de Google Play requerirá que las nuevas aplicaciones tengan como destino el nivel de API 26
(Android 8,0) o posterior. Las aplicaciones existentes deberán tener como destino el nivel de API 26 o superior a partir de noviembre
de 2018. Para obtener más información, consulte mejorar la seguridad y el rendimiento de las aplicaciones en Google Play durante
años.

Visual Studio
Visual Studio para Mac
Normalmente, los tres niveles de la API de Xamarin. Android se establecen en el mismo valor. En la página de la
aplicación , establezca compilar con la versión de Android (plataforma de destino) en la versión de API estable más
reciente (o, como mínimo, en la versión de Android que tenga todas las características que necesita). En la siguiente
captura de pantalla, la versión de .NET Framework de destino está establecida en Android 7,1 (nivel de API 25-
nougat) :

En la página manifiesto de Android , establezca la versión mínima de Android para usar compilar con la versión del
SDK y establezca la versión de Android de destino en el mismo valor que la versión de .NET Framework de destino (en la
siguiente captura de pantalla, el marco de trabajo de Android de destino se establece en Android 7,1 (nougat) ):

Si quiere mantener la compatibilidad con versiones anteriores de Android, establezca la versión mínima de Android en
destino a la versión más antigua de Android que quiera que admita la aplicación. (Tenga en cuenta que el nivel de API 14
es el nivel de API mínimo necesario para los servicios de Google Play y la compatibilidad con Firebase ). La configuración
de ejemplo siguiente admite versiones de Android desde el nivel de API 14 a través del nivel de API 25:

Si la aplicación admite varias versiones de Android, el código debe incluir comprobaciones en tiempo de ejecución para
asegurarse de que la aplicación funciona con la configuración de versión mínima de Android (consulte comprobaciones
en tiempo de ejecución para las versiones de Android a continuación para más información). Si está consumiendo o
creando una biblioteca, consulte niveles de API y bibliotecas a continuación para conocer los procedimientos
recomendados para configurar las opciones de nivel de API de las bibliotecas.

Versiones de Android y niveles de API


A medida que la plataforma Android evoluciona y se publican nuevas versiones de Android, a cada versión de Android se
le asigna un identificador entero único, denominado nivel de API. Por lo tanto, cada versión de Android corresponde a un
solo nivel de API de Android. Dado que los usuarios instalan aplicaciones en versiones anteriores, así como en las
versiones más recientes de Android, las aplicaciones Android del mundo real deben estar diseñadas para funcionar con
varios niveles de API de Android.
Versiones de Android
Cada versión de Android va acompañada de varios nombres:
La versión de Android, como android 9,0
Un nombre de código (o postre), como un círculo
Un nivel de API correspondiente, como el nivel de API 28
Un nombre de código de Android puede corresponder a varias versiones y niveles de API (como se muestra en la tabla
siguiente), pero cada versión de Android corresponde a un nivel de API exactamente.
Además, Xamarin. Android define códigos de versión de compilación que se asignan a los niveles de API de Android
conocidos actualmente. La tabla siguiente puede ayudarle a traducir entre el nivel de API, la versión de Android, el
nombre de código y el código de la versión de compilación de Android.OS Xamarin. Android (los códigos de versión de
compilación se definen en el espacio de nombres):

GENERAR CÓDIGO DE
NAME VERSIÓN NIVEL DE API LANZAMIENTO VERSIÓN

Gráficos circulares 9.0 28 Agosto de 2018 BuildVersionCodes.P

Oreo 8.1 27 Diciembre de 2017 BuildVersionCodes.OMr1

Oreo 8.0 26 Agosto de 2017 BuildVersionCodes.O

Nougat 7.1 25 Diciembre de 2016 BuildVersionCodes.NMr1

Nougat 7.0 24 Agosto de 2016 BuildVersionCodes.N

Mallorca 6.0 23 Agosto de 2015 BuildVersionCodes.M

Círculo 5.1 22 Marzo de 2015 BuildVersionCodes.LollipopMr1

Círculo 5.0 21 Noviembre de 2014 BuildVersionCodes.Lollipop

Kitkat Watch 4.4W 20 Junio de 2014 BuildVersionCodes.KitKatWatch

Kitkat 4.4 19 Octubre de 2013 BuildVersionCodes.KitKat

Jelly Bean 4.3 18 Julio de 2013 BuildVersionCodes.JellyBeanMr2

Jelly Bean 4.2-4.2.2 17 Noviembre de 2012 BuildVersionCodes.JellyBeanMr1

Jelly Bean 4.1-4.1.1 16 Junio de 2012 BuildVersionCodes.JellyBean

ICE Cream Sandwich 4.0.3-4.0.4 15 Diciembre de 2011 BuildVersionCodes.IceCreamSandwichMr

ICE Cream Sandwich 4.0-4.0.2 14 Octubre de 2011 BuildVersionCodes.IceCreamSandwich

Honeycomb 3.2 13 Junio de 2011 BuildVersionCodes.HoneyCombMr2

Honeycomb 3.1.x 12 Mayo de 2011 BuildVersionCodes.HoneyCombMr1

Honeycomb 3.0.x 11 Febrero de 2011 BuildVersionCodes.HoneyComb

Monigote 2.3.3-2.3.4 10 Febrero de 2011 BuildVersionCodes.GingerBreadMr1

Monigote 2.3-2.3.2 9 Noviembre de 2010 BuildVersionCodes.GingerBread

Froyo 2.2.x 8 Jun de 2010 BuildVersionCodes.Froyo

Eclair 2.1.x 7 Ene 2010 BuildVersionCodes.EclairMr1


GENERAR CÓDIGO DE
NAME VERSIÓN NIVEL DE API LANZAMIENTO VERSIÓN

Eclair 2.0.1 6 Diciembre de 2009 BuildVersionCodes.Eclair01

Eclair 2.0 5 Noviembre de 2009 BuildVersionCodes.Eclair

Anillo 1.6 4 Septiembre de 2009 BuildVersionCodes.Donut

Para magdalenas 1.5 3 Mayo de 2009 BuildVersionCodes.Cupcake


glaseadas

Base 1.1 2 Feb 2009 BuildVersionCodes.Base11

Base 1.0 1 Octubre de 2008 BuildVersionCodes.Base

Como se indica en esta tabla, las nuevas versiones de – Android se publican frecuentemente a veces en más de una
versión al año. Como resultado, el universo de dispositivos Android que pueden ejecutar la aplicación incluye una amplia
variedad de versiones de Android antiguas y más recientes. ¿Cómo se puede garantizar que la aplicación se ejecute de
forma coherente y confiable en tantas versiones diferentes de Android? Los niveles de API de Android pueden ayudarle a
administrar este problema.
Niveles de API de Android
Cada dispositivo Android se ejecuta en un nivel – de API exactamente. se garantiza que este nivel de API es único por
cada versión de la plataforma Android. El nivel de API identifica con precisión la versión del conjunto de API al que puede
llamar la aplicación; identifica la combinación de elementos de manifiesto, permisos, etc., que se codifican como
desarrollador. El sistema de Android de niveles de API ayuda a Android a determinar si una aplicación es compatible con
una imagen de sistema Android antes de instalar la aplicación en un dispositivo.
Cuando se compila una aplicación, contiene la siguiente información de nivel de API:
El nivel de API de destino de Android en el que se crea la aplicación.
El nivel mínimo de API de Android que debe tener un dispositivo Android para ejecutar la aplicación.
Esta configuración se usa para garantizar que la funcionalidad necesaria para ejecutar la aplicación correctamente esté
disponible en el dispositivo Android en el momento de la instalación. Si no es así, se bloquea la ejecución de la aplicación
en ese dispositivo. Por ejemplo, si el nivel de API de un dispositivo Android es inferior al nivel de API mínimo que se
especifica para la aplicación, el dispositivo Android impedirá que el usuario instale la aplicación.

Configuración de nivel de API del proyecto


En las secciones siguientes se explica cómo usar SDK Manager para preparar el entorno de desarrollo para los niveles de
API a los que desea dirigirse, seguido de una explicación detallada de cómo configurar el marco de trabajo de destino, la
versión mínima de AndroidyConfiguración de versión de Android de destino en Xamarin. Android.
Plataformas Android SDK
Antes de poder seleccionar un nivel de API de destino o mínimo en Xamarin. Android, debe instalar la versión de la
plataforma Android SDK que se corresponda con ese nivel de API. El intervalo de opciones disponibles para el marco de
trabajo de destino, la versión mínima de Android y la versión de Android de destino se limita al intervalo de versiones
Android SDK que ha instalado. Puede usar el administrador de SDK para comprobar que están instaladas las versiones
de Android SDK necesarias y puede usarla para agregar los nuevos niveles de API que necesite para la aplicación. Si no
está familiarizado con la instalación de los niveles de API, consulte Android SDK Setup.
Versión de .NET Framework de destino
La plataforma de destino (también conocida compileSdkVersion como) es la versión específica de Android Framework
(nivel de API) para la que se compila la aplicación en tiempo de compilación. Esta configuración especifica qué API espera
usar la aplicación cuando se ejecuta, pero no tiene ningún efecto en qué API están realmente disponibles para la
aplicación cuando se instala. Como resultado, el cambio de la configuración de la plataforma de destino no cambia el
comportamiento en tiempo de ejecución.
La versión de .NET Framework de destino identifica las versiones de la – biblioteca a las que está vinculada la aplicación
en esta configuración y determina qué API se pueden usar en la aplicación. Por ejemplo, si quiere usar el método
NotificationBuilder. SetCategory que se presentó en Android 5,0 Lollipop, debe establecer la versión de .NET Framework
de destino en el nivel de API 21 (Lollipop) o posterior. Si establece la plataforma de destino del proyecto en un nivel de
API como el nivel de API 19 (KitKat) e intenta llamar SetCategory al método en el código, obtendrá un error de
compilación.
Se recomienda compilar siempre con la última versión de .NET Framework de destino disponible. Al hacerlo, se
proporcionan mensajes de advertencia útiles para las API en desuso a las que puede llamar el código. El uso de la versión
más reciente de la plataforma de destino es especialmente importante cuando se – usa la versión más reciente de la
biblioteca de soporte técnico cada biblioteca espera que la aplicación se compile en el nivel mínimo de API de la
biblioteca de compatibilidad o superior.
Visual Studio
Visual Studio para Mac
Para acceder a la configuración de la plataforma de destino en Visual Studio, abra las propiedades del proyecto en
Explorador de soluciones y seleccione la página de la aplicación :

Establezca la versión de .NET Framework de destino seleccionando un nivel de API en el menú desplegable de compilar
con la versión de Android como se mostró anteriormente.
Versión mínima de Android
La versión mínima de Android (también conocida minSdkVersion como) es la versión más antigua del sistema operativo
Android (es decir, el nivel de API más bajo) que puede instalar y ejecutar la aplicación. De forma predeterminada, una
aplicación solo se puede instalar en dispositivos que coincidan con la configuración de la plataforma de destino o
superior; Si la configuración de versión mínima de Android es anterior a la configuración de la plataforma de destino, la
aplicación también puede ejecutarse en versiones anteriores de Android. Por ejemplo, si establece la plataforma de
destino en android 7,1 (nougat) y establece la versión mínima de Android en Android 4.0.3 (sandwichde helado), la
aplicación se puede instalar en cualquier plataforma desde el nivel de API 15 hasta el nivel de API 25, ambos inclusive.
Aunque la aplicación puede compilarse e instalarse correctamente en este intervalo de plataformas, esto no garantiza que
se ejecute correctamente en todas estas plataformas. Por ejemplo, si la aplicación se instala en android 5,0 (Lollipop) y
el código llama a una API que solo está disponible en Android 7,1 (nougat) y versiones más recientes, la aplicación
obtendrá un error en tiempo de ejecución y, posiblemente, se bloqueará. Por lo tanto, el código – debe asegurarse – en
tiempo de ejecución de que solo llama a las API admitidas por el dispositivo Android en el que se está ejecutando. En
otras palabras, el código debe incluir comprobaciones explícitas en tiempo de ejecución para asegurarse de que la
aplicación usa las API más recientes solo en los dispositivos que son lo suficientemente recientes como para admitirlos.
Las comprobaciones en tiempo de ejecución de las versiones de Android, más adelante en esta guía, explica cómo
agregar estas comprobaciones en tiempo de ejecución al código.
Visual Studio
Visual Studio para Mac
Para acceder a la configuración de versión mínima de Android en Visual Studio, abra las propiedades del proyecto en
Explorador de soluciones y seleccione la página manifiesto de Android . En el menú desplegable de la versión
mínima de Android , puede seleccionar la versión mínima de Android para la aplicación:
Si selecciona usar compilar con la versión del SDK, la versión mínima de Android será la misma que la configuración
de la plataforma de destino.
Versión de Android de destino
La versión de Android de destino (también targetSdkVersion conocida como) es el nivel de API del dispositivo Android en
el que la aplicación espera ejecutarse. Android usa esta opción para determinar si se debe habilitar cualquier
comportamiento – de compatibilidad. Esto garantiza que la aplicación siga funcionando de la manera esperada. Android
usa la configuración de versión de Android de destino de la aplicación para averiguar qué cambios de comportamiento se
pueden aplicar a la aplicación sin interrumpirla (este es el modo en que Android proporciona compatibilidad con
versiones posteriores).
La plataforma de destino y la versión de Android de destino, aunque tienen nombres muy similares, no son lo mismo. La
configuración de plataforma de destino comunica información de nivel de API de destino a Xamarin. Android para su uso
en tiempo de compilación, mientras que la versión de Android de destino comunica información de nivel de API de
destino a Android para su uso en tiempo de ejecución (cuando la aplicación está instalado y en ejecución en un
dispositivo).
Visual Studio
Visual Studio para Mac
Para acceder a esta configuración en Visual Studio, abra las propiedades del proyecto en Explorador de soluciones y
seleccione la página manifiesto de Android . En el menú desplegable de versión de Android de destino puede
seleccionar la versión de Android de destino de la aplicación:

Se recomienda establecer explícitamente la versión de Android de destino en la versión más reciente de Android que se
usa para probar la aplicación. Idealmente, debe establecerse en la versión – de Android SDK más reciente, lo que le
permite usar nuevas API antes de trabajar con los cambios de comportamiento. Para la mayoría de los desarrolladores,
no se recomienda establecer la versión de Android de destino para usar compilar con la versión del SDK.
En general, la versión de Android de destino debe estar limitada por la versión mínima de Android y la plataforma de
destino. Es decir:
Versión mínima de Android < = versión de Android de destino < = plataforma de destino
Para obtener más información sobre los niveles de SDK, consulte la documentación sobre el SDK para desarrolladores de
Android.

Comprobaciones en tiempo de ejecución para las versiones de Android


A medida que se publica cada nueva versión de Android, la API de Framework se actualiza para proporcionar una
funcionalidad nueva o de reemplazo. Con pocas excepciones, la funcionalidad de API de versiones anteriores de Android
se lleva a cabo en nuevas versiones de Android sin modificaciones. Como resultado, si la aplicación se ejecuta en un nivel
de API de Android determinado, normalmente podrá ejecutarse en un nivel de API de Android posterior sin
modificaciones. Pero ¿qué ocurre si también quiere ejecutar la aplicación en versiones anteriores de Android?
Si selecciona una versión mínima de Android que sea anterior a la configuración de la plataforma de destino, es posible
que algunas API no estén disponibles para la aplicación en tiempo de ejecución. Sin embargo, la aplicación todavía puede
ejecutarse en un dispositivo anterior, pero con funcionalidad reducida. Para cada API que no esté disponible en
plataformas Android correspondientes a la configuración de versión mínima de Android, el código debe comprobar
explícitamente el Android.OS.Build.VERSION.SdkInt valor de la propiedad para determinar el nivel de API de la plataforma
en la que se ejecuta la aplicación. Si el nivel de API es inferior a la versión mínima de Android que admite la API a la que
desea llamar, el código tiene que encontrar una manera de funcionar correctamente sin hacer esta llamada API.
Por ejemplo, supongamos que deseamos usar el método NotificationBuilder. SetCategory para clasificar una notificación
cuando se ejecuta en Android 5,0 Lollipop (y versiones posteriores), pero todavía queremos que nuestra aplicación se
ejecute en versiones anteriores de Android, como Java de jalea Android 4,1 (donde SetCategory no está disponible). Al
hacer referencia a la tabla de versiones de Android al principio de esta guía, vemos que el código de versión de
compilación para Android.OS.BuildVersionCodes.Lollipop el círculo de Android 5,0 es. Para admitir versiones anteriores
de Android en SetCategory las que no está disponible, nuestro código puede detectar el nivel de API en tiempo de
SetCategory ejecución y llamar condicionalmente solo cuando el nivel de API sea mayor o igual que el código de la
versión de compilación Lollipop:

if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.Lollipop)


{
builder.SetCategory(Notification.CategoryEmail);
}

En este ejemplo, el marco de trabajo de destino de la aplicación está establecido en android 5,0 (nivel de API 21) y su
versión mínima de Android está establecida en Android 4,1 (nivel de API 16) . Dado SetCategory que está disponible
en el Android.OS.BuildVersionCodes.Lollipop nivel de API y versiones posteriores, este SetCategory código de ejemplo
solo llamará – cuando esté realmente disponible, no SetCategory intentará llamar a cuando el nivel de API sea 16, 17, 18,
19 o 20. La funcionalidad se reduce en estas versiones anteriores de Android solo en la medida en que las notificaciones
no están ordenadas correctamente (porque no se clasifican por tipo), pero las notificaciones siguen publicadas para
alertar al usuario. Nuestra aplicación sigue funcionando, pero su funcionalidad se reduce ligeramente.
En general, la comprobación de la versión de compilación ayuda a su código a decidir en tiempo de ejecución entre hacer
algo de la forma nueva en lugar de la antigua. Por ejemplo:

if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.Lollipop)


{
// Do things the Lollipop way
}
else
{
// Do things the pre-Lollipop way
}

No hay ninguna regla rápida y sencilla que explique cómo reducir o modificar la funcionalidad de la aplicación cuando se
ejecuta en versiones de Android anteriores que carecen de una o más API. En algunos casos (como en el SetCategory
ejemplo anterior), es suficiente para omitir la llamada API cuando no está disponible. Sin embargo, en otros casos, puede
que necesite implementar una funcionalidad alternativa para Android.OS.Build.VERSION.SdkInt cuando se detecte que es
menor que el nivel de API que la aplicación necesita para presentar su experiencia óptima.

Niveles y bibliotecas de API


Visual Studio
Visual Studio para Mac
Al crear un proyecto de biblioteca Xamarin. Android (como una biblioteca de clases o una biblioteca de enlaces), solo
puede configurar la plataforma de destino estableciendo – la versión mínima de Android y la configuración de versión de
Android de destino no está disponible. Esto se debe a que no hay ninguna página de manifiesto de Android :

La versión mínima de Android y la configuración de versión de Android de destino no están disponibles porque la
biblioteca resultante no es – una aplicación independiente. la biblioteca puede ejecutarse en cualquier versión de Android,
en función de la aplicación con la que está empaquetada. Puede especificar cómo se va a compilarla biblioteca, pero no
puede predecir en qué nivel de API de plataforma se ejecutará la biblioteca. Teniendo esto en cuenta, deben tenerse en
cuenta los siguientes procedimientos recomendados al consumir o crear bibliotecas:
Al utilizar una biblioteca de Android Si está consumiendo una biblioteca de Android en la aplicación,
asegúrese de establecer la configuración de la plataforma de destino de la aplicación en un nivel de API que sea al
menos tan alto como el de la versión de .NET Framework de destino de la biblioteca. –
Al crear una biblioteca de Android – Si va a crear una biblioteca de Android para su uso por parte de otras
aplicaciones, asegúrese de establecer la configuración de la plataforma de destino en el nivel de API mínimo que
necesita para compilar.
Se recomiendan estas prácticas recomendadas para evitar la situación en la que una biblioteca intenta llamar a una API
que no está disponible en tiempo de ejecución (lo que puede hacer que la aplicación se bloquee). Si es un desarrollador
de bibliotecas, debe esforzarse por restringir el uso de las llamadas API a un subconjunto pequeño y bien establecido del
área expuesta de API total. Esto ayuda a garantizar que la biblioteca se puede usar de forma segura en una amplia gama
de versiones de Android.

Resumen
En esta guía se explica cómo se usan los niveles de API de Android para administrar la compatibilidad de aplicaciones en
diferentes versiones de Android. Proporcionó pasos detallados para configurar la plataforma de destinode Xamarin.
Android, la versión mínima de Androidy la configuración de proyecto de versión de Android de destino . Se proporcionan
instrucciones para usar el administrador de Android SDK para instalar paquetes de SDK, se incluyen ejemplos de cómo
escribir código para tratar con diferentes niveles de API en tiempo de ejecución y se explica cómo administrar los niveles
de API al crear o usar bibliotecas de Android. También proporciona una lista completa que relaciona los niveles de API
con los números de versión de Android (como Android 4,4), los nombres de versión de Android (como KitKat) y los
códigos de versión de compilación de Xamarin. Android.

Vínculos relacionados
Configuración de Android SDK
Cambios en las herramientas de la CLI de SDK
Selección de compileSdkVersion, minSdkVersion y targetSdkVersion
¿Qué es el nivel de API?
Nombres, etiquetas y números de compilación
Recursos de Android
16/08/2019 • 5 minutes to read • Edit Online

En este artículo se presenta el concepto de recursos de Android en Xamarin. Android y se documenta cómo
usarlos. En él se explica cómo usar los recursos de la aplicación de Android para admitir la localización de
aplicaciones y varios dispositivos, incluidos los tamaños y las densidades de pantalla variables.

Información general
Una aplicación Android rara vez es solo código fuente. A menudo hay muchos otros archivos que componen
una aplicación: vídeo, imágenes, fuentes y archivos de audio simplemente por nombrar algunos. Colectivamente,
estos archivos de código no fuente se conocen como recursos y se compilan (junto con el código fuente) durante
el proceso de compilación y se empaquetan como un APK para su distribución e instalación en los dispositivos:

Los recursos ofrecen varias ventajas a una aplicación de Android:


Separación de código – Separa el código fuente de imágenes, cadenas, menús, animaciones, colores,
etc. Como tales recursos pueden ayudar considerablemente al localizar.
Destino en varios dispositivos – Proporciona compatibilidad más sencilla con diferentes
configuraciones de dispositivo sin cambios de código.
Comprobación en tiempo de compilación – Los recursos son estáticos y se compilan en la aplicación.
Esto permite comprobar el uso de los recursos en tiempo de compilación, cuando será fácil detectar y
corregir los errores, en lugar de en tiempo de ejecución cuando sea más difícil de localizar y de corregir.
Cuando se inicia un nuevo proyecto de Xamarin. Android, se crea un directorio especial denominado recursos,
junto con algunos subdirectorios:
Visual Studio
Visual Studio para Mac
En la imagen anterior, los recursos de la aplicación se organizan según su tipo en estos subdirectorios: las
imágenes Irán en el directorio de Drawing. las vistas van en el subdirectorio de diseño , etc.
Hay dos maneras de tener acceso a estos recursos en una aplicación de Xamarin. Android: mediante
programación en código y de forma declarativa en XML con una sintaxis XML especial.
Estos recursos se denominan recursos predeterminados y se usan en todos los dispositivos a menos que se
especifique una coincidencia más específica. Además, cada tipo de recurso puede tener opcionalmente recursos
alternativos que Android puede usar para dirigirse a dispositivos específicos. Por ejemplo, se pueden
proporcionar recursos para el destino de la configuración regional del usuario, el tamaño de la pantalla o si el
dispositivo gira 90 grados de vertical a horizontal, etc. En cada uno de estos casos, Android cargará los recursos
para su uso por parte de la aplicación sin ningún esfuerzo de codificación adicional por parte del desarrollador.
Los recursos alternativos se especifican agregando una cadena corta,denominada calificador, al final del
directorio que contiene un tipo de recursos determinado.
Por ejemplo, Resources/drawable-de especificará las imágenes para los dispositivos que están configurados
en una configuración regional alemana, mientras que Resources -fr puede contener imágenes para dispositivos
establecidos en una configuración regional en francés. Un ejemplo de cómo proporcionar recursos alternativos
puede verse en la imagen siguiente, donde se ejecuta la misma aplicación con solo la configuración regional del
dispositivo que cambia:
En este artículo se describe el uso de los recursos y se tratan los temas siguientes:
Aspectos básicos de los recursos de Android – Usar recursos predeterminados mediante programación
y mediante declaración, agregando tipos de recursos, como imágenes y fuentes, a una aplicación.
Configuraciones específicas del dispositivo – Compatibilidad con las diferentes resoluciones de
pantalla y densidades de una aplicación.
Localización de – Mediante el uso de recursos para admitir las distintas regiones, puede usarse una
aplicación.

Vínculos relacionados
Uso de recursos de Android
Principios de la aplicación
Recursos de la aplicación
Compatibilidad con varias pantallas
Conceptos básicos de los recursos de Android
16/08/2019 • 8 minutes to read • Edit Online

Casi todas las aplicaciones de Android tendrán algún tipo de recursos. como mínimo, suelen tener los diseños de la
interfaz de usuario en forma de archivos XML. Cuando se crea una aplicación de Xamarin. Android por primera
vez, la plantilla de proyecto de Xamarin. Android configura los recursos predeterminados:
Visual Studio
Visual Studio para Mac

Los cinco archivos que componen los recursos predeterminados se crearon en la carpeta recursos:
Icon. png – icono predeterminado para la aplicación
Main. axml – el archivo de diseño de la interfaz de usuario predeterminado para una aplicación. Tenga en
cuenta que mientras Android usa la extensión de archivo . XML , Xamarin. Android usa la extensión de
archivo . axml .
Strings. XML – tabla de cadenas para ayudar con la localización de la aplicación
AboutResources. txt – no es necesario y puede eliminarse de forma segura. Solo proporciona información
general de alto nivel de la carpeta de recursos y los archivos que contiene.
Resource.Designer.CS – este archivo se genera y mantiene automáticamente en Xamarin. Android y contiene
el identificador único asignado a cada recurso. Esto es muy similar y idéntico en lo que respecta al archivo R.
Java que tendría una aplicación Android escrita en Java. Lo crean automáticamente las herramientas de
Xamarin. Android y se volverán a generar de vez en cuando.

Crear y obtener acceso a recursos


La creación de recursos es tan sencilla como agregar archivos al directorio para el tipo de recurso en cuestión. En la
captura de pantalla siguiente se muestran los recursos de cadena para las configuraciones regionales alemanas que
se agregaron a un proyecto. Cuando se agregó Strings. XML al archivo, la acción de compilación se estableció
automáticamente en AndroidResource con las herramientas de Xamarin. Android:
Visual Studio
Visual Studio para Mac

Esto permite a las herramientas de Xamarin. Android compilar e insertar correctamente los recursos en el archivo
APK. Si, por alguna razón, la acción de compilación no está establecida en el recurso de Android, los archivos
se excluirán del APK y cualquier intento de cargar o tener acceso a los recursos producirá un error en tiempo de
ejecución y la aplicación se bloqueará.
Además, es importante tener en cuenta que aunque Android solo admite nombres de archivo en minúsculas para
los elementos de recursos, Xamarin. Android es un poco más permisivo; será compatible con los nombres de
archivo en mayúsculas y minúsculas. La Convención para los nombres de imagen es usar minúsculas con
caracteres de subrayado como separadores (por ejemplo, mi_nombre de_imagen. png). Tenga en cuenta que los
nombres de recursos no se pueden procesar si los guiones o espacios se usan como separadores.
Una vez que se han agregado recursos a un proyecto, hay dos maneras de utilizarlos en una – aplicación mediante
programación (dentro del código) o de archivos XML.

Referencia a recursos mediante programación


Para tener acceso a estos archivos mediante programación, se les asigna un identificador de recurso único. Este
identificador de recurso es un entero definido en una clase especial denominada Resource , que se encuentra en el
archivo Resource.Designer.CS, y tiene un aspecto similar al siguiente:
public partial class Resource
{
public partial class Attribute
{
}
public partial class Drawable {
public const int Icon=0x7f020000;
}
public partial class Id
{
public const int Textview=0x7f050000;
}
public partial class Layout
{
public const int Main=0x7f030000;
}
public partial class String
{
public const int App_Name=0x7f040001;
public const int Hello=0x7f040000;
}
}

Cada identificador de recurso se encuentra dentro de una clase anidada que corresponde al tipo de recurso. Por
ejemplo, cuando se agregó el archivo Icon. png al proyecto, Xamarin. Android actualizó la Resource clase,
creando una clase anidada denominada Drawable con una constante dentro de Icon denominada. Esto permite
hacer referencia al archivo Icon. png en el código como Resource.Drawable.Icon . La Resource clase no se debe
editar manualmente, ya que Xamarin. Android sobrescribirá los cambios que se realicen en ella.
Al hacer referencia a los recursos mediante programación (en el código), se puede tener acceso a ellos a través de
la jerarquía de clases Resources, que usa la sintaxis siguiente:

[<PackageName>.]Resource.<ResourceType>.<ResourceName>

Packagename – El paquete que proporciona el recurso y solo es necesario cuando se usan recursos de
otros paquetes.
Resourcetype – Este es el tipo de recurso anidado que se encuentra dentro de la clase de recursos que se
ha descrito anteriormente.
Nombre del recurso – es el nombre de archivo del recurso (sin la extensión) o el valor del atributo
Android: Name para los recursos que están en un elemento XML.

Referencia a recursos desde XML


Se obtiene acceso a los recursos de un archivo XML mediante una sintaxis especial:

@[<PackageName>:]<ResourceType>/<ResourceName>

Packagename – el paquete que proporciona el recurso y solo es necesario cuando se usan recursos de
otros paquetes.
Resourcetype – Este es el tipo de recurso anidado que se encuentra dentro de la clase de recursos.
Nombre del recurso es el nombre de archivo del recurso (sin la extensión de tipo de archivo) o
android:name el valor del atributo para los recursos que están en un elemento XML. –

Por ejemplo, el contenido de un archivo de diseño, Main. axml, es el siguiente:


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ImageView android:id="@+id/myImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/flag" />
</LinearLayout>

Este ejemplo tiene un ImageView que requiere una marcade nombre de recurso dibujable. Tiene su src atributo
establecido en @drawable/flag . ImageView Cuando se inicia la actividad, Android buscará en el recurso de
directorio o dibujable para un archivo denominado Flag. png (la extensión de archivo podría ser otro formato de
imagen, como Flag. jpg) y cargar ese archivo y ImageView mostrarlo en el. Cuando se ejecuta esta aplicación,
tendría un aspecto similar al de la siguiente imagen:
Recursos predeterminados
16/08/2019 • 9 minutes to read • Edit Online

Los recursos predeterminados son elementos que no son específicos de un determinado dispositivo o factor de
forma y, por lo tanto, son la opción predeterminada del sistema operativo Android si no se pueden encontrar más
recursos específicos. Como tal, son el tipo más común de recurso que se va a crear. Están organizados en
subdirectorios del directorio de recursos según su tipo de recurso:
Visual Studio
Visual Studio para Mac

En la imagen anterior, el proyecto tiene valores predeterminados para los recursos, diseños y valores que se van a
dibujar (archivos XML que contienen valores simples).
A continuación se proporciona una lista completa de los tipos de recursos:
animación de – Archivos XML que describen animaciones de propiedades. Las animaciones de
propiedades se introdujeron en el nivel de API 11 (Android 3,0) y proporcionan la animación de
propiedades en un objeto. Las animaciones de propiedades son una forma más flexible y eficaz de describir
animaciones en cualquier tipo de objeto.
Anim Archivos XML que describen animaciones de intercalación. – Las animaciones de interpolación son
una serie de instrucciones de animación para realizar transformaciones en el contenido de un objeto de
vista, o por ejemplo, la rotación de una imagen o el aumento del tamaño del texto. Las animaciones de
interpolación están limitadas solo a objetos de vista.
color de – Archivos XML que describen una lista de Estados de los colores. Para comprender las listas de
Estados de color, considere la posibilidad de usar un widget de interfaz de usuario, como un botón. Puede
tener distintos Estados, como presionar o deshabilitar, y el botón puede cambiar de color con cada cambio
de estado. La lista se expresa en una lista de Estados.
dibujo – Los recursos dibujables son un concepto general para los gráficos que se pueden compilar en la
aplicación y a los que se tiene acceso mediante llamadas API o a los que hacen referencia otros recursos
XML. Algunos ejemplos de drawables son los archivos de mapa de bits (. png,. gif,. jpg), mapas de bits
redimensionables especiales conocidos como nueve revisiones, listas de Estados, formas genéricas definidas
en XML, etc.
diseño de – Archivos XML que describen un diseño de interfaz de usuario, como una actividad o una fila de
una lista.
menú de Archivos XML que describen los menús de la aplicación, como menús de opciones,
menúscontextuales y submenús. – Para obtener un ejemplo de menús, vea la demostración del menú
emergente o el ejemplo de controles estándar .
sin formato – Archivos arbitrarios que se guardan en formato binario y sin formato. Estos archivos se
compilan en una aplicación Android en formato binario.
valores de – Archivos XML que contienen valores simples. Un archivo XML en el directorio Values no
define un solo recurso, sino que puede definir varios recursos. Por ejemplo, un archivo XML puede contener
una lista de valores de cadena, mientras que otro archivo XML puede contener una lista de valores de color.
archivos XML XML que son similares en función de los archivos de configuración de .net. – Se trata de XML
arbitrario que la aplicación puede leer en tiempo de ejecución.
Recursos alternativos
16/08/2019 • 18 minutes to read • Edit Online

Los recursos alternativos son aquellos que tienen como destino un dispositivo específico o una configuración en
tiempo de ejecución, como el idioma actual, el tamaño de pantalla concreto o la densidad de píxeles. Si Android
puede coincidir con un recurso más específico para un determinado dispositivo o configuración que el recurso
predeterminado, se utilizará ese recurso en su lugar. Si no encuentra un recurso alternativo que coincida con la
configuración actual, se cargarán los recursos predeterminados. La forma en que Android decide qué recursos
usará una aplicación se tratará con más detalle a continuación, en la sección Ubicación de recursos.
Los recursos alternativos se organizan como un subdirectorio dentro de la carpeta recursos según el tipo de
recurso, al igual que los recursos predeterminados. El nombre del subdirectorio de recurso alternativo tiene el
formato siguiente: ResourceType-Qualifier
El calificador es un nombre que identifica una configuración específica del dispositivo. Puede haber más de un
calificador en un nombre, cada uno de ellos separado por un guión. Por ejemplo, la captura de pantalla siguiente
muestra un proyecto simple que tiene recursos alternativos para varias configuraciones, como la configuración
regional, la densidad de la pantalla, el tamaño de la pantalla y la orientación:
Visual Studio
Visual Studio para Mac

Al agregar calificadores a un tipo de recurso, se aplican las siguientes reglas:


1. Puede haber más de un calificador, donde cada calificador está separado por un guión.
2. Es posible que los calificadores solo se especifiquen una vez.
3. Los calificadores deben estar en el orden en que aparecen en la tabla siguiente.
Los calificadores posibles se enumeran a continuación como referencia:
MCC y MNC El código de país móvil (MCC ) y, opcionalmente, el código de red móvil (MNC ). – La tarjeta
SIM proporcionará la MCC, mientras que la red a la que está conectado el dispositivo proporcionará el
MNC. Aunque es posible destinar a las configuraciones regionales con el código de país móvil, el enfoque
recomendado es usar el calificador de lenguaje que se especifica a continuación. Por ejemplo, para dirigirse
a los recursos a Alemania, el mcc262 calificador sería. Para dirigirse a recursos de T-Mobile en EE. UU., el
mcc310-mnc026 calificador es. Para obtener una lista completa de códigos de país móvil y códigos de
http://mcc-mnc.com/red móvil, consulte.
Idioma de El código de idioma ISO 639-1 de dos letras y, opcionalmente, seguido del código de la región
ISO -3166-Alpha-2de dos letras. – Si se proporcionan ambos calificadores, se separan mediante un -r . Por
ejemplo, para tener como destino las configuraciones regionales en francés, se fr usa el calificador de.
Para tener como destino las fr-rCA configuraciones regionales en francés (Canadá), se utilizaría. Para
obtener una lista completa de códigos de idioma y códigos de región, consulte códigos para la
representación de los nombres de los idiomas y los nombres de los países y los elementos de código.
Menor ancho – Especifica el ancho de pantalla más pequeño en el que se va a ejecutar la aplicación. Se
describe con más detalle en creación de recursos para diferentes pantallas. Disponible en el nivel de API 13
(Android 3,2) y versiones posteriores. Por ejemplo, el calificador sw320dp se usa para destinar dispositivos
cuyo alto y ancho sea al menos 320dp.
Ancho disponible El ancho mínimo de la pantalla con el formato wnDP, donde n es el ancho en píxeles
independientes de densidad. – Este valor puede cambiar a medida que el usuario gira el dispositivo. Se
describe con más detalle en creación de recursos para diferentes pantallas. Disponible en el nivel de API 13
(Android 3,2) y versiones posteriores. Ejemplo: el calificador w720dp se usa para dispositivos de destino
que tienen un ancho de menos de 720dp.
Alto disponible El alto mínimo de la pantalla con el formato hnDP, donde N es el alto de DP. – Este valor
puede cambiar a medida que el usuario gira el dispositivo. Se describe con más detalle en creación de
recursos para diferentes pantallas. Disponible en el nivel de API 13 (Android 3,2) y versiones posteriores.
Por ejemplo, el calificador h720dp se usa para dispositivos de destino que tienen un alto de menos de
720dp
Tamaño de pantalla – Este calificador es una generalización del tamaño de la pantalla para el que son
estos recursos. Se trata con más detalle en la creación de recursos para diferentes pantallas. Los valores
posibles son small , normal , large y xlarge . Agregado en el nivel de API 9 (Android 2.3/Android
2.3.1/Android 2.3.2)
Aspecto de la pantalla – Esto se basa en la relación de aspecto, no en la orientación de la pantalla. Una
pantalla larga es más ancha. Agregado en el nivel de API 4 (Android 1,6). Los valores posibles son Long e
notlong.
Orientación de la pantalla – Orientación de pantalla vertical u horizontal. Esto puede cambiar durante la
vigencia de una aplicación. Los valores posibles son port y land .
Modo de acoplamiento – En el caso de los dispositivos de una base de coche o un muelle de mesa.
Agregado en el nivel de API 8 (Android 2.2. x). Los valores posibles son car y desk .
Modo nocturno – Si la aplicación se está ejecutando por la noche o en el día. Esto puede cambiar durante
la vigencia de una aplicación y está diseñado para ofrecer a los desarrolladores una oportunidad de usar
versiones más oscuras de una interfaz por la noche. Agregado en el nivel de API 8 (Android 2.2. x). Los
valores posibles son night y notnight .
Densidad de píxeles de pantalla (PPP ) – Número de píxeles de un área determinada en la pantalla física.
Normalmente expresado como puntos por pulgada (PPP ). Los valores posibles son:
ldpi – Pantallas de baja densidad.
mdpi – Pantallas de densidad media
hdpi – Pantallas de alta densidad
xhdpi – Pantallas de alta densidad adicional
nodpi – Recursos que no se van a escalar
tvdpi – Introducido en el nivel de API 13 (Android 3,2) para pantallas entre pantallas y hdpi.
Tipo de pantalla táctil – Especifica el tipo de pantalla táctil que puede tener un dispositivo. Los valores
posibles notouch son (sin pantalla táctil) stylus , (una pantalla táctil resistente adecuada para un lápiz) y
finger (una pantalla táctil).

Disponibilidad del teclado – Especifica qué tipo de teclado está disponible. Esto puede cambiar durante
la vigencia de una aplicación – , por ejemplo, cuando un usuario abre un teclado de hardware. Los valores
posibles son:
keysexposed – El dispositivo tiene un teclado disponible. Si no hay ningún teclado de software
habilitado, solo se utilizará cuando se abra el teclado de hardware.
keyshidden– El dispositivo tiene un teclado de hardware, pero está oculto y no hay ningún teclado de
software habilitado.
keyssoft – el dispositivo tiene un teclado de software habilitado.
Método de entrada de texto principal – Utilice para especificar qué tipos de claves de hardware están
disponibles para la entrada. Los valores posibles son:
nokeys – No hay claves de hardware para la entrada.
qwerty – Hay un teclado QWERTY disponible.
12key – Hay un teclado de hardware de 12 teclas
Disponibilidad de la clave de navegación – Para cuando esté disponible la navegación de 5 o d (pad
direccional). Esto puede cambiar durante la vigencia de la aplicación. Los valores posibles son:
navexposed – las teclas de navegación están disponibles para el usuario
navhidden – las teclas de navegación no están disponibles.
Método de navegación no táctil principal – El tipo de navegación disponible en el dispositivo. Los
valores posibles son:
nonav – la única característica de navegación disponible es la pantalla táctil
dpad – un panel de control de acceso (PAD ) está disponible para la navegación
trackball – el dispositivo tiene un trackball para la navegación
wheel – escenario poco frecuente en el que hay una o varias ruedas direccionales disponibles
Versión de la plataforma (nivel de API ) El nivel de API que admite el dispositivo en el formato vn,
donde N es el nivel de API que se va a usar como destino. – Por ejemplo, V11 se dirigirá a un dispositivo de
nivel de API 11 (Android 3,0).
Para obtener información más completa sobre los calificadores de recursos, vea proporcionar recursos en el sitio
web de desarrolladores de Android.

Cómo determina Android qué recursos usar


Es muy posible y es probable que una aplicación Android contenga muchos recursos. Es importante comprender
cómo Android seleccionará los recursos de una aplicación cuando se ejecuta en un dispositivo.
Android determina la base de recursos mediante la iteración de la siguiente prueba de reglas:
Eliminación de calificadores contradictorios – por ejemplo, si la orientación del dispositivo es vertical, se
rechazarán todos los directorios de recursos del entorno.
Omitir calificadores no admitidos – No todos los calificadores están disponibles para todos los niveles
de API. Si un directorio de recursos contiene un calificador que no es compatible con el dispositivo, se
omitirá ese directorio de recursos.
Identificar el calificador de mayor prioridad siguiente – al hacer referencia a la tabla anterior, se
selecciona el calificador de prioridad superior siguiente (de arriba abajo).
Mantener los directorios de recursos para el calificador – si hay algún directorio de recursos que
coincida con el calificador de la tabla anterior, seleccione el calificador de prioridad más alta (de arriba
abajo).
Estas reglas también se muestran en el diagrama de flujo siguiente:

Cuando el sistema busca recursos específicos de la densidad y no los encuentra, intentará localizar otros recursos
específicos de la densidad y escalarlos. Es posible que Android no use necesariamente los recursos
predeterminados. Por ejemplo, al buscar un recurso de baja densidad y no está disponible, Android puede
seleccionar la versión de alta densidad del recurso a través de los recursos predeterminados o de densidad media.
Esto se debe a que el recurso de alta densidad puede reducirse en un factor de 0,5, lo que producirá menos
problemas de visibilidad que el escalado vertical de un recurso de densidad media, lo que requeriría un factor de
0,75.
Como ejemplo, considere una aplicación que tiene los siguientes directorios de recursos Dibujables:
drawable
drawable-en
drawable-fr-rCA
drawable-en-port
drawable-en-notouch-12key
drawable-en-port-ldpi
drawable-port-ldpi
drawable-port-notouch-12key

Y ahora la aplicación se ejecuta en un dispositivo con la configuración siguiente:


Configuración regional – en-GB
Orientación – puerto de
Densidad de pantalla – hdpi
Tipo de pantalla táctil – NoTouch
Método de entrada principal – 12key
Para empezar, los recursos en francés se eliminan a medida que entran en conflicto en-GB con la configuración
regional de, y nos dejan con:

drawable
drawable-en
drawable-en-port
drawable-en-notouch-12key
drawable-en-port-ldpi
drawable-port-ldpi
drawable-port-notouch-12key

A continuación, se selecciona el primer calificador de la tabla de calificadores anterior: MCC y MNC. No hay
directorios de recursos que contengan este calificador, por lo que se omite el código de MCC/MNC.
Se selecciona el siguiente calificador, que es el idioma. Hay recursos que coinciden con el código de idioma. Se
rechazan todos los directorios de recursos que no coinciden con el código de idioma de en , de modo que la lista
de recursos es ahora:

drawable-en-port
drawable-en-notouch-12key
drawable-en-port-ldpi

El siguiente calificador que está presente es para la orientación de la pantalla, por lo que se eliminan todos los
port directorios de recursos que no coinciden con la orientación de la pantalla de:

drawable-en-port
drawable-en-port-ldpi

El siguiente es el calificador para la ldpi densidad de pantalla,, lo que da como resultado la exclusión de un
directorio de recursos más:

drawable-en-port-ldpi

Como resultado de este proceso, Android usará los recursos que se dibujan en el directorio drawable-en-port-ldpi
de recursos para el dispositivo.
NOTE
Los calificadores de tamaño de pantalla proporcionan una excepción a este proceso de selección. Es posible que Android
seleccione recursos diseñados para una pantalla más pequeña que el que proporciona el dispositivo actual. Por ejemplo, un
dispositivo de pantalla grande puede usar los recursos proporcionados para una pantalla de tamaño normal. Sin embargo, lo
contrario no es cierto: el mismo dispositivo de pantalla grande no usará los recursos proporcionados para una pantalla de
xlarge. Si Android no encuentra un conjunto de recursos que coincida con un tamaño de pantalla determinado, se bloqueará
la aplicación.
Crear recursos para diferentes pantallas
27/07/2019 • 15 minutes to read • Edit Online

Android se ejecuta en muchos dispositivos diferentes, cada uno con una amplia variedad de resoluciones,
tamaños de pantalla y densidades de pantalla. Android realizará el escalado y el cambio de tamaño para que la
aplicación funcione en estos dispositivos, pero esto puede dar lugar a una experiencia de usuario poco óptima.
Por ejemplo, las imágenes podrían aparecer borrosas o pueden estar colocadas como se esperaba en una vista.

Conceptos
Es importante comprender algunos términos y conceptos para admitir varias pantallas.
Tamaño de pantalla – La cantidad de espacio físico para mostrar la aplicación
Densidad de pantalla – Número de píxeles de un área determinada de la pantalla. La unidad de medida
típica es puntos por pulgada (PPP ).
Solución de – Número total de píxeles en la pantalla. Al desarrollar aplicaciones, la resolución no es tan
importante como el tamaño y la densidad de la pantalla.
Píxel independiente de la densidad (DP ) – Unidad de medida virtual que permite diseñar diseños
independientes de la densidad. Esta fórmula se usa para convertir el DP en píxeles de pantalla:
PX = DP × PPP 160÷
Orientación – La orientación de la pantalla se considera horizontal cuando es más ancha que la alta. En
cambio, la orientación vertical es cuando la pantalla es más alta que la ancha. La orientación puede
cambiar durante la vigencia de una aplicación cuando el usuario gira el dispositivo.
Observe que los tres primeros de estos conceptos se relacionan entre – sí al aumentar la resolución sin aumentar
la densidad, lo que aumentará el tamaño de la pantalla. Sin embargo, si aumentan la densidad y la resolución, el
tamaño de la pantalla puede permanecer sin cambios. Esta relación entre el tamaño de la pantalla, la densidad y
la resolución complica la compatibilidad con la pantalla rápidamente.
Para ayudar a abordar esta complejidad, el marco de trabajo de Android prefiere usar píxeles independientes de
la densidad (DP ) para los diseños de pantalla. Mediante el uso de píxeles independientes de densidad, los
elementos de la interfaz de usuario aparecerán para que el usuario tenga el mismo tamaño físico en las pantallas
con diferentes densidades.

Compatibilidad con varios tamaños de pantalla y densidades


Android controla la mayor parte del trabajo para presentar los diseños correctamente para cada configuración
de pantalla. Sin embargo, se pueden realizar algunas acciones para ayudar al sistema a salir.
El uso de píxeles independientes de la densidad en lugar de píxeles reales en los diseños es suficiente en la
mayoría de los casos para garantizar la independencia de la densidad. Android escalará el drawables en tiempo
de ejecución al tamaño adecuado. Sin embargo, es posible que el escalado provoque que los mapas de bits
parezcan borrosos. Para solucionar este problema, proporcione recursos alternativos para las diferentes
densidades. Al diseñar dispositivos para varias resoluciones y densidades de pantalla, resultará más fácil
empezar con las imágenes de mayor resolución o densidad y, a continuación, reducir verticalmente.
Declarar el tamaño de pantalla compatible
La declaración del tamaño de la pantalla garantiza que solo los dispositivos compatibles puedan descargar la
aplicación. Esto se logra estableciendo el elemento Supports-Screens en el archivo archivo AndroidManifest.
XML . Este elemento se usa para especificar los tamaños de pantalla admitidos por la aplicación. Se considera
que una pantalla determinada es compatible Si la aplicación puede colocar correctamente sus diseños en la
pantalla de relleno. Al usar este elemento de manifiesto, la aplicación no se mostrará en Google Play para los
dispositivos que no cumplan las especificaciones de pantalla. Sin embargo, la aplicación todavía se ejecutará en
dispositivos con pantallas no compatibles, pero los diseños pueden aparecer borrosos y con Pixelizar.
Los Sixes de pantalla admitidos se declaran en el archivo Configurations /archivo AndroidManifest. XML de
la solución:
Visual Studio
Visual Studio para Mac

Edite archivo AndroidManifest. XML para incluir Supports-Screens:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1"
android:versionName="1.0"
package="HelloWorld.HelloWorld">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="27" />
<supports-screens android:resizable="true"
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true" />
<application android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true" android:theme="@style/AppTheme">
</application>
</manifest>

Proporcionar diseños alternativos para diferentes tamaños de pantalla


Los diseños alternativos permiten personalizar una vista para un tamaño de pantalla de específico, cambiando la
posición o el tamaño de los elementos de la interfaz de usuario del componente.
A partir del nivel de API 13 (Android 3,2), los tamaños de pantalla están en desuso en favor de usar el
calificadorNDP de SW. Este nuevo calificador declara la cantidad de espacio que necesita un diseño
determinado. Se recomienda que las aplicaciones que están diseñadas para ejecutarse en Android 3,2 o superior
deben usar estos calificadores más recientes.
Por ejemplo, si un diseño requirió un mínimo de 700 DP de ancho de pantalla, el diseño alternativo se incluiría
en una carpeta layout-sw700dp:
Visual Studio
Visual Studio para Mac
Como directriz, estos son algunos números para varios dispositivos:
Teléfono típico – 320 DP: un teléfono típico
Un dispositivo 5 "Tablet/" Tweener " – 480 DP: por ejemplo, la nota de Samsung
Una tableta de 7 " 600 DP: por ejemplo, el Nook de Barnes &noble –
Una tableta de 10 " – 720 DP: por ejemplo, el Xoom de Motorola
En el caso de las aplicaciones que tienen como destino niveles de API de hasta 12 (Android 3,1), los diseños
deben ir en directorios que usan los calificadores Small/Xlarge grandes/normales/como generalizaciones de
los distintos tamaños de pantalla que están disponibles en la mayoría de los dispositivos. Por ejemplo, en la
imagen siguiente, existen recursos alternativos para los cuatro tamaños de pantalla diferentes:
Visual Studio
Visual Studio para Mac

A continuación se explica cómo se comparan los calificadores de tamaño de pantalla de nivel 13 anteriores de la
API anterior con los píxeles independientes de la densidad:
426 DP x 320 DP es pequeño
470 DP x 320 DP es normal
640 DP x 480 DP es grande
960 DP x 720 DP es Xlarge
Los calificadores de tamaño de pantalla más recientes en el nivel de API 13 y superior tienen una prioridad más
alta que los calificadores de pantalla más antiguos de los niveles de API 12 y inferiores. En el caso de las
aplicaciones que abarcarán los niveles de API antiguos y nuevos, puede que sea necesario crear recursos
alternativos con ambos conjuntos de calificadores, tal como se muestra en la siguiente captura de pantalla:
Visual Studio
Visual Studio para Mac

Proporcionar diferentes mapas de bits para diferentes densidades de pantalla


Aunque Android escalará los mapas de bits según sea necesario para un dispositivo, los propios mapas de bits
no se pueden escalar o reducir verticalmente de forma elegante: pueden ser aproximados o borrosos. Si
proporciona mapas de bits adecuados para la densidad de pantalla, se solucionará este problema.
Por ejemplo, la imagen siguiente es un ejemplo de problemas de diseño y apariencia que pueden producirse
cuando no se proporcionan recursos de especificación de densidad.

Compárelo con un diseño que esté diseñado con recursos específicos de la densidad:

Creación de recursos de densidad variable con Android Asset Studio


La creación de estos mapas de bits de diversas densidades puede ser un poco tediosa. Como tal, Google ha
creado una utilidad en línea que puede reducir algunos de los tediosas tareas implicados en la creación de estos
mapas de bits denominados Android Asset Studio.

Este sitio web le ayudará en la creación de mapas de bits que tienen como destino las cuatro densidades de
pantalla comunes mediante el suministro de una imagen. Después, Android Asset Studio creará los mapas de
bits con algunas personalizaciones y, a continuación, permitirá que se descarguen como un archivo zip.
Sugerencias para varias pantallas
Android se ejecuta en un número de dispositivos desconcertante, y la combinación de los tamaños de pantalla y
las densidades de pantalla puede parecer abrumadora. Las siguientes sugerencias pueden ayudarle a minimizar
el esfuerzo necesario para admitir varios dispositivos:
Solo diseño y desarrollo para lo que necesita – Existen muchos dispositivos diferentes, pero algunos
existen en factores de forma poco frecuentes que pueden suponer un esfuerzo importante para diseñar y
desarrollar para. El panel de densidad y tamaño de pantalla es una página proporcionada por Google
que proporciona datos sobre el desglose de la matriz de densidad de pantalla o el tamaño de la pantalla.
Este desglose proporciona información sobre cómo desarrollar el esfuerzo en las pantallas de soporte
técnico.
Usar DPS en lugar de píxeles -píxeles se vuelve problemático a medida que cambia la densidad de la
pantalla. No codificar valores de píxeles. Evite píxeles en favor de DP (píxeles independientes de la
densidad).
Evitar AbsoluteLayout Siempre que sea posible – , está en desuso en el nivel de API 3 (Android 1,5) y
dará como resultado diseños frágiles. No debe usarse. En su lugar, intente usar widgets de diseño más
flexibles como LinearLayout, RelativeLayouto el nuevo GridLayout.
Elegir una orientación de diseño como predeterminada Por ejemplo, en lugar de proporcionar los
recursos alternativos y el puerto de diseño, coloque los recursos para el panorama en el diseño y los
recursos de vertical en el puerto de diseño. –
Usar LayoutParams para el alto y el ancho : al definir los elementos de la interfaz de usuario en un
archivo de diseño XML, una aplicación Android que use los valores wrap_content y fill_parent tendrá
más éxito y garantizará una apariencia adecuada en los distintos dispositivos que usar unidades
independientes de píxeles o de densidad. Estos valores de dimensión hacen que Android escale los
recursos de mapa de bits según corresponda. Por esta misma razón, las unidades independientes de la
densidad se reservan mejor para cuando se especifican los márgenes y el relleno de los elementos de la
interfaz de usuario.

Probar varias pantallas


Una aplicación Android debe probarse con todas las configuraciones que se admitirán. Idealmente, los
dispositivos deben probarse en los propios dispositivos reales, pero en muchos casos esto no es posible o
práctico. En este caso, será útil el uso del emulador y el programa de instalación de dispositivos virtuales Android
para cada configuración de dispositivo.
El Android SDK proporciona algunas máscaras del emulador que se pueden usar para crear AVD replicará el
tamaño, la densidad y la resolución de muchos dispositivos. Muchos de los proveedores de hardware
proporcionan también máscaras para sus dispositivos.
Otra opción es usar los servicios de un servicio de prueba de terceros. Estos servicios tomarán un APK, lo
ejecutarán en muchos dispositivos diferentes y, a continuación, proporcionarán comentarios sobre cómo
funcionó la aplicación.
Localización de aplicaciones y recursos de cadena
11/07/2019 • 2 minutes to read • Edit Online

Localización de aplicaciones es el acto de proporcionar recursos alternativos para una región específica o la
configuración regional de destino. Por ejemplo, podría proporcionar cadenas traducidas para distintos países, o
puede cambiar los colores ni el diseño para que coincida con referencias culturales determinadas. Android cargará
y usar los recursos adecuados para la configuración regional del dispositivo en tiempo de ejecución sin realizar
ningún cambio en el código fuente.
Por ejemplo, la imagen siguiente muestra la misma aplicación que se ejecuta en tres configuraciones regionales de
otro dispositivo, pero es específico para la configuración regional que cada dispositivo se establece en el texto
mostrado en cada botón:

En este ejemplo, el contenido de un archivo de diseño, Main.axml es algo parecido a esto:

<?xml version="1.0" encoding="utf-8"?>


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<Button
android:id="@+id/myButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
/>
</LinearLayout>

En el ejemplo anterior, la cadena para el botón se cargó desde los recursos al proporcionar el identificador de
recurso para la cadena:
Visual Studio
Visual Studio para Mac
Localización de aplicaciones Android
Leer el Introducción a la localización para sugerencias e instrucciones sobre la localización de aplicaciones móviles.
El localizar aplicaciones Android guía contiene ejemplos más específicos sobre cómo traducir cadenas y localizar
imágenes con Xamarin.Android.

Vínculos relacionados
Localización de aplicaciones Android
Información general de localización de multiplataforma
Uso de recursos de Android
27/07/2019 • 2 minutes to read • Edit Online

Los recursos proporcionan una manera de incluir archivos arbitrarios como texto, XML, fuentes, música y vídeo en
la aplicación. Si intenta incluir estos archivos como "recursos", Android los procesará en su sistema de recursos y
no podrá obtener los datos sin procesar. Si desea tener acceso a los datos sin tocar, los recursos son una forma de
hacerlo.
Los recursos agregados al proyecto se mostrarán como un sistema de archivos que puede leer la aplicación
mediante AssetManager. En esta sencilla demostración, vamos a agregar un recurso de archivo de texto a nuestro
proyecto, a leerlo con AssetManager y a mostrarlo en una TextView.

Agregar activo al proyecto


Los recursos van en Assets la carpeta del proyecto. Agregue un nuevo archivo de texto a esta carpeta
read_asset.txt denominada. Coloque texto en él como "he recibido de un recurso".

Visual Studio
Visual Studio para Mac
Visual Studio debe haber establecido la acción de compilación para este archivo en AndroidAsset:

Al seleccionar la opción BuildAction correcta se garantiza que el archivo se empaquetará en el APK en tiempo de
compilación.

Leer recursos
Los recursos se leen mediante un AssetManager. Una instancia del AssetManager está disponible mediante el
acceso a la propiedad assets en Android.Content.Context , como una actividad. En el código siguiente, se abre
nuestro recurso read_asset. txt , se lee el contenido y se muestra mediante una TextView.
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);

// Create a new TextView and set it as our view


TextView tv = new TextView (this);

// Read the contents of our asset


string content;
AssetManager assets = this.Assets;
using (StreamReader sr = new StreamReader (assets.Open ("read_asset.txt")))
{
content = sr.ReadToEnd ();
}

// Set TextView.Text to our asset content


tv.Text = content;
SetContentView (tv);
}

Ejecutar la aplicación
Ejecute la aplicación y verá lo siguiente:

Vínculos relacionados
AssetManager
Contexto
Fuentes
11/07/2019 • 23 minutes to read • Edit Online

Información general
A partir de nivel de API 26, el SDK de Android permite las fuentes se traten como recursos, al igual que un diseños
o recursos drawable. El Android soporte biblioteca 26 NuGet le restituir la nueva fuente de la API para aquellas
aplicaciones que tienen como destino el nivel de API 14 o superior.
Después de la API 26 tiene como destino o instalando el v26 Android Support Library, hay dos maneras de utilizar
las fuentes en una aplicación de Android:
1. Empaquetar la fuente como un recurso de Android – Esto garantiza que la fuente esté siempre disponible
para la aplicación, pero aumentará el tamaño del APK.
2. Descargar las fuentes – Android también admite la descarga de una fuente de un proveedor de fuente. El
proveedor de fuente comprueba si la fuente ya está en el dispositivo. Si es necesario, la fuente se descargará y
se almacena en caché en el dispositivo. Esta fuente se puede compartir entre varias aplicaciones.
Fuentes similares (o una fuente que puede tener varios estilos diferentes) puede agruparse en familias de fuentes.
Esto permite a los desarrolladores especificar ciertos atributos de la fuente, como su peso, y Android seleccionará
automáticamente la fuente adecuada de la familia de fuentes.
El v26 Android Support Library va a restituir compatibilidad con fuentes a nivel de API 26. Cuando el destino de
los niveles de API anteriores, es necesario declarar el app espacio de nombres XML y entre los distintos atributos
de fuente mediante la android: espacio de nombres y el app: espacio de nombres. Si solo el android: se utiliza
el espacio de nombres, las fuentes no se muestran dispositivos que ejecutan el nivel de API 25 o menos. Por
ejemplo, este fragmento de código XML declara un nuevo familia de fuentes recursos que funcionarán en el nivel
de API 14 o superior:

<?xml version="1.0" encoding="utf-8"?>


<font-family
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">

<font android:font="@font/sourcesanspro_regular"
android:fontStyle="normal"
android:fontWeight="400"
app:font="@font/sourcesanspro_regular"
app:fontStyle="normal"
app:fontWeight="400" />

</font-family>

Se proporcionan fuentes a una aplicación Android de forma adecuada, siempre que se pueden aplicar a un widget
de interfaz de usuario estableciendo el fontFamily atributo. Por ejemplo, el fragmento de código siguiente muestra
cómo mostrar una fuente en una vista de texto:
<TextView
android:text="The quick brown fox jumped over the lazy dog."
android:fontFamily="@font/sourcesanspro_regular"
app:fontFamily="@font/sourcesanspro_regular"
android:textAppearance="?android:attr/textAppearanceLarge"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

Esta guía se explique cómo usar las fuentes como un recurso de Android en primer lugar y, a continuación, pasar a
explicar cómo descargar fuentes en tiempo de ejecución.

Fuentes como un recurso


Empaquetar una fuente en un APK de Android, se garantiza que siempre esté disponible para la aplicación. Un
archivo de fuentes (ya sea una. THF o. Archivo OTF ) se agrega a una aplicación de Xamarin.Android, al igual que
cualquier otro recurso, copiando los archivos en un subdirectorio en el recursos carpeta de un proyecto de
Xamarin.Android. Los recursos de fuentes se mantienen un fuente : el subdirectorio de la recursos carpeta del
proyecto.

NOTE
Las fuentes deben tener un acción de compilación de AndroidResource o no se empaquetarán en el APK final. La acción
de compilación debe establecerse automáticamente por el IDE.

Cuando hay muchos archivos de fuente similares (por ejemplo, la misma fuente con diferentes ponderaciones o
estilos) es posible agruparlos en una familia de fuentes.
Familias de fuentes
Una familia de fuentes es un conjunto de fuentes que tienen los estilos y pesos diferentes. Por ejemplo, puede
haber archivos de fuentes independiente para las fuentes en negrita o cursiva. La familia de fuentes se define
mediante font elementos en un archivo XML que se mantiene en el recursos/fuente directory. Cada familia de
fuentes debe tener su propio archivo XML.
Para crear una familia de fuentes, primero agregue todas las fuentes a la recursos/fuente carpeta. A continuación,
cree un nuevo archivo XML en la carpeta de fuentes para la familia de fuentes. El nombre del archivo XML no tiene
ninguna afinidad o la relación que las fuentes que se hace referencia; el archivo de recursos puede ser cualquier
nombre de archivo de recursos de Android legal. Este archivo XML tendrá una raíz font-family elemento que
contiene uno o varios font elementos. Cada font elemento declara los atributos de una fuente.
El siguiente código XML es un ejemplo de una familia de fuentes para el orígenes SAN Pro fuente que define los
pesos de muchas fuentes diferentes. Esto se guarda como archivo en el recursos/fuente carpeta denominada
sourcesanspro.xml:
<?xml version="1.0" encoding="utf-8"?>
<font-family xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<font android:font="@font/sourcesanspro_regular"
android:fontStyle="normal"
android:fontWeight="400"
app:font="@font/sourcesanspro_regular"
app:fontStyle="normal"
app:fontWeight="400" />
<font android:font="@font/sourcesanspro_bold"
android:fontStyle="normal"
android:fontWeight="800"
app:font="@font/sourcesanspro_bold"
app:fontStyle="normal"
app:fontWeight="800" />
<font android:font="@font/sourcesanspro_italic"
android:fontStyle="italic"
android:fontWeight="400"
app:font="@font/sourcesanspro_italic"
app:fontStyle="italic"
app:fontWeight="400" />
</font-family>

El fontStyle atributo tiene dos valores posibles:


normal – una fuente normal
cursiva – una fuente en cursiva
El fontWeight atributo corresponde a la hoja CSS font-weight atributo y hace referencia el grosor de la fuente. Se
trata de un valor en el intervalo de 100 a 900. En la lista siguiente se describe los valores de peso de fuente
comunes y su nombre:
Thin – 100
Extra claro – 200
Luz – 300
Normal – 400
Medio – 500
Negrita semi – 600
Bold – 700
Extra-negrita – 800
Negro – 900
Una vez que se ha definido una familia de fuentes, se puede utilizar mediante declaración estableciendo el
fontFamily , textStyle , y fontWeight atributos en el archivo de diseño. Por ejemplo, el fragmento XML siguiente
establece una fuente 600 peso (normal) y un estilo de texto en cursiva:

<TextView
android:text="Sans Source Pro semi-bold italic, 600 weight, italic"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="@font/sourcesanspro"
android:textAppearance="?android:attr/textAppearanceLarge"
android:gravity="center_horizontal"
android:fontWeight="600"
android:textStyle="italic"
/>

Asignar mediante programación las fuentes


Las fuentes se pueden establecer mediante programación utilizando la Resources.GetFont método para recuperar
un Typeface objeto. Muchas de las vistas tienen un TypeFace propiedad que puede usarse para asignar la fuente
para el widget. Este fragmento de código muestra cómo establecer mediante programación la fuente en una vista
de texto:

Android.Graphics.Typeface typeface = this.Resources.GetFont(Resource.Font.caveat_regular);


textView1.Typeface = typeface;
textView1.Text = "Changed the font";

El GetFont método cargará automáticamente la primera fuente dentro de una familia de fuentes. Para cargar una
fuente que coincide con un estilo determinado, use el Typeface.Create método. Este método intentará cargar una
fuente que coincide con el estilo especificado. Por ejemplo, este fragmento de código intentará cargar negrita
Typeface objeto a partir de una familia de fuentes que se define en recursos/fuentes:

var typeface = Typeface.Create("<FONT FAMILY NAME>", Android.Graphics.TypefaceStyle.Bold);


textView1.Typeface = typeface;

Descarga de fuentes
Empaquetar fuentes como un recurso de aplicación, en lugar de Android puede descargar fuentes desde un origen
remoto. Esto tendrá el efecto de reducir el tamaño del APK deseable.
Las fuentes se descargan con la Ayuda de un proveedor de fuente. Se trata de un proveedor de contenido
especializado que administra la descarga y el almacenamiento en caché de fuentes para todas las aplicaciones en el
dispositivo. Android 8.0 incluye un proveedor de fuente para descargar fuentes desde el fuente de Google
Repository. Este proveedor de fuente predeterminado es usado en el nivel de API 14 con v26 de la biblioteca de
compatibilidad de Android.
Cuando una aplicación realiza una solicitud para una fuente, el proveedor de fuente en primer lugar comprueba si
la fuente ya está en el dispositivo. Si no es así, a continuación, intentará descargar la fuente. Si la fuente no puede
ser descargado, Android, a continuación, usará la fuente predeterminada del sistema. Una vez que se ha
descargado la fuente, está disponible para todas las aplicaciones en el dispositivo, no solo a la aplicación que
realizó la solicitud inicial.
Cuando se realiza una solicitud para descargar una fuente, la aplicación no consultar directamente el proveedor de
fuente. En su lugar, las aplicaciones usarán una instancia de la FontsContract API (o la FontsContractCompat si se
usa el 26 de biblioteca de soporte técnico).
Android 8.0 admite descargar fuentes de dos maneras diferentes:
1. Declarar las fuentes que se pueden descargar como un recurso – una aplicación puede declarar las fuentes
descargables para Android a través de los archivos de recursos XML. Estos archivos contendrá todos los
metadatos que se debe descargar las fuentes de forma asincrónica cuando se inicia la aplicación y almacenarlos
en memoria caché en el dispositivo Android.
2. Mediante programación – API en el nivel de API de Android 26 permiten que una aplicación descargar las
fuentes mediante programación, mientras se está ejecutando la aplicación. Aplicaciones creará un FontRequest
de objetos para una fuente determinada y pasar este objeto a la FontsContract clase. El FontsContract toma el
FontRequest y recupera la fuente de un proveedor de fuente. Android sincrónicamente descargará la fuente. Un
ejemplo de cómo crear un FontRequest se mostrarán más adelante en esta guía.

Independientemente del enfoque que se usa, se pueden descargar los archivos de recursos que deben agregarse a
la aplicación de Xamarin.Android antes de fuentes. En primer lugar, se deben declarar las fuentes en un archivo
XML en el recursos/fuente directorio como parte de una familia de fuentes. Este fragmento de código es un
ejemplo de cómo descargar fuentes desde el colección de código abierto de fuentes de Google utilizando el
proveedor de fuente predeterminado que se incluye con Android 8.0 (o biblioteca de compatibilidad v26):

<?xml version="1.0" encoding="utf-8"?>


<font-family xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:fontProviderAuthority="com.google.android.gms.fonts"
android:fontProviderPackage="com.google.android.gms"
android:fontProviderQuery="VT323"
android:fontProviderCerts="@array/com_google_android_gms_fonts_certs"
app:fontProviderAuthority="com.google.android.gms.fonts"
app:fontProviderPackage="com.google.android.gms"
app:fontProviderQuery="VT323"
app:fontProviderCerts="@array/com_google_android_gms_fonts_certs"
>
</font-family>

El font-family elemento contiene los atributos siguientes, que se declara la información que requiere Android
para descargar las fuentes:
1. fontProviderAuthority – la autoridad del proveedor de fuente que se usará para la solicitud.
2. fontPackage – el paquete para el proveedor de fuente que se usará para la solicitud. Esto se usa para
comprobar la identidad del proveedor.
3. fontQuery – es una cadena que le ayudarán al proveedor de fuente para localizar la fuente solicitada. Obtener
más información sobre la consulta de fuente es específicos del proveedor de fuente. El QueryBuilder clase en el
fuentes descargables aplicación de ejemplo proporciona cierta información sobre el formato de consulta para
las fuentes de la colección de origen abierto de fuentes de Google.
4. fontProviderCerts – con la lista de conjuntos de valores hash de los certificados que el proveedor debe estar
firmado con una matriz de recursos.
Una vez que se definen las fuentes, puede ser necesario proporcionar información sobre la certificados fuente
implicada en la descarga.
Certificados de fuente
Si el proveedor de fuente no está preinstalado en el dispositivo, o si la aplicación usa el
Xamarin.Android.Support.Compat biblioteca, Android requiere que los certificados de seguridad del proveedor de
fuente. Estos certificados se mostrarán en un archivo de recursos de la matriz que se mantiene en
recursos/valores directory.
Por ejemplo, el siguiente código XML denominado Resources/values/fonts_cert.xml y almacena los certificados
para el proveedor de fuente de Google:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<array name="com_google_android_gms_fonts_certs">
<item>@array/com_google_android_gms_fonts_certs_dev</item>
<item>@array/com_google_android_gms_fonts_certs_prod</item>
</array>
<string-array name="com_google_android_gms_fonts_certs_dev">
<item>

MIIEqDCCA5CgAwIBAgIJANWFuGx90071MA0GCSqGSIb3DQEBBAUAMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1U
EBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAGCSqGSIb3DQ
EJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTAeFw0wODA0MTUyMzM2NTZaFw0zNTA5MDEyMzM2NTZaMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ
2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5k
cm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTCCASAwDQYJKoZIhvcNAQEBBQADggENADCCAQgCggEBANbOLggKv+IxTdG
Ns8/TGFy0PTP6DHThvbbR24kT9ixcOd9W+EaBPWW+wPPKQmsHxajtWjmQwWfna8mZuSeJS48LIgAZlKkpFeVyxW0qMBujb8X8ETrWy550NaFtI6
t9+u7hZeTfHwqNvacKhp1RbE6dBRGWynwMVX8XW8N1+UjFaq6GCJukT4qmpN2afb8sCjUigq0GuMwYXrFVee74bQgLHWGJwPmvmLHC69EH6kWr2
2ijx4OKXlSIx2xT1AsSHee70w5iDBiK4aph27yH3TxkXy9V89TDdexAcKk/cVHYNnDBapcavl7y0RiQ4biu8ymM8Ga/nmzhRKya6G0cGw8CAQOj
gfwwgfkwHQYDVR0OBBYEFI0cxb6VTEM8YYY6FbBMvAPyT+CyMIHJBgNVHSMEgcEwgb6AFI0cxb6VTEM8YYY6FbBMvAPyT+CyoYGapIGXMIGUMQs
wCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECx
MHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbYIJANWFuGx90071MAwGA1UdEwQFM
AMBAf8wDQYJKoZIhvcNAQEEBQADggEBABnTDPEF+3iSP0wNfdIjIz1AlnrPzgAIHVvXxunW7SBrDhEglQZBbKJEk5kT0mtKoOD1JMrSu1xuTKEB
ahWRbqHsXclaXjoBADb0kkjVEJu/Lh5hgYZnOjvlba8Ld7HCKePCVePoTJBdI4fvugnL8TsgK05aIskyY0hKI9L8KfqfGTl1lzOv2KoWD0KWwtA
WPoGChZxmQ+nBli+gwYMzM1vAkP+aayLe0a1EQimlOalO762r0GXO0ks+UeXde2Z4e+8S/pf7pITEI/tP+MxJTALw9QUWEv9lKTk+jkbqxbsh8n
fBUapfKqYn0eidpwq2AzVp3juYl7//fKnaPhJD9gs=
</item>
</string-array>
<string-array name="com_google_android_gms_fonts_certs_prod">
<item>

MIIEQzCCAyugAwIBAgIJAMLgh0ZkSjCNMA0GCSqGSIb3DQEBBAUAMHQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQ
HEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtHb29nbGUgSW5jLjEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDAeFw0wODA4Mj
EyMzEzMzRaFw0zNjAxMDcyMzEzMzRaMHQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3M
RQwEgYDVQQKEwtHb29nbGUgSW5jLjEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDCCASAwDQYJKoZIhvcNAQEBBQADggENADCC
AQgCggEBAKtWLgDYO6IIrgqWbxJOKdoR8qtW0I9Y4sypEwPpt1TTcvZApxsdyxMJZ2JORland2qSGT2y5b+3JKkedxiLDmpHpDsz2WCbdxgxRcz
fey5YZnTJ4VZbH0xqWVW/8lGmPav5xVwnIiJS6HXk+BVKZF+JcWjAsb/GEuq/eFdpuzSqeYTcfi6idkyugwfYwXFU1+5fZKUaRKYCwkkFQVfcAs
1fXA5V+++FGfvjJ/CxURaSxaBvGdGDhfXE28LWuT9ozCl5xw4Yq5OGazvV24mZVSoOO0yZ31j7kYvtwYK6NeADwbSxDdJEqO4k//0zOHKrUiGYX
tqw/A0LFFtqoZKFjnkCAQOjgdkwgdYwHQYDVR0OBBYEFMd9jMIhF1Ylmn/Tgt9r45jk14alMIGmBgNVHSMEgZ4wgZuAFMd9jMIhF1Ylmn/Tgt9r
45jk14aloXikdjB0MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEUMBIGA1UEChMLR29
vZ2xlIEluYy4xEDAOBgNVBAsTB0FuZHJvaWQxEDAOBgNVBAMTB0FuZHJvaWSCCQDC4IdGZEowjTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBA
UAA4IBAQBt0lLO74UwLDYKqs6Tm8/yzKkEu116FmH4rkaymUIE0P9KaMftGlMexFlaYjzmB2OxZyl6euNXEsQH8gjwyxCUKRJNexBiGcCEyj6z+
a1fuHHvkiaai+KL8W1EyNmgjmyy8AW7P+LLlkR+ho5zEHatRbM/YAnqGcFh5iZBqpknHf1SKMXFh4dd239FJ1jWYfbMDMy3NS5CTMQ2XFI1Mvcy
UTdZPErjQfTbQe3aDQsQcafEQPD+nqActifKZ0Np0IS9L9kR/wbNvyz6ENwPiTrjV2KRkEjH78ZMcUQXg0L3BYHJ3lc69Vs5Ddf9uUGGMYldX3W
fMBEmh/9iFBDAaTCK
</item>
</string-array>
</resources>

Con estos archivos de recursos en su lugar, la aplicación es capaz de descargar las fuentes.
Declarar que se puede descargar fuentes como recursos
Enumerando las fuentes que se pueden descargar en el AndroidManifest.XML, Android descargará las fuentes
de forma asincrónica cuando la aplicación se inicia por primera vez. La fuente de sí mismos se muestran en un
archivo de recursos de matriz, similar a ésta:

<?xml version="1.0" encoding="utf-8"?>


<resources>
<array name="downloadable_fonts" translatable="false">
<item>@font/vt323</item>
</array>
</resources>

Para descargar estas fuentes, tienen que ser declarados en AndroidManifest.XML agregando meta-data como
elemento secundario de la application elemento. Por ejemplo, si se declaran las fuentes que se pueden descargar
en un archivo de recursos en Resources/values/downloadable_fonts.xml, a continuación, este fragmento de
código tendría que se agregó al manifiesto:

<meta-data android:name="downloadable_fonts" android:resource="@array/downloadable_fonts" />

Descargar una fuente con las API de fuente


Es posible descargar mediante programación una fuente creando un FontRequest objeto y que se va a pasar el
FontContractCompat.RequestFont método. El FontContractCompat.RequestFont método compruebe primero si existe
la fuente en el dispositivo y, a continuación, si es necesario le asincrónicamente consulta el proveedor de fuente e
intente descargar la fuente de la aplicación. Si FontRequest es no se puede descargar la fuente, a continuación, va a
usar la fuente predeterminada del sistema Android.
Un FontRequest objeto contiene información que se usará el proveedor de fuente para buscar y descargar una
fuente. Un FontRequest requiere cuatro fragmentos de información:
1. Entidad de proveedor de fuente – la autoridad del proveedor de fuente que se usará para la solicitud.
2. Paquete de fuentes – el paquete para el proveedor de fuente que se usará para la solicitud. Esto se usa para
comprobar la identidad del proveedor.
3. Consulta de fuente – es una cadena que le ayudarán al proveedor de fuente para localizar la fuente solicitada.
Obtener más información sobre la consulta de fuente es específicos del proveedor de fuente. Los detalles de la
cadena son específicos del proveedor de fuente. El QueryBuilder clase en el fuentes descargables aplicación de
ejemplo proporciona cierta información sobre el formato de consulta para las fuentes de la colección de origen
abierto de fuentes de Google.
4. Certificados del proveedor de fuente – una matriz de recursos con la lista de conjuntos de códigos hash para
los certificados con el proveedor debería iniciar sesión.
Este fragmento de código es un ejemplo de instancias de un nuevo FontRequest objeto:

FontRequest request = new FontRequest("com.google.android.gms.fonts", "com.google.android.gms",


<FontToDownload>, Resource.Array.com_google_android_gms_fonts_certs);

En el fragmento anterior FontToDownload es una consulta que le ayudarán a la fuente de la colección de código
abierto de fuentes de Google.
Antes de pasar el FontRequest a la FontContractCompat.RequestFont método, hay dos objetos que se deben crear:
FontsContractCompat.FontRequestCallback – Se trata de una clase abstracta que se debe extender. Es una
devolución de llamada que se invoca cuando RequestFont haya finalizado. Una aplicación de Xamarin.Android
debe subclase FontsContractCompat.FontRequestCallback e invalidar la OnTypefaceRequestFailed y
OnTypefaceRetrieved , que proporciona las acciones que se realizarán cuando la descarga se produce un error o
se realiza correctamente, respectivamente.
Handler – Se trata de un Handler que se usará en RequestFont para descargar la fuente en un subproceso, si
es necesario. Las fuentes deben no descargarse en el subproceso de interfaz de usuario.
Este fragmento de código es un ejemplo de un C# clase asincrónicamente, se descargará una fuente de colección
de código abierto de fuentes de Google. Implementa el FontRequestCallback interfaz y genera un C# eventos
cuando FontRequest ha finalizado.
public class FontDownloadHelper : FontsContractCompat.FontRequestCallback
{
// A very simple font query; replace as necessary
public static readonly String FontToDownload = "Courgette";

Android.OS.Handler Handler = null;

public event EventHandler<FontDownloadEventArg> FontDownloaded = delegate


{
// just an empty delegate to avoid null reference exceptions.
};

public void DownloadFonts(Context context)


{
FontRequest request = new FontRequest("com.google.android.gms.fonts",
"com.google.android.gms",FontToDownload , Resource.Array.com_google_android_gms_fonts_certs);
FontsContractCompat.RequestFont(context, request, this, GetHandlerThreadHandler());
}

public override void OnTypefaceRequestFailed(int reason)


{
base.OnTypefaceRequestFailed(reason);
FontDownloaded(this, new FontDownloadEventArg(null));
}

public override void OnTypefaceRetrieved(Android.Graphics.Typeface typeface)


{
base.OnTypefaceRetrieved(typeface);
FontDownloaded(this, new FontDownloadEventArg(typeface));
}

Handler GetHandlerThreadHandler()
{
if (Handler == null)
{
HandlerThread handlerThread = new HandlerThread("fonts");
handlerThread.Start();
Handler = new Handler(handlerThread.Looper);
}
return Handler;
}
}

public class FontDownloadEventArg : EventArgs


{
public FontDownloadEventArg(Android.Graphics.Typeface typeface)
{
Typeface = typeface;
}
public Android.Graphics.Typeface Typeface { get; private set; }
public bool RequestFailed
{
get
{
return Typeface != null;
}
}
}

Para usar esta aplicación auxiliar, un nuevo FontDownloadHelper se crea, y se le asigna un controlador de eventos:
var fontHelper = new FontDownloadHelper();

fontHelper.FontDownloaded += (object sender, FontDownloadEventArg e) =>


{
//React to the request
};
fontHelper.DownloadFonts(this); // this is an Android Context instance.

Resumen
Esta guía describe las nuevas API de Android 8.0 para admitir las fuentes descargables y las fuentes como
recursos. También se han descrito cómo incrustar fuentes existentes en un APK y se usan en un diseño. También
describe cómo Android 8.0 admite descargar fuentes de un proveedor de fuente, mediante programación o
mediante la declaración de los metadatos fuente en los archivos de recursos.

Vínculos relacionados
fontFamily
FontConfig
FontRequest
FontsContractCompat
Resources.GetFont
Tipo de letra
Compatibilidad con Android biblioteca 26 NuGet
Uso de fuentes en Android
Especificación de peso de fuente CSS
Colección de código abierto de fuentes de Google
Código fuente Sans Pro
Ciclo de vida de la actividad
19/08/2019 • 35 minutes to read • Edit Online

Las actividades son un bloque de creación fundamental de las aplicaciones de Android y pueden existir en
varios Estados diferentes. El ciclo de vida de la actividad comienza con la creación de instancias y termina con la
destrucción, e incluye muchos Estados entre ellos. Cuando una actividad cambia de estado, se llama al método
de evento del ciclo de vida adecuado, que notifica a la actividad el cambio de estado inminente y le permite
ejecutar el código para adaptarse a ese cambio. En este artículo se examina el ciclo de vida de las actividades y
se explica la responsabilidad que tiene una actividad durante cada uno de estos cambios de estado para que
formen parte de una aplicación con un comportamiento correcto y confiable.

Información general del ciclo de vida de actividad


Las actividades son un concepto de programación inusual específico de Android. En el desarrollo de
aplicaciones tradicional, normalmente hay un método Main estático, que se ejecuta para iniciar la aplicación.
Con Android, sin embargo, las cosas son diferentes; Las aplicaciones de Android se pueden iniciar a través de
cualquier actividad registrada en una aplicación. En la práctica, la mayoría de las aplicaciones solo tendrán una
actividad específica que se especifica como el punto de entrada de la aplicación. Sin embargo, si una aplicación
se bloquea, o el sistema operativo finaliza, puede intentar reiniciar la aplicación en la última actividad abierta o
en cualquier otra parte de la pila de actividades anterior. Además, el sistema operativo puede pausar actividades
cuando no están activas y reclamarlas si tiene poca memoria. Se debe tener cuidado a la hora de permitir que la
aplicación restaure correctamente su estado en caso de que se reinicie una actividad, especialmente si esa
actividad depende de datos de actividades anteriores.
El ciclo de vida de la actividad se implementa como una colección de métodos que el sistema operativo llama a
lo largo del ciclo de vida de una actividad. Estos métodos permiten a los desarrolladores implementar la
funcionalidad necesaria para satisfacer los requisitos de administración de estado y recursos de sus aplicaciones.
Es extremadamente importante que el desarrollador de la aplicación analice los requisitos de cada actividad
para determinar qué métodos expuestos por el ciclo de vida de la actividad deben implementarse. Si no lo hace,
se puede producir inestabilidad en la aplicación, bloqueos, saturación de recursos y, posiblemente, la
inestabilidad subyacente del sistema operativo.
En este capítulo se examina el ciclo de vida de la actividad en detalle, incluidos:
Estados de actividad
Métodos de ciclo de vida
Conservar el estado de una aplicación
En esta sección también se incluye un tutorial que proporciona ejemplos prácticos sobre cómo guardar el estado
de forma eficaz durante el ciclo de vida de la actividad. Al final de este capítulo, debe comprender el ciclo de vida
de la actividad y cómo admitirlo en una aplicación Android.

Ciclo de vida de la actividad


El ciclo de vida de la actividad de Android comprende una colección de métodos que se exponen en la clase de
actividad que proporcionan al desarrollador un marco de administración de recursos. Este marco de trabajo
permite a los desarrolladores cumplir los requisitos de administración de estado únicos de cada actividad dentro
de una aplicación y administrar correctamente la administración de recursos.
Estados de actividad
El sistema operativo Android arbitra las actividades en función de su estado. Esto ayuda a Android a identificar
las actividades que ya no se usan, lo que permite al sistema operativo reclamar la memoria y los recursos. En el
diagrama siguiente se muestran los Estados en los que puede pasar una actividad durante su vigencia:

Estos Estados se pueden dividir en cuatro grupos principales como se indica a continuación:
1. Activo o en ejecución – Las actividades se consideran activas o en ejecución si están en primer plano,
también conocidas como la parte superior de la pila de actividades. Esto se considera la actividad de
prioridad más alta en Android y, como tal, solo la eliminará el sistema operativo en situaciones extremas,
por ejemplo, si la actividad intenta usar más memoria que la disponible en el dispositivo, ya que esto
podría hacer que la interfaz de usuario dejara de responder.
2. En pausa – Cuando el dispositivo entra en suspensión, o una actividad todavía está visible pero está
parcialmente oculta por una actividad nueva, que no es de tamaño completo o transparente, se considera
que la actividad está en pausa. Las actividades en pausa están todavía activas, es decir, mantienen toda la
información sobre el estado y los miembros y permanecen adjuntas al administrador de ventanas. Se
considera que es la segunda actividad de mayor prioridad en Android y, como tal, solo la eliminará el
sistema operativo Si el sacrificio de esta actividad satisfará los requisitos de recursos necesarios para
mantener la actividad activa/en ejecución estable y con capacidad de respuesta.
3. Detenido o en segundo plano – Las actividades ocultas completamente por otra actividad se consideran
detenidas o en segundo plano. Las actividades detenidas siguen intentando conservar su estado y la
información de los miembros siempre que sea posible, pero las actividades detenidas se consideran la
prioridad más baja de los tres Estados y, como tal, el sistema operativo eliminará primero las actividades
en este estado para satisfacer el recurso. requisitos de actividades con mayor prioridad.
4. Reiniciado – Es posible que Android Quite de la memoria una actividad que esté en cualquier lugar en
pausa en el ciclo de vida. Si el usuario vuelve a la actividad, se debe reiniciar, restaurar a su estado
guardado previamente y, a continuación, mostrar al usuario.
Volver a crear la actividad en respuesta a los cambios de configuración
Para que las cuestiones sean más complicadas, Android lanza una llave más en la combinación llamada cambios
de configuración. Los cambios de configuración son ciclos de destrucción y recreación de la actividad rápida que
se producen cuando cambia la configuración de una actividad, por ejemplo, cuando se gira el dispositivo (y la
actividad debe volver a generarse en modo horizontal o vertical), cuando el se muestra el teclado (y la actividad
se presenta con una oportunidad de cambiar el tamaño) o cuando el dispositivo se coloca en un Dock, entre
otros.
Los cambios de configuración siguen provocando los mismos cambios de estado de actividad que se
producirían durante la detención y el reinicio de una actividad. Sin embargo, para asegurarse de que una
aplicación se comporta correctamente y funciona bien durante los cambios de configuración, es importante que
se controlen lo más rápido posible. Por este motivo, Android tiene una API específica que se puede usar para
conservar el estado durante los cambios de configuración. Esto se tratará más adelante en el Estado de
administración a lo largo del ciclo de vida .
Métodos de ciclo de vida de actividad
Los Android SDK y, por extensión, el marco de Xamarin. Android proporcionan un modelo eficaz para
administrar el estado de las actividades dentro de una aplicación. Cuando el estado de una actividad cambia, el
sistema operativo notifica la actividad, que llama a métodos específicos en esa actividad. En el diagrama
siguiente se muestran estos métodos en relación con el ciclo de vida de la actividad:

Como desarrollador, puede controlar los cambios de estado invalidando estos métodos dentro de una actividad.
Sin embargo, es importante tener en cuenta que todos los métodos del ciclo de vida se llaman en el subproceso
de la interfaz de usuario y impedirán que el sistema operativo realice la siguiente parte del trabajo de la interfaz
de usuario, como ocultar la actividad actual, mostrar una nueva actividad, etc. Como tal, el código de estos
métodos debe ser lo más breve posible para que una aplicación funcione correctamente. Las tareas de ejecución
prolongada deben ejecutarse en un subproceso en segundo plano.
Vamos a examinar cada uno de estos métodos de ciclo de vida y su uso:
OnCreate
Alcrear es el primer método al que se llama cuando se crea una actividad. OnCreate siempre se invalida para
realizar cualquier inicialización de inicio que puede ser necesaria para una actividad como la siguiente:
Crear vistas
Inicializar variables
Enlazar datos estáticos a listas
OnCreate toma un parámetro de agrupación, que es un diccionario para almacenar y pasar información de
estado y objetos entre actividades si la agrupación no es null, lo que indica que la actividad se está reiniciando y
debe restaurar su estado desde la instancia anterior. En el código siguiente se muestra cómo recuperar valores
de la agrupación:

protected override void OnCreate(Bundle bundle)


{
base.OnCreate(bundle);

string intentString;
bool intentBool;

if (bundle != null)
{
intentString = bundle.GetString("myString");
intentBool = bundle.GetBoolean("myBool");
}

// Set our view from the "main" layout resource


SetContentView(Resource.Layout.Main);
}

Una OnCreate vez finalizado, Android llamará a OnStart .


OnStart
El sistema siempre llama a OnStart una vez OnCreate finalizada. Las actividades pueden invalidar este método
si necesitan realizar cualquier tarea específica justo antes de que una actividad sea visible, como actualizar los
valores actuales de las vistas dentro de la actividad. Android llamará OnResume inmediatamente después de este
método.
Alnude
El sistema llama a OnResume cuando la actividad está lista para empezar a interactuar con el usuario. Las
actividades deben invalidar este método para realizar tareas como las siguientes:
Rampa de velocidades de fotogramas (una tarea común en el desarrollo de juegos)
Animaciones iniciales
Escuchando actualizaciones de GPS
Mostrar cualquier alerta o cuadro de diálogo relevante
Conectar controladores de eventos externos
Por ejemplo, en el siguiente fragmento de código se muestra cómo inicializar la cámara:

public void OnResume()


{
base.OnResume(); // Always call the superclass first.

if (_camera==null)
{
// Do camera initializations here
}
}

OnResume es importante porque las operaciones que se realizan en OnPause deben deshacerse en OnResume , ya
que es el único método de ciclo de vida que se garantiza que se ejecute OnPause después de que la actividad
vuelva a la vida.
Alpausar
Se llama a OnPause cuando el sistema está a punto de colocar la actividad en segundo plano o cuando la
actividad se oculta parcialmente. Las actividades deben invalidar este método si necesitan:
Confirmar los cambios no guardados en los datos persistentes
Destruir o limpiar otros objetos que consumen recursos
Aumentar las velocidades de fotogramas y pausar animaciones
Anular el registro de controladores de eventos externos o controladores de notificación (es decir, los que
están vinculados a un servicio). Esto se debe hacer para evitar pérdidas de memoria de la actividad.
Del mismo modo, si la actividad ha mostrado cuadros de diálogo o alertas, deben limpiarse con el
.Dismiss() método.

Como ejemplo, el siguiente fragmento de código liberará la cámara, ya que la actividad no puede hacer uso de
ella mientras está en pausa:

public void OnPause()


{
base.OnPause(); // Always call the superclass first

// Release the camera as other activities might need it


if (_camera != null)
{
_camera.Release();
_camera = null;
}
}

Hay dos métodos de ciclo de vida posibles a los que OnPause se llamará después de:
1. OnResume se llamará a si la actividad se va a devolver al primer plano.
2. OnStop se llamará a si la actividad se coloca en segundo plano.

OnStop
Se llama a OnStop cuando la actividad ya no es visible para el usuario. Esto sucede cuando se produce uno de
los siguientes casos:
Se está iniciando una nueva actividad y está cubriendo esta actividad.
Una actividad existente se pone en primer plano.
Se está destruyendo la actividad.
OnStop no siempre se puede llamar en situaciones de memoria insuficiente, como cuando Android se queda sin
recursos y no puede almacenar en segundo plano la actividad. Por esta razón, es mejor no depender de OnStop
la llamada a cuando se prepara una actividad para la destrucción. Los siguientes métodos de ciclo de vida a los
que se puede llamar OnDestroy después de este se producirán si la OnRestart actividad deja de estar
disponible, o si la actividad se va a devolver para interactuar con el usuario.
Destruir
Aldestroy es el método final al que se llama en una instancia de actividad antes de que se destruya y se quite por
completo de la memoria. En situaciones extremas, Android puede terminar el proceso de aplicación que
hospeda la actividad, lo que OnDestroy provocará que no se invoque. La mayoría de las actividades no
implementarán este método, ya que la mayoría de las operaciones de OnPause limpieza OnStop y cierre se han
realizado en los métodos y. Normalmente OnDestroy , el método se invalida para limpiar los recursos de larga
ejecución que podrían perder recursos. Un ejemplo de esto podría ser subprocesos en segundo plano OnCreate
que se iniciaron en.
No habrá ningún método de ciclo de vida llamado después de que se haya destruido la actividad.
Reiniciar
OnRestart se llama después de que se haya detenido la actividad antes de que se vuelva a iniciar. Un buen
ejemplo sería cuando el usuario presiona el botón Inicio mientras está en una actividad de la aplicación. Cuando
esto ocurre OnPause OnStop y se llama a los métodos, y la actividad se mueve al fondo, pero no se destruye. Si
después el usuario restaurara la aplicación mediante el administrador de tareas o una aplicación similar, Android
llamará al OnRestart método de la actividad.
No hay ninguna directriz general para el tipo de lógica que se debe implementar OnRestart en. Esto se debe
OnStart a que siempre se invoca con independencia de si la actividad se crea o se reinicia, por lo que todos los
recursos necesarios para la actividad se deben inicializar en OnStart , OnRestart en lugar de.
El siguiente método de ciclo de OnRestart vida llamado OnStart después de será.
Atrás frente a Página principal
Muchos dispositivos Android tienen dos botones distintos: un botón "atrás" y un botón "Inicio". Un ejemplo de
esto puede verse en la siguiente captura de pantalla de Android 4.0.3:

Hay una diferencia sutil entre los dos botones, aunque parezca que tienen el mismo efecto de colocar una
aplicación en segundo plano. Cuando un usuario hace clic en el botón atrás, indica a Android que se ha hecho
con la actividad. Android destruirá la actividad. Por el contrario, cuando el usuario hace clic en el botón Inicio, la
actividad se coloca simplemente – en el Android en segundo plano no eliminará la actividad.

Administración del estado a lo largo del ciclo de vida


Cuando una actividad se detiene o se destruye, el sistema ofrece la oportunidad de guardar el estado de la
actividad para su posterior rehidratación. Este estado guardado se conoce como estado de instancia. Android
proporciona tres opciones para almacenar el estado de la instancia durante el ciclo de vida de la actividad:
1. Almacenar valores primitivos en Dictionary un conocido como agrupación que Android usará para
guardar el estado.
2. Crear una clase personalizada que contenga valores complejos como mapas de bits. Android usará esta
clase personalizada para guardar el estado.
3. Elusión del ciclo de vida de los cambios de configuración y suponiendo la responsabilidad completa de
mantener el estado en la actividad.
En esta guía se describen las dos primeras opciones.
Estado del paquete
La opción principal para guardar el estado de la instancia es usar un objeto de diccionario de clave o valor
conocido como agrupación. Recuerde que cuando se crea una actividad que el OnCreate método pasa una
agrupación como parámetro, este paquete se puede usar para restaurar el estado de la instancia. No se
recomienda usar un paquete para datos más complejos que no se serialicen rápida o fácilmente en pares de
clave y valor (como mapas de bits). en su lugar, debe usarse para valores simples como cadenas.
Una actividad proporciona métodos para ayudarle a guardar y recuperar el estado de la instancia en la
agrupación:
OnSaveInstanceState – Lo invoca Android cuando se destruye la actividad. Las actividades pueden
implementar este método si necesitan conservar cualquier elemento de estado de clave/valor.
OnRestoreInstanceState Se llama a esta función OnCreate una vez finalizado el método y proporciona
otra oportunidad para que una actividad restaure su estado una vez completada la inicialización. –
En el diagrama siguiente se muestra cómo se usan estos métodos:

OnSaveInstanceState
Se llamará a OnSaveInstanceState cuando se detenga la actividad. Recibirá un parámetro de agrupación en el
que la actividad puede almacenar su estado. Cuando un dispositivo experimenta un cambio de configuración,
una actividad puede usar Bundle el objeto que se pasa para conservar el estado de actividad invalidando.
OnSaveInstanceState Por ejemplo, considere el siguiente código:

int c;

protected override void OnCreate (Bundle bundle)


{
base.OnCreate (bundle);

this.SetContentView (Resource.Layout.SimpleStateView);

var output = this.FindViewById<TextView> (Resource.Id.outputText);

if (bundle != null) {
c = bundle.GetInt ("counter", -1);
} else {
c = -1;
}

output.Text = c.ToString ();

var incrementCounter = this.FindViewById<Button> (Resource.Id.incrementCounter);

incrementCounter.Click += (s,e) => {


output.Text = (++c).ToString();
};
}

El código anterior incrementa c un entero denominado cuando se hace clic en un botón denominado
incrementCounter y muestra el resultado en un TextView denominado output . Cuando se produce un cambio
de configuración, por ejemplo, cuando se gira el dispositivo, el código anterior perdería el valor de c bundle
porque sería null , tal y como se muestra en la ilustración siguiente:
Para conservar el valor de c en este ejemplo, la actividad puede invalidarse OnSaveInstanceState , guardando el
valor en la agrupación como se muestra a continuación:

protected override void OnSaveInstanceState (Bundle outState)


{
outState.PutInt ("counter", c);
base.OnSaveInstanceState (outState);
}

Ahora, cuando el dispositivo se gira a una nueva orientación, el entero se guarda en la agrupación y se recupera
con la línea:

c = bundle.GetInt ("counter", -1);

NOTE
Es importante llamar siempre a la implementación base de OnSaveInstanceState para que también se pueda guardar el
estado de la jerarquía de vistas.

Est a d o d e v i st a

Reemplazar OnSaveInstanceState es un mecanismo adecuado para guardar datos transitorios en una actividad a
través de cambios de orientación, como el contador en el ejemplo anterior. Sin embargo, la implementación
predeterminada OnSaveInstanceState de se encargará de guardar los datos transitorios en la interfaz de usuario
para cada vista, siempre y cuando cada vista tenga un identificador asignado. Por ejemplo, suponga que una
aplicación tiene EditText un elemento definido en XML como se indica a continuación:

<EditText android:id="@+id/myText"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>

Puesto que EditText el control tiene id un asignado, cuando el usuario escribe algunos datos y gira el
dispositivo, los datos se siguen mostrando, como se muestra a continuación:

OnRestoreInstanceState
Se llamará a OnRestoreInstanceState después de OnStart . Proporciona una actividad con la oportunidad de
restaurar cualquier Estado que se guardó anteriormente en un paquete durante el anterior OnSaveInstanceState .
Sin embargo OnCreate , es el mismo paquete que se proporciona.
En el código siguiente se muestra cómo se puede restaurar OnRestoreInstanceState el estado en:

protected override void OnRestoreInstanceState(Bundle savedState)


{
base.OnRestoreSaveInstanceState(savedState);
var myString = savedState.GetString("myString");
var myBool = savedState.GetBoolean("myBool");
}

Este método existe para proporcionar cierta flexibilidad a la hora de restaurar el estado. A veces es más
adecuado esperar hasta que se realicen todas las inicializaciones antes de restaurar el estado de la instancia.
Además, una subclase de una actividad existente solo puede querer restaurar determinados valores del estado
de la instancia. En muchos casos, no es necesario invalidar OnRestoreInstanceState , ya que la mayoría de las
actividades pueden restaurar el estado mediante el paquete proporcionado a. OnCreate
Para obtener un ejemplo de cómo guardar el Bundle estado con, consulte el Tutorial: guardar el estado de la
actividad.
Limitaciones de agrupación
Aunque OnSaveInstanceState facilita el almacenamiento de datos transitorios, tiene algunas limitaciones:
No se llama en todos los casos. Por ejemplo, si presiona Inicio o atrás para salir de una actividad,
OnSaveInstanceState no se llamará.

La agrupación que OnSaveInstanceState se pasa a no está diseñada para objetos grandes, como
imágenes. En el caso de objetos grandes, es preferible guardar el objeto de
OnRetainNonConfigurationInstance , como se describe a continuación.
Los datos guardados mediante el lote se serializan, lo que puede provocar retrasos.
El estado de agrupación es útil para datos simples que no usan mucha memoria, mientras que los datos de
instancia que no son de configuración son útiles para datos más complejos, o datos que son caros de recuperar,
como por ejemplo una llamada de servicio web o una consulta de base de datos complicada. Los datos de
instancia que no son de configuración se guardan en un objeto según sea necesario. En la siguiente sección
OnRetainNonConfigurationInstance se explica cómo conservar tipos de datos más complejos a través de los
cambios de configuración.
Persistencia de datos complejos
Además de conservar los datos en el paquete, Android también admite el almacenamiento de datos invalidando
OnRetainNonConfigurationInstance y devolviendo una instancia Java.Lang.Object de que contiene los datos
que se van a conservar. Usar OnRetainNonConfigurationInstance para guardar el estado tiene dos ventajas
principales:
El objeto devuelto OnRetainNonConfigurationInstance de funciona bien con tipos de datos más grandes y
más complejos porque la memoria conserva este objeto.
Se OnRetainNonConfigurationInstance llama al método a petición y solo cuando es necesario. Esto es más
económico que usar una memoria caché manual.
El OnRetainNonConfigurationInstance uso de es adecuado para escenarios en los que resulta caro recuperar los
datos varias veces, como las llamadas a servicios Web. Por ejemplo, considere el siguiente código que busca
Twitter:
public class NonConfigInstanceActivity : ListActivity
{
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
SearchTwitter ("xamarin");
}

public void SearchTwitter (string text)


{
string searchUrl = String.Format("http://search.twitter.com/search.json?" + "q=
{0}&rpp=10&include_entities=false&" + "result_type=mixed", text);

var httpReq = (HttpWebRequest)HttpWebRequest.Create (new Uri (searchUrl));


httpReq.BeginGetResponse (new AsyncCallback (ResponseCallback), httpReq);
}

void ResponseCallback (IAsyncResult ar)


{
var httpReq = (HttpWebRequest)ar.AsyncState;

using (var httpRes = (HttpWebResponse)httpReq.EndGetResponse (ar)) {


ParseResults (httpRes);
}
}

void ParseResults (HttpWebResponse httpRes)


{
var s = httpRes.GetResponseStream ();
var j = (JsonObject)JsonObject.Load (s);

var results = (from result in (JsonArray)j ["results"] let jResult = result as JsonObject select jResult
["text"].ToString ()).ToArray ();

RunOnUiThread (() => {


PopulateTweetList (results);
});
}

void PopulateTweetList (string[] results)


{
ListAdapter = new ArrayAdapter<string> (this, Resource.Layout.ItemView, results);
}
}

Este código recupera los resultados del Web con formato JSON, los analiza y, a continuación, presenta los
resultados en una lista, como se muestra en la siguiente captura de pantalla:
Cuando se produce un cambio de configuración, por ejemplo, cuando se gira un dispositivo, el código repite el
proceso. Para reutilizar los resultados recuperados originalmente y no ocasionar llamadas de red redundantes e
innecesarias, podemos usar OnRetainNonconfigurationInstance para guardar los resultados, como se muestra a
continuación:
public class NonConfigInstanceActivity : ListActivity
{
TweetListWrapper _savedInstance;

protected override void OnCreate (Bundle bundle)


{
base.OnCreate (bundle);

var tweetsWrapper = LastNonConfigurationInstance as TweetListWrapper;

if (tweetsWrapper != null) {
PopulateTweetList (tweetsWrapper.Tweets);
} else {
SearchTwitter ("xamarin");
}

public override Java.Lang.Object OnRetainNonConfigurationInstance ()


{
base.OnRetainNonConfigurationInstance ();
return _savedInstance;
}

...

void PopulateTweetList (string[] results)


{
ListAdapter = new ArrayAdapter<string> (this, Resource.Layout.ItemView, results);
_savedInstance = new TweetListWrapper{Tweets=results};
}
}

Ahora, cuando se gira el dispositivo, los resultados originales se recuperan de LastNonConfiguartionInstance la


propiedad. En este ejemplo, los resultados se componen de un string[] que contiene tweets. Puesto
OnRetainNonConfigurationInstance que requiere Java.Lang.Object que se devuelva, string[] se
Java.Lang.Object ajusta en una clase que subclases, como se muestra a continuación:

class TweetListWrapper : Java.Lang.Object


{
public string[] Tweets { get; set; }
}

Por ejemplo, si se intenta usar TextView como el objeto devuelto de OnRetainNonConfigurationInstance , se


perderá la actividad, como se muestra en el código siguiente:
TextView _textView;

protected override void OnCreate (Bundle bundle)


{
base.OnCreate (bundle);

var tv = LastNonConfigurationInstance as TextViewWrapper;

if(tv != null) {
_textView = tv;
var parent = _textView.Parent as FrameLayout;
parent.RemoveView(_textView);
} else {
_textView = new TextView (this);
_textView.Text = "This will leak.";
}

SetContentView (_textView);
}

public override Java.Lang.Object OnRetainNonConfigurationInstance ()


{
base.OnRetainNonConfigurationInstance ();
return _textView;
}

En esta sección, hemos aprendido a conservar los Bundle datos de estado sencillos con y a guardar tipos de
datos más complejos con. OnRetainNonConfigurationInstance

Resumen
El ciclo de vida de la actividad de Android proporciona un marco eficaz para la administración de Estados de
actividades dentro de una aplicación, pero puede ser difícil de entender e implementar. En este capítulo se
presentaron los distintos Estados en los que puede pasar una actividad durante su duración, así como los
métodos de ciclo de vida asociados a esos Estados. A continuación, se proporciona una guía sobre el tipo de
lógica que debe realizarse en cada uno de estos métodos.

Vínculos relacionados
Control de giro
Actividad de Android
Tutorial: guardado del estado de actividad
31/07/2019 • 7 minutes to read • Edit Online

Hemos tratado la teoría detrás de guardar el estado en la guía del ciclo de vida de la actividad. Ahora, vamos a
examinar un ejemplo.

Tutorial de estado de actividad


Vamos a abrir el proyecto ActivityLifecycle_Start (en el ejemplo ActivityLifecycle ), compilarlo y ejecutarlo. Se
trata de un proyecto muy sencillo que tiene dos actividades para demostrar el ciclo de vida de la actividad y cómo
se llama a los distintos métodos del ciclo de vida. Al iniciar la aplicación, se muestra la pantalla MainActivity de:

Ver transiciones de estado


Cada método de este ejemplo escribe en la ventana de salida de la aplicación IDE para indicar el estado de la
actividad. (Para abrir la ventana de salida en Visual Studio, presione CTRL -ALT-O; para abrir la ventana de salida
en Visual Studio para Mac, haga clic en ver > paneles > salidade la aplicación).
Cuando la aplicación se inicia por primera vez, la ventana de salida muestra los cambios de estado de la actividad
A:

[ActivityLifecycle.MainActivity] Activity A - OnCreate


[ActivityLifecycle.MainActivity] Activity A - OnStart
[ActivityLifecycle.MainActivity] Activity A - OnResume

Cuando hacemos clic en el botón iniciar actividad b , vemos actividad en pausa y detener mientras la actividad
B pasa por sus cambios de estado:
[ActivityLifecycle.MainActivity] Activity A - OnPause
[ActivityLifecycle.SecondActivity] Activity B - OnCreate
[ActivityLifecycle.SecondActivity] Activity B - OnStart
[ActivityLifecycle.SecondActivity] Activity B - OnResume
[ActivityLifecycle.MainActivity] Activity A - OnStop

Como resultado, la actividad B se inicia y se muestra en lugar de la actividad a:

Cuando hacemos clic en el botón atrás , la actividad B se destruye y se reanuda la actividad A :

[ActivityLifecycle.SecondActivity] Activity B - OnPause


[ActivityLifecycle.MainActivity] Activity A - OnRestart
[ActivityLifecycle.MainActivity] Activity A - OnStart
[ActivityLifecycle.MainActivity] Activity A - OnResume
[ActivityLifecycle.SecondActivity] Activity B - OnStop
[ActivityLifecycle.SecondActivity] Activity B - OnDestroy

Agregar un contador de clics


A continuación, vamos a cambiar la aplicación para que tengamos un botón que cuente y muestre el número de
veces que se hace clic en él. En primer lugar, vamos a _counter agregar una variable MainActivity de instancia a:

int _counter = 0;

A continuación, vamos a editar el archivo de diseño Resource/layout/main. axml y agregar clickButton un


nuevo que muestre el número de veces que el usuario hizo clic en el botón. El Main. axml resultante debe ser
similar al siguiente:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Button
android:id="@+id/myButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/mybutton_text" />
<Button
android:id="@+id/clickButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/counterbutton_text" />
</LinearLayout>

Vamos a agregar el código siguiente al final del método de creación en MainActivity – clickButton este código
que controla los eventos de clic de:

var clickbutton = FindViewById<Button> (Resource.Id.clickButton);


clickbutton.Text = Resources.GetString (
Resource.String.counterbutton_text, _counter);
clickbutton.Click += (object sender, System.EventArgs e) =>
{
_counter++;
clickbutton.Text = Resources.GetString (
Resource.String.counterbutton_text, _counter);
} ;

Al compilar y ejecutar la aplicación de nuevo, aparece un botón nuevo que se incrementa y muestra el _counter
valor de en cada clic:

Pero cuando giramos el dispositivo al modo horizontal, se pierde este recuento:


Al examinar la salida de la aplicación, vemos que la actividad A se pausó, se detuvo, se destruye, se vuelve a crear,
se reinicia y luego se reanuda durante la rotación del modo vertical a horizontal:

[ActivityLifecycle.MainActivity] Activity A - OnPause


[ActivityLifecycle.MainActivity] Activity A - OnStop
[ActivityLifecycle.MainActivity] Activity A - On Destroy

[ActivityLifecycle.MainActivity] Activity A - OnCreate


[ActivityLifecycle.MainActivity] Activity A - OnStart
[ActivityLifecycle.MainActivity] Activity A - OnResume

Dado que la actividad A se destruye y vuelve a crear cuando se gira el dispositivo, se pierde el estado de la
instancia. A continuación, agregaremos código para guardar y restaurar el estado de la instancia.
Agregar código para conservar el estado de la instancia
Vamos a agregar un método a MainActivity para guardar el estado de la instancia. Antes de que se destruya la
actividad A , Android llama automáticamente a OnSaveInstanceState y pasa una agrupación que se puede usar
para almacenar el estado de la instancia. Vamos a usarlo para guardar nuestro recuento de clics como un valor
entero:

protected override void OnSaveInstanceState (Bundle outState)


{
outState.PutInt ("click_count", _counter);
Log.Debug(GetType().FullName, "Activity A - Saving instance state");

// always call the base implementation!


base.OnSaveInstanceState (outState);
}

Cuando se vuelve a crear y reanudar la actividad a , Android lo Bundle pasa a nuestro OnCreate método. Vamos
a agregar código a OnCreate para restaurar el _counter valor Bundle desde el pasado. Agregue el código
siguiente justo antes de la línea clickbutton donde se define:
if (bundle != null)
{
_counter = bundle.GetInt ("click_count", 0);
Log.Debug(GetType().FullName, "Activity A - Recovered instance state");
}

Vuelva a compilar y ejecutar la aplicación y, a continuación, haga clic en el segundo botón varias veces. Cuando
giramos el dispositivo al modo horizontal, se conserva el recuento.

Echemos un vistazo a la ventana de salida para ver lo que ha sucedido:

[ActivityLifecycle.MainActivity] Activity A - OnPause


[ActivityLifecycle.MainActivity] Activity A - Saving instance state
[ActivityLifecycle.MainActivity] Activity A - OnStop
[ActivityLifecycle.MainActivity] Activity A - On Destroy

[ActivityLifecycle.MainActivity] Activity A - OnCreate


[ActivityLifecycle.MainActivity] Activity A - Recovered instance state
[ActivityLifecycle.MainActivity] Activity A - OnStart
[ActivityLifecycle.MainActivity] Activity A - OnResume

Antes de llamar al método OnStop , se llamó a OnSaveInstanceState nuestro nuevo método para guardar Bundle
el _counter valor en. Android lo pasó Bundle de nuevo a nosotros cuando llamó a OnCreate nuestro método, y
pudimos usarlo para restaurar el _counter valor al lugar donde se quedó.

Resumen
En este tutorial, hemos usado nuestro conocimiento del ciclo de vida de la actividad para conservar los datos de
estado.

Vínculos relacionados
ActivityLifecycle (ejemplo)
Ciclo de vida de la actividad
Actividad de Android
Creación de servicios de Android
11/07/2019 • 19 minutes to read • Edit Online

Esta guía trata los servicios de Xamarin.Android, que son componentes de Android que permiten que el trabajo
se realiza sin una interfaz de usuario activas. Los servicios se usan con mucha frecuencia para las tareas que se
realizan en segundo plano, como los cálculos mucho tiempo, descarga de archivos, reproducir música y así
sucesivamente. Explica los diferentes escenarios más adecuados para servicios y se muestra cómo implementarlos
tanto para realizar tareas en segundo plano de larga ejecución, así como para proporcionar una interfaz para
las llamadas a procedimiento remoto.

Introducción a los servicios de Android


Aplicaciones móviles no son como las aplicaciones de escritorio. Equipos de escritorio tienen ingentes cantidades
de recursos, como una fuente de alimentación conectado, espacio de almacenamiento, memoria y espacio en
pantalla, dispositivos móviles no lo hace. Estas restricciones forzar las aplicaciones móviles para comportarse de
manera diferente. Por ejemplo, la pequeña pantalla en un dispositivo móvil normalmente significa que solo una
aplicación (es decir, la actividad) está visible en un momento. Otras actividades se mueven al fondo y se insertan
en un estado suspendido, donde no se puede realizar cualquier trabajo. Sin embargo, sólo porque una aplicación
Android está en segundo plano no significa que es imposible que la aplicación siga funcionando.
Las aplicaciones de Android están formadas por al menos uno de los siguientes cuatro componentes principales:
Las actividades, receptores de difusión, proveedores de contenido, y servicios. Las actividades son la piedra
angular de muchas excelentes aplicaciones de Android, ya que proporcionan la interfaz de usuario que permite al
usuario interactuar con la aplicación. Sin embargo, cuando se trata de realizar simultáneas o trabajo en segundo
plano, las actividades no son siempre la mejor opción.
El mecanismo principal para el trabajo en segundo plano en Android es el servicio. Un servicio de Android es un
componente que está diseñado para realizar algún trabajo sin una interfaz de usuario. Un servicio podría
descargar un archivo, reproducir música o aplicar un filtro a una imagen. También se pueden usar servicios para
la comunicación entre procesos (IPC ) entre las aplicaciones de Android. Por ejemplo, una aplicación de Android
puede usar el servicio de Reproductor de música es desde otra aplicación o una aplicación podría exponer los
datos (por ejemplo, información de contacto de una persona) a otras aplicaciones a través de un servicio.
Servicios y su capacidad para realizar el trabajo en segundo plano, son cruciales para proporcionar una interfaz
de usuario fluida y sin problemas. Todas las aplicaciones de Android tienen un subproceso principal (también
conocido como un el subproceso de interfaz de usuario) en que se ejecutan las actividades. Para que el dispositivo
siga respondiendo, Android debe ser capaz de actualizar la interfaz de usuario a una velocidad de 60 fotogramas
por segundo. Si una aplicación Android realiza demasiado trabajo en el subproceso principal, entonces Android
coloque fotogramas, lo que a su vez hace que la interfaz de usuario aparece irregular (también a veces se
denomina janky). Esto significa que debe completar todo el trabajo realizado en el subproceso de interfaz de
usuario en el intervalo de tiempo entre los dos marcos, aproximadamente 16 milisegundos (1 segundo cada 60
fotogramas).
Para solucionar este problema, un desarrollador puede usar subprocesos en una actividad para realizar algún
trabajo que se bloquearía la interfaz de usuario. Sin embargo, esto podría producir problemas. Es muy posible
que Android destruirá y volver a crear las distintas instancias de la actividad. Sin embargo, Android destruirá
automáticamente los subprocesos, lo que podrían dar lugar a pérdidas de memoria. Un buen ejemplo de esto es
cuando la se gira el dispositivo – Android intentará destruye la instancia de la actividad y, a continuación, volver a
crear una nueva:
Se trata de una posible pérdida de memoria – seguirán ejecutando el subproceso creado por la primera instancia
de la actividad. Si el subproceso tiene una referencia a la primera instancia de la actividad, esto impedirá Android
recopilar el objeto de elementos no utilizados. Sin embargo, se sigue creando la segunda instancia de la actividad
(que a su vez podría crear un nuevo subproceso). Girar el dispositivo varias veces en una sucesión rápida puede
agotar toda la RAM y forzar Android para terminar la aplicación completa para reclamar la memoria.
Como regla general, si el trabajo que se realizará debe durar más que una actividad, a continuación, un servicio
debe crearse para llevar a cabo ese trabajo. Sin embargo, si el trabajo solo es aplicable en el contexto de una
actividad, a continuación, crear un subproceso para realizar el trabajo puede ser más adecuado. Por ejemplo, la
creación de una miniatura para ver una fotografía que se acaba de agregar a una aplicación de Galería fotográfica
probablemente debe producirse en un servicio. Sin embargo, un subproceso podría ser más adecuado para
reproducir la música que sólo debe ser escuchada mientras una actividad está en primer plano.
Trabajo en segundo plano puede dividirse en dos clasificaciones amplias:
1. Tarea larga ejecución – se trata de trabajo que está en curso hasta que se detiene explícitamente. Un
ejemplo de un tareas de larga ejecución es una aplicación que transmite por secuencias música o que debe
supervisar los datos recopilados por un sensor. Aunque la aplicación no tiene ninguna interfaz de usuario
visible, deben ejecutar estas tareas.
2. Tareas periódicas – (a veces se denomina un trabajo) una tarea periódica es aquel que es de relativamente
corta duración (unos segundos) y se ejecuta según una programación (es decir, una vez al día durante una
semana o quizás solo una vez en el próximos 60 segundos). Un ejemplo de esto es descargar un archivo desde
internet o generar una miniatura de una imagen.
Hay cuatro tipos diferentes de servicios de Android:
Enlazar servicio – un enlazado servicio es un servicio que tiene algún otro componente (normalmente
una actividad) enlazado a él. Un servicio dependiente proporciona una interfaz que permite el componente
enlazado y el servicio interactúan entre sí. Una vez que existen más clientes enlazados al servicio, Android
apagará el servicio.
IntentService – Un IntentService es una subclase especializada de la Service clase que simplifica la
creación de servicios y uso. Un IntentService está diseñado para controlar las llamadas individuales
autónomas. A diferencia de un servicio, que al mismo tiempo se puede administrar varias llamadas, una
IntentService es más parecido a un procesador de la cola de trabajo – trabajo está en la cola y un
IntentService procesa cada trabajo de uno a la vez en un único subproceso de trabajo. Normalmente, un
IntentService no está enlazado a una actividad o un fragmento.

Servicio iniciado – A servicio iniciado es un servicio que se ha iniciado por algún otro componente
Android (por ejemplo, una actividad) y se ejecuta continuamente en segundo plano hasta que algo se
indica explícitamente el servicio se detenga. A diferencia de un servicio dependiente, un servicio iniciado
no tiene ningún cliente enlazado directamente a él. Por este motivo, es importante diseñar servicios
iniciados por lo que puede reiniciar correctamente según sea necesario.
Servicio híbrido – A servicio híbrido es un servicio que tiene las características de un servicio iniciado y
un enlazado servicio. Puede iniciar un servicio híbrido cuando un componente que se enlaza a ella o se
puede iniciar por algún evento. Un componente de cliente puede o no puede enlazarse al servicio híbrido.
Un servicio híbrido se seguirá ejecutando hasta que explícitamente se le indica a detener, o hasta que no
hay ningún cliente más enlazado a él.
Qué tipo de servicio que se usará es muy dependiente de los requisitos de la aplicación. Como regla general, un
IntentService o un servicio dependiente son suficientes para la mayoría de las tareas que debe llevar a cabo una
aplicación de Android, por lo que debe darse preferencia a uno de esos dos tipos de servicios. Un IntentService
es una buena elección para las tareas "Monoestable", como la descarga de un archivo, mientras que un servicio
dependiente sería adecuado cuando se requiere con frecuencia interacciones con un fragmento de actividad.
Aunque la mayoría de los servicios se ejecuta en segundo plano, hay una subcategoría especial, conocida como
un servicio de primer plano. Se trata de un servicio que se asigna una prioridad más alta (en comparación con un
servicio normal) para realizar algún trabajo para el usuario (por ejemplo, reproducir música).
También es posible ejecutar un servicio en su propio proceso en el mismo dispositivo, esto se denomina a veces
un servicio remoto o como un servicio fuera de proceso. Esto requiere más esfuerzo para crear, pero puede ser
útil para cuando una aplicación necesita compartir la funcionalidad con otras aplicaciones y puede, en algunos
casos, mejorar la experiencia del usuario de una aplicación.
Límites de ejecución en segundo plano en Android 8.0
A partir de Android 8.0 (nivel de API 26), una aplicación Android ya no tiene la capacidad de ejecutar libremente
en segundo plano. En primer plano, una aplicación puede iniciar y ejecutar los servicios sin restricciones. Cuando
una aplicación se mueve en segundo plano, Android le dará a la aplicación de una cierta cantidad de tiempo para
iniciar y usar los servicios. Una vez transcurrido ese tiempo, la aplicación ya no puede iniciar los servicios y se
terminarán todos los servicios que se iniciaron. En este momento no es posible que la aplicación realizar
cualquier trabajo. Android considera que una aplicación puede estar en primer plano, si se cumple una de las
condiciones siguientes:
Hay una actividad visible (iniciado o en pausa).
La aplicación ha iniciado un servicio de primer plano.
Otra aplicación está en primer plano y utiliza los componentes de una aplicación que de lo contrario en
segundo plano. Un ejemplo de esto es si una aplicación, que se encuentra en primer plano, se enlaza a un
servicio suministrado por aplicación B. aplicación B, a continuación, también sería considera en primer plano y
no termina con Android para que se está en segundo plano.
Existen algunas situaciones donde, aunque es una aplicación en segundo plano, Android reactivar la aplicación y
relajar estas restricciones durante unos minutos, que permite a la aplicación realizar algún trabajo:
La aplicación recibe una mensaje en la nube de Firebase de prioridad alta.
La aplicación recibe una difusión.
La aplicación recibe y ejecuta un PendingIntent en respuesta a una notificación.

Las aplicaciones existentes de Xamarin.Android que tenga que cambiar la forma de realizar tareas en segundo
plano para evitar cualquier problema que pueda surgir en Android 8.0. Estas son algunas alternativas prácticas
para un servicio de Android:
Programar el trabajo para ejecutar en segundo plano mediante el programador de trabajos de
Android o el distribuidor de trabajo de Firebase – estas dos bibliotecas proporcionan un marco para
aplicaciones separar los trabajos en segundo plano en trabajos, una unidad de trabajo discreta. Aplicaciones, a
continuación, pueden programar el trabajo con el sistema operativo junto con algunos criterios sobre cuándo
puede ejecutar el trabajo.
Iniciar el servicio en primer plano – un servicio de primer plano es útil para cuando la aplicación debe
realizar alguna tarea en segundo plano y el usuario que deba periódicamente interactuar con esa tarea. El
servicio de primer plano mostrará una notificación persistente para que el usuario sea consciente de que la
aplicación se está ejecutando una tarea en segundo plano y también proporciona una manera de supervisar o
interactuar con la tarea. Un ejemplo de esto sería una aplicación de podcasting reproducir un podcast para el
usuario o quizás descarga un episodio del podcast para que tenían más adelante.
Usar una mensaje de nube de Firebase (FCM ) de alta prioridad – Android cuando recibe una prioridad
alta FCM para una aplicación, permitirá que esa aplicación ejecutar servicios en segundo plano durante un
breve período de tiempo. Esto sería una buena alternativa a tener un servicio en segundo plano que sondea
una aplicación en segundo plano.
Aplazar el trabajo de la aplicación cuando se pone en primer plano – si ninguna de las soluciones
anteriores son viable, las aplicaciones deben desarrollar su propia manera de pausar y reanudar el trabajo
cuando la aplicación se pone en primer plano.

Vínculos relacionados
Limita la ejecución en segundo plano de Android Oreo
Crear un servicio
16/08/2019 • 9 minutes to read • Edit Online

Los servicios de Xamarin. Android deben obedecer dos reglas inviolable de servicios Android:
Deben extender el Android.App.Service .
Deben decorarse con Android.App.ServiceAttribute .
Otro requisito de los servicios de Android es que se deben registrar en archivo AndroidManifest. XML y asignar
un nombre único. Xamarin. Android registrará automáticamente el servicio en el manifiesto en tiempo de
compilación con el atributo XML necesario.
Este fragmento de código es el ejemplo más sencillo de creación de un servicio en Xamarin. Android que cumple
estos dos requisitos:

[Service]
public class DemoService : Service
{
// Magical code that makes the service do wonderful things.
}

En tiempo de compilación, Xamarin. Android registrará el servicio insertando el siguiente elemento XML en
archivo AndroidManifest. XML (Observe que Xamarin. Android generó un nombre aleatorio para el servicio):

<service android:name="md5a0cbbf8da641ae5a4c781aaf35e00a86.DemoService" />

Es posible compartir un servicio con otras aplicaciones de Android exportándolos . Esto se logra estableciendo la
Exported propiedad ServiceAttribute en. Al exportar un servicio, la ServiceAttribute.Name propiedad también
debe establecerse para proporcionar un nombre público significativo para el servicio. Este fragmento de código
muestra cómo exportar y asignar un nombre a un servicio:

[Service(Exported=true, Name="com.xamarin.example.DemoService")]
public class DemoService : Service
{
// Magical code that makes the service do wonderful things.
}

El elemento archivo AndroidManifest. XML para este servicio tendrá un aspecto similar al siguiente:

<service android:exported="true" android:name="com.xamarin.example.DemoService" />

Los servicios tienen su propio ciclo de vida con métodos de devolución de llamada que se invocan cuando se crea
el servicio. Exactamente qué métodos se invocan depende del tipo de servicio. Un servicio iniciado debe
implementar distintos métodos de ciclo de vida que un servicio enlazado, mientras que un servicio híbrido debe
implementar los métodos de devolución de llamada para un servicio iniciado y un servicio enlazado. Estos
métodos son todos los miembros de Service la clase; el modo en que se inicia el servicio determinará qué
métodos de ciclo de vida se invocarán. Estos métodos de ciclo de vida se tratarán con más detalle más adelante.
De forma predeterminada, un servicio se iniciará en el mismo proceso que una aplicación de Android. Es posible
iniciar un servicio en su propio proceso estableciendo la ServiceAttribute.IsolatedProcess propiedad en true:
[Service(IsolatedProcess=true)]
public class DemoService : Service
{
// Magical code that makes the service do wonderful things, in it's own process!
}

El siguiente paso consiste en examinar cómo iniciar un servicio y, a continuación, pasar a examinar cómo
implementar los tres tipos de servicios diferentes.

NOTE
Un servicio se ejecuta en el subproceso de la interfaz de usuario, por lo que si se va a realizar algún trabajo que bloquea la
interfaz de usuario, el servicio debe usar subprocesos para realizar el trabajo.

Iniciar un servicio
La forma más básica de iniciar un servicio en Android es enviar un Intent que contiene metadatos para ayudar a
identificar qué servicio debe iniciarse. Hay dos estilos diferentes de intenciones que se pueden usar para iniciar un
servicio:
Intento explícito Un intento explícito identificará exactamente qué servicio se debe usar para completar
una acción determinada. – Un intento explícito puede considerarse como una letra que tiene una dirección
específica; Android enrutará la intención al servicio que se identifica explícitamente. Este fragmento de
código es un ejemplo del uso de un intento explícito para iniciar DownloadService un servicio denominado:

// Example of creating an explicit Intent in an Android Activity


Intent downloadIntent = new Intent(this, typeof(DownloadService));
downloadIntent.data = Uri.Parse(fileToDownload);

Intención implícita – Este tipo de intención identifica de manera flexible la acción que el usuario desea
realizar, pero el servicio exacto para completar esa acción es desconocido. Una intención implícita puede
considerarse como una carta que se dirige "a quién puede afectar...". Android examinará el contenido de la
intención y determinará si hay un servicio existente que coincida con la intención.
Un filtro de intención se utiliza para ayudar a hacer coincidir la intención implícita con un servicio registrado.
Un filtro de intención es un elemento XML que se agrega a archivo AndroidManifest. XML , que contiene
los metadatos necesarios para ayudar a que un servicio coincida con una intención implícita.

Intent sendIntent = new Intent("common.xamarin.DemoService");


sendIntent.Data = Uri.Parse(fileToDownload);

Si Android tiene más de una coincidencia posible para una intención implícita, puede pedirle al usuario que
seleccione el componente para controlar la acción:
![Captura de pantalla de un cuadro de diálogo de] desambiguación (images/creating-a-service-01.png "Captura de
pantalla de un cuadro de diálogo de") desambiguación

IMPORTANT
A partir de Android 5,0 (nivel de AP 21), no se puede usar una intención implícita para iniciar un servicio.

Siempre que sea posible, las aplicaciones deben usar intentos explícitos para iniciar un servicio. Una intención
implícita no pide que un servicio específico inicie – , es una solicitud de algún servicio instalado en el dispositivo
para controlar la solicitud. Esta solicitud ambigua puede dar lugar a que el servicio equivocado controle la solicitud
o que otra aplicación se inicie innecesariamente (lo que aumenta la presión de los recursos en el dispositivo).
La forma en que se envía el intento depende del tipo de servicio y se tratará con más detalle más adelante en las
guías específicas de cada tipo de servicio.
Creación de un filtro de intención para intenciones IMPLÍCITAS
Para asociar un servicio con una intención implícita, una aplicación Android debe proporcionar algunos metadatos
para identificar las capacidades del servicio. Los _filtros de intención_proporcionan estos metadatos. Los filtros de
intención contienen información, como una acción o un tipo de datos, que deben estar presentes para iniciar un
servicio. En Xamarin. Android, el filtro de intención se registra en archivo AndroidManifest. XML al decorar un
servicio IntentFilterAttribute con. Por ejemplo, el código siguiente agrega un filtro de intención con una acción
asociada com.xamarin.DemoService de:

[Service]
[IntentFilter(new String[]{"com.xamarin.DemoService"})]
public class DemoService : Service
{
}

Esto da como resultado la inclusión de una entrada en el archivo – archivo AndroidManifest. XML en una
entrada que se empaqueta con la aplicación de forma análoga al ejemplo siguiente:

<service android:name="demoservice.DemoService">
<intent-filter>
<action android:name="com.xamarin.DemoService" />
</intent-filter>
</service>

Con los aspectos básicos de un servicio de Xamarin. Android fuera de camino, vamos a examinar los distintos
subtipos de servicios con más detalle.

Vínculos relacionados
Android.App.Service
Android.App.ServiceAttribute
Android.App.Intent
Android.App.IntentFilterAttribute
Servicios enlazados en Xamarin. Android
19/08/2019 • 20 minutes to read • Edit Online

Los servicios enlazados son servicios de Android que proporcionan una interfaz cliente-servidor que un cliente
(como una actividad de Android ) puede interactuar con. En esta guía se describen los componentes clave
implicados en la creación de un servicio enlazado y cómo usarlo en una aplicación de Xamarin. Android.

Información general sobre servicios enlazados


Los servicios que proporcionan una interfaz cliente-servidor para que los clientes interactúen directamente con el
servicio se conocen como servicios enlazados. Puede haber varios clientes conectados a una única instancia de un
servicio al mismo tiempo. El servicio enlazado y el cliente están aislados entre sí. En su lugar, Android proporciona
una serie de objetos intermedios que administran el estado de la conexión entre los dos. Este estado es mantenido
por un objeto que implementa la Android.Content.IServiceConnection interfaz. El cliente crea este objeto y se pasa
como un parámetro al BindService método. Está disponible en cualquier Android.Content.Context objeto (como
una actividad). BindService Se trata de una solicitud al sistema operativo Android para iniciar el servicio y enlazar
un cliente a él. Hay tres maneras de enlazar un cliente a un servicio mediante el BindService método:
Un enlazador de servicios Un enlazador de servicios es una clase que implementa la Android.OS.IBinder
interfaz. – La mayoría de las aplicaciones no implementarán esta interfaz directamente, sino que extienden la
Android.OS.Binder clase. Este es el enfoque más común y es adecuado para cuando el servicio y el cliente
existen en el mismo proceso.
Uso de Messenger – Esta técnica es adecuada para cuando el servicio puede existir en un proceso
independiente. En su lugar, se calcula la referencia de las solicitudes de servicio entre el Android.OS.Messenger
cliente y el servicio a través de. Se crea en el servicio que controlará las Messenger solicitudes.
Android.OS.Handler Esto se tratará en otra guía.
Uso del lenguaje de definición de interfaz de Android (AIDL ) – AIDL es una técnica avanzada que no se
tratará en esta guía.
Una vez que un cliente se ha enlazado a un servicio, la comunicación entre los Android.OS.IBinder dos se produce
a través de un objeto. Este objeto es responsable de la interfaz que permitirá al cliente interactuar con el servicio.
No es necesario que cada aplicación de Xamarin. Android implemente esta interfaz desde cero, el Android SDK
proporciona la Android.OS.Binder clase que se encarga de la mayor parte del código necesario para calcular las
referencias del objeto entre el cliente y el servicio.
Cuando un cliente se realiza con el servicio, debe desenlazarlo mediante una llamada al UnbindService método.
Una vez que el último cliente se ha desenlazado de un servicio, Android detendrá y eliminará el servicio enlazado.
En este diagrama se ilustra el modo en que la actividad, la conexión de servicio, el enlazador y el servicio se
relacionan entre sí:
En esta guía se explica cómo extender la Service clase para implementar un servicio enlazado. También se tratará
la IServiceConnection implementación y Binder la extensión para permitir que un cliente se comunique con el
servicio. Una aplicación de ejemplo acompaña a esta guía, que contiene una solución con un solo proyecto de
Xamarin. Android denominado BoundServiceDemo . Se trata de una aplicación muy básica que muestra cómo
implementar un servicio y cómo enlazar una actividad a él. El servicio enlazado tiene una API muy sencilla con un
solo método GetFormattedTimestamp ,, que devuelve una cadena que indica al usuario Cuándo se ha iniciado el
servicio y cuánto tiempo se ha estado ejecutando. La aplicación también permite al usuario Desenlazar
manualmente y enlazar con el servicio.
Implementación y consumo de un servicio enlazado
Hay tres componentes que se deben implementar para que una aplicación Android consuma un servicio enlazado:
1. Extienda la Service clase e implemente los métodos – de devolución de llamada del ciclo de vida esta
clase contendrá el código que realizará el trabajo que se solicitará del servicio. Esto se tratará con más detalle a
continuación.
2. Crear una clase que implemente IServiceConnection – esta interfaz proporciona métodos de devolución de
llamada invocados por Android para notificar al cliente cuando la conexión con el servicio ha cambiado, es decir,
el cliente se ha conectado o desconectado al servicio. La conexión de servicio también proporcionará una
referencia a un objeto que el cliente puede utilizar para interactuar directamente con el servicio. Esta referencia
se conoce como el enlazador.
3. Crear una clase que implemente IBinder – una implementación de enlazador proporciona la API que un
cliente utiliza para comunicarse con el servicio. El enlazador puede proporcionar una referencia al servicio
enlazado, lo que permite invocar métodos directamente o el enlazador puede proporcionar una API de cliente
que encapsula y oculta el servicio enlazado de la aplicación. Un IBinder debe proporcionar el código necesario
para las llamadas a procedimientos remotos. No es necesario (o recomendado) implementar la IBinder
interfaz directamente. En su lugar, las aplicaciones Binder deben extender el tipo que proporciona la mayor
parte de la IBinder funcionalidad básica que requiere.
4. Inicio y enlace a un servicio – Una vez que se ha creado la conexión de servicio, el enlazador y el servicio, la
aplicación de Android es responsable de iniciar el servicio y enlazarlo.
Cada uno de estos pasos se tratará con más detalle en las secciones siguientes.
Extender la Service clase
Para crear un servicio con Xamarin. Android, es necesario crear una subclase Service y adornar la clase
ServiceAttribute con. Las herramientas de compilación de Xamarin. Android usan el atributo para registrar
correctamente el servicio en el archivo archivo AndroidManifest. XML de la aplicación de forma similar a una
actividad, un servicio enlazado tiene su propio ciclo de vida y métodos de devolución de llamada asociados a los
eventos importantes en su ciclo de vida. La lista siguiente es un ejemplo de algunos de los métodos de devolución
de llamada más comunes que implementará un servicio:
OnCreate – Android invoca este método, ya que crea instancias del servicio. Se utiliza para inicializar las
variables u objetos que requiere el servicio durante su vigencia. Este método es opcional.
OnBind – Este método debe ser implementado por todos los servicios enlazados. Se invoca cuando el primer
cliente intenta conectarse al servicio. Devolverá una instancia de IBinder para que el cliente pueda interactuar
con el servicio. Siempre que el servicio se esté ejecutando, el IBinder objeto se usará para satisfacer las
solicitudes de cliente futuras para enlazar con el servicio.
OnUnbind – Se llama a este método cuando todos los clientes enlazados tienen desenlazado. Al devolver true
desde este método, el servicio llamará OnRebind más adelante con el intento que OnUnbind se pasa a cuando
los nuevos clientes se enlazan a él. Lo haría cuando un servicio siga ejecutándose una vez que se haya
desenlazado. Esto ocurrirá si el servicio desenlazado recientemente también era un servicio iniciado y
StopService o StopSelf no se hubiese llamado. En este escenario, OnRebind permite recuperar el intento. El
valor predeterminado false devuelve, que no hace nada. Opcional.
OnDestroy – Se llama a este método cuando Android está destruyendo el servicio. Cualquier limpieza necesaria,
como liberar recursos, debe realizarse en este método. Opcional.
Los eventos de ciclo de vida clave de un servicio enlazado se muestran en este diagrama:
En el siguiente fragmento de código, desde la aplicación complementaria que acompaña a esta guía, se muestra
cómo implementar un servicio enlazado en Xamarin. Android:
using Android.App;
using Android.Util;
using Android.Content;
using Android.OS;

namespace BoundServiceDemo
{
[Service(Name="com.xamarin.ServicesDemo1")]
public class TimestampService : Service, IGetTimestamp
{
static readonly string TAG = typeof(TimestampService).FullName;
IGetTimestamp timestamper;

public IBinder Binder { get; private set; }

public override void OnCreate()


{
// This method is optional to implement
base.OnCreate();
Log.Debug(TAG, "OnCreate");
timestamper = new UtcTimestamper();
}

public override IBinder OnBind(Intent intent)


{
// This method must always be implemented
Log.Debug(TAG, "OnBind");
this.Binder = new TimestampBinder(this);
return this.Binder;
}

public override bool OnUnbind(Intent intent)


{
// This method is optional to implement
Log.Debug(TAG, "OnUnbind");
return base.OnUnbind(intent);
}

public override void OnDestroy()


{
// This method is optional to implement
Log.Debug(TAG, "OnDestroy");
Binder = null;
timestamper = null;
base.OnDestroy();
}

/// <summary>
/// This method will return a formatted timestamp to the client.
/// </summary>
/// <returns>A string that details what time the service started and how long it has been running.
</returns>
public string GetFormattedTimestamp()
{
return timestamper?.GetFormattedTimestamp();
}
}
}

En el ejemplo, el OnCreate método inicializa un objeto que contiene la lógica para recuperar y dar formato a una
marca de tiempo que el cliente solicitará. Cuando el primer cliente intenta enlazar con el servicio, Android invocará
el OnBind método. Este servicio creará una instancia TimestampBinder de un objeto que permitirá a los clientes
tener acceso a esta instancia del servicio en ejecución. La TimestampBinder clase se describe en la sección siguiente.
Implementación de IBinder
Como se mencionó, IBinder un objeto proporciona el canal de comunicación entre un cliente y un servicio. Las
aplicaciones de Android no deben IBinder implementar la interfaz Android.OS.Binder ; se debe extender. La
Binder clase proporciona gran parte de la infraestructura necesaria, lo que es necesario para calcular las
referencias del objeto de enlazador desde el servicio (que se puede estar ejecutando en un proceso independiente)
al cliente. En la mayoría de los Binder casos, la subclase es solo unas pocas líneas de código y ajusta una
referencia al servicio. En este ejemplo, TimestampBinder tiene una propiedad que expone el TimestampService al
cliente:

public class TimestampBinder : Binder


{
public TimestampBinder(TimestampService service)
{
this.Service = service;
}

public TimestampService Service { get; private set; }


}

Esto Binder hace posible invocar los métodos públicos en el servicio; por ejemplo:

string currentTimestamp = serviceConnection.Binder.Service.GetFormattedTimestamp()

Una Binder vez que se ha ampliado, es necesario implementar IServiceConnection para conectar todo.
Crear la conexión de servicio
El IServiceConnection objeto presentará | introducción | exponer | conectar Binder el objeto al cliente. Además de
implementar la IServiceConnection interfaz, la clase debe extenderse. Java.Lang.Object La conexión de servicio
también debe proporcionar alguna manera en que el cliente puede Binder tener acceso a (y, por tanto,
comunicarse con el servicio enlazado).
Este código procede del proyecto de ejemplo que lo acompaña es una forma posible de IServiceConnection
implementar:
using Android.Util;
using Android.OS;
using Android.Content;

namespace BoundServiceDemo
{
public class TimestampServiceConnection : Java.Lang.Object, IServiceConnection, IGetTimestamp
{
static readonly string TAG = typeof(TimestampServiceConnection).FullName;

MainActivity mainActivity;
public TimestampServiceConnection(MainActivity activity)
{
IsConnected = false;
Binder = null;
mainActivity = activity;
}

public bool IsConnected { get; private set; }


public TimestampBinder Binder { get; private set; }

public void OnServiceConnected(ComponentName name, IBinder service)


{
Binder = service as TimestampBinder;
IsConnected = this.Binder != null;

string message = "onServiceConnected - ";


Log.Debug(TAG, $"OnServiceConnected {name.ClassName}");

if (IsConnected)
{
message = message + " bound to service " + name.ClassName;
mainActivity.UpdateUiForBoundService();
}
else
{
message = message + " not bound to service " + name.ClassName;
mainActivity.UpdateUiForUnboundService();
}

Log.Info(TAG, message);
mainActivity.timestampMessageTextView.Text = message;

public void OnServiceDisconnected(ComponentName name)


{
Log.Debug(TAG, $"OnServiceDisconnected {name.ClassName}");
IsConnected = false;
Binder = null;
mainActivity.UpdateUiForUnboundService();
}

public string GetFormattedTimestamp()


{
if (!IsConnected)
{
return null;
}

return Binder?.GetFormattedTimestamp();
}
}
}
Como parte del proceso de enlace, Android invocará el OnServiceConnected método, proporcionando el name del
servicio que se está enlazando y el binder que contiene una referencia al propio servicio. En este ejemplo, la
conexión de servicio tiene dos propiedades, una que contiene una referencia al enlazador y una marca booleana
para si el cliente está conectado al servicio o no.
El OnServiceDisconnected método solo se invoca cuando la conexión entre un cliente y un servicio se pierde o se
interrumpe inesperadamente. Este método permite al cliente tener la oportunidad de responder a la interrupción
en el servicio.

Inicio y enlace a un servicio con un intento explícito


Para usar un servicio enlazado, un cliente (por ejemplo, una actividad) debe crear una instancia de un
Android.Content.IServiceConnection objeto que implemente e invoque el BindService método. BindService
devolverá true si el servicio está enlazado false a, si no lo está. El método BindService toma tres parámetros:
Una Intent intención– debe identificar explícitamente a qué servicio se va a conectar.
Un IServiceConnection objeto– este objeto es un intermediario que proporciona métodos de devolución de
llamada para notificar al cliente cuando se inicia y se detiene el servicio enlazado.
enum este parámetro es un conjunto de marcas que el sistema utiliza para enlazar el objeto.
Android.Content.Bind – El valor que se usa con Bind.AutoCreate más frecuencia es, que iniciará
automáticamente el servicio si aún no se está ejecutando.
El siguiente fragmento de código es un ejemplo de cómo iniciar un servicio enlazado en una actividad mediante un
intento explícito:

protected override void OnStart ()


{
base.OnStart ();

if (serviceConnection == null)
{
this.serviceConnection = new TimestampServiceConnection(this);
}

Intent serviceToStart = new Intent(this, typeof(TimestampService));


BindService(serviceToStart, this.serviceConnection, Bind.AutoCreate);

IMPORTANT
A partir de Android 5,0 (nivel de API 21), solo es posible enlazar a un servicio con una intención explícita.

Notas arquitectónicas sobre la conexión de servicio y el enlazador.


Algunos puristas de OOP pueden no aprobar la implementación anterior de la TimestampBinder clase, ya que es
una infracción de la ley de Demeter que, en sus Estados de formulario más sencillos, no se comunica con los
extraños; Hable solo con sus amigos. Esta implementación concreta expone la clase concreta TimestampService a
todos los clientes.
En realidad, no es necesario que el cliente conozca TimestampService y exponer esa clase concreta a los clientes
puede hacer que una aplicación sea más frágil y más difícil de mantener durante su duración. Un enfoque
alternativo es usar una interfaz que exponga el GetFormattedTimestamp() método y las llamadas de proxy al
servicio a través de Binder (o posible la clase de conexión de servicio):
public class TimestampBinder : Binder, IGetTimestamp
{
TimestampService service;
public TimestampBinder(TimestampService service)
{
this.service = service;
}

public string GetFormattedTimestamp()


{
return service?.GetFormattedTimestamp();
}
}

En este ejemplo concreto se permite que una actividad invoque métodos en el propio servicio:

// In this example the Activity is only talking to a friend, i.e. the IGetTimestamp interface provided by the
Binder.
string currentTimestamp = serviceConnection.Binder.GetFormattedTimestamp()

Vínculos relacionados
Android.App.Service
Android.Content.Bind
Android.Content.Context
Android.Content.IServiceConnection
Android.OS.Binder
Android.OS.IBinder
BoundServiceDemo (ejemplo)
Servicios de intención en Xamarin. Android
27/07/2019 • 3 minutes to read • Edit Online

Información general sobre servicios de intención


Tanto los servicios iniciados como los enlazados se ejecutan en el subproceso principal, lo que significa que para
mantener el rendimiento sin problemas, un servicio necesita realizar el trabajo de forma asincrónica. Una de las
formas más sencillas de solucionar este problema es con un patrón de procesador de cola de trabajo, en el que el
trabajo que se va a hacer se coloca en una cola a la que presta servicio un solo subproceso.
Es una subclase de la Service clase que proporciona una implementación específica de Android de este patrón.
IntentService Administrará el trabajo de puesta en cola, iniciará un subproceso de trabajo para atender la cola y
eliminará las solicitudes de la cola que se va a ejecutar en el subproceso de trabajo. Un IntentService se detendrá
de forma silenciosa y quitará el subproceso de trabajo cuando no haya más trabajo en la cola.
Para enviar el trabajo a la cola, se Intent crea y, a Intent continuación, StartService se pasa al método.
No es posible detener o interrumpir el OnHandleIntent método IntentService mientras está funcionando. Debido
a este diseño, IntentService debe mantenerse – sin estado y no debe basarse en una conexión activa o en una
comunicación desde el resto de la aplicación. Una IntentService está pensada para statelessly procesar las
solicitudes de trabajo.
Existen dos requisitos para la subclase IntentService :
1. El nuevo tipo (creado por la creación de IntentService subclases) solo invalida OnHandleIntent el método.
2. El constructor del nuevo tipo requiere una cadena que se usa para asignar un nombre al subproceso de trabajo
que controlará las solicitudes. El nombre de este subproceso de trabajo se usa principalmente al depurar la
aplicación.
En el código siguiente se IntentService muestra una implementación con el OnHandleIntent método invalidado:

[Service]
public class DemoIntentService: IntentService
{
public DemoIntentService () : base("DemoIntentService")
{
}

protected override void OnHandleIntent (Android.Content.Intent intent)


{
Console.WriteLine ("perform some long running work");
...
Console.WriteLine ("work complete");
}
}

El trabajo se envía a IntentService una instancia Intent de y, a continuación, StartService llama al método con
esa intención como parámetro. La intención se pasará al servicio como un parámetro en el OnHandleIntent
método. Este fragmento de código es un ejemplo de envío de una solicitud de trabajo a un intento:
// This code might be called from within an Activity, for example in an event
// handler for a button click.
Intent downloadIntent = new Intent(this, typeof(DemoIntentService));

// This is just one example of passing some values to an IntentService via the Intent:
downloadIntent.Put
("file_to_download", "http://www.somewhere.com/file/to/download.zip");

StartService(downloadIntent);

IntentService Puede extraer los valores de la intención, tal como se muestra en este fragmento de código:

protected override void OnHandleIntent (Android.Content.Intent intent)


{
string fileToDownload = intent.GetStringExtra("file_to_download");

Log.Debug("DemoIntentService", $"File to download: {fileToDownload}.");


}

Vínculos relacionados
IntentService
StartService
Servicios iniciados con Xamarin. Android
31/07/2019 • 11 minutes to read • Edit Online

Introducción a los servicios iniciados


Los servicios iniciados suelen realizar una unidad de trabajo sin proporcionar comentarios directos o resultados al
cliente. Un ejemplo de una unidad de trabajo es un servicio que carga un archivo en un servidor. El cliente realizará
una solicitud a un servicio para cargar un archivo desde el dispositivo a un sitio Web. El servicio cargará
silenciosamente el archivo (incluso si la aplicación no tiene ninguna actividad en primer plano) y se terminará
cuando se haya completado la carga. Es importante saber que un servicio iniciado se ejecutará en el subproceso de
interfaz de usuario de una aplicación. Esto significa que si un servicio va a realizar el trabajo que bloqueará el
subproceso de la interfaz de usuario, debe crear y eliminar los subprocesos según sea necesario.
A diferencia de un servicio enlazado, no hay ningún canal de comunicación entre un servicio iniciado "puro" y sus
clientes. Esto significa que un servicio iniciado implementará algunos métodos de ciclo de vida distintos de un
servicio enlazado. En la lista siguiente se resaltan los métodos de ciclo de vida comunes en un servicio iniciado:
OnCreate – Se llama una vez cuando se inicia el servicio por primera vez. Aquí es donde se debe implementar el
código de inicialización.
OnBind – Este método debe ser implementado por todas las clases de servicio; sin embargo, un servicio iniciado
no tiene normalmente un cliente enlazado a él. Por este motivo, un servicio iniciado simplemente devuelve
null . En cambio, un servicio híbrido (que es la combinación de un servicio enlazado y un servicio iniciado)
tiene que implementar y devolver Binder un para el cliente.
OnStartCommand Se llama para cada solicitud de inicio del servicio, ya sea en respuesta a una StartService
llamada a o a un reinicio del sistema. – Aquí es donde el servicio puede iniciar cualquier tarea de ejecución
prolongada. El método devuelve un StartCommandResult valor que indica cómo o si el sistema debe controlar el
reinicio del servicio después de un cierre debido a la falta de memoria. Esta llamada se realiza en el subproceso
principal. Este método se describe con más detalle a continuación.
OnDestroy – Se llama a este método cuando se destruye el servicio. Se utiliza para realizar una limpieza final
requerida.
El método importante para un servicio iniciado es el OnStartCommand método. Se invocará cada vez que el servicio
reciba una solicitud para realizar algún trabajo. El siguiente fragmento de código es un ejemplo OnStartCommand de:

public override StartCommandResult OnStartCommand (Android.Content.Intent intent, StartCommandFlags flags, int


startId)
{
// This method executes on the main thread of the application.
Log.Debug ("DemoService", "DemoService started");
...
return StartCommandResult.Sticky;
}

El primer parámetro es un Intent objeto que contiene los metadatos sobre el trabajo que se va a realizar. El
segundo parámetro contiene un StartCommandFlags valor que proporciona información sobre la llamada al
método. Este parámetro tiene uno de dos valores posibles:
StartCommandFlag.RedeliveryEsto significa que es una nueva entrega de una anterior Intent . Intent – Este
valor se proporciona cuando se devolvió StartCommandResult.RedeliverIntent el servicio pero se detuvo antes
de que se pudiera apagar correctamente. - StartCommandFlag.Retry\ Este valor se recibe cuando se produce
OnStartCommand\ un error en una llamada anterior y Android intenta iniciar el servicio de nuevo con la misma
intención que el intento con error anterior. -
Por último, el tercer parámetro es un valor entero que es único para la aplicación que identifica la solicitud. Es
posible que varios llamadores puedan invocar el mismo objeto de servicio. Este valor se usa para asociar una
solicitud para detener un servicio con una solicitud determinada para iniciar un servicio. Se tratará con más detalle
en la sección detener el servicio.
El servicio StartCommandResult devuelve el valor como una sugerencia para Android sobre qué hacer si se elimina
el servicio debido a las restricciones de recursos. Hay tres valores posibles para StartCommandResult :
StartCommandResult. NotSticky – este valor indica a Android que no es necesario reiniciar el servicio que ha
eliminado. Como ejemplo, considere un servicio que genera miniaturas para una galería en una aplicación. Si se
elimina el servicio, no es fundamental volver a crear la miniatura inmediatamente – la miniatura se puede volver
a crear la próxima vez que se ejecute la aplicación.
StartCommandResult. – la permanencia indica a Android que reinicie el servicio, pero no que entregue el
último intento que inició el servicio. Si no hay ningún intento pendiente de control, null se proporcionará para
el parámetro de intención. Un ejemplo de esto podría ser una aplicación de reproductor de música; el servicio se
reiniciará listo para reproducir música, pero reproducirá la última canción.
StartCommandResult. RedeliverIntent – este valor indica a Android que reinicie el servicio y vuelva a ofrecer
el último Intent . Un ejemplo de esto es un servicio que descarga un archivo de datos para una aplicación. Si se
elimina el servicio, todavía es necesario descargar el archivo de datos. Al volver
StartCommandResult.RedeliverIntent , cuando Android reinicia el servicio, también proporcionará la intención
(que contiene la dirección URL del archivo que se va a descargar) al servicio. Esto permitirá que la descarga se
reinicie o se reanude (dependiendo de la implementación exacta del código).
Hay un cuarto valor para StartCommandResult . – StartCommandResult.ContinuationMask Devuelve este valor
OnStartCommand y describe cómo Android continuará el servicio que ha eliminado. Este valor no se usa
normalmente para iniciar un servicio.
Los eventos de ciclo de vida clave de un servicio iniciado se muestran en este diagrama:
Detener el servicio
Un servicio iniciado se mantendrá en ejecución indefinidamente. Android mantendrá el servicio en ejecución
siempre que haya suficientes recursos del sistema. El cliente debe detener el servicio o el servicio puede detenerse
cuando se realiza su trabajo. Hay dos maneras de detener un servicio:
Android. Content. Context. StopService () Un cliente (por ejemplo, una actividad) puede solicitar que se
detenga un servicio StopService llamando al método: –
StopService(new Intent(this, typeof(DemoService));

Android. app. Service. StopSelf () Un servicio puede apagarse inactivamente mediante la invocación del
StopSelf : –

StopSelf();

Uso de startId para detener un servicio


Varios llamadores pueden solicitar que se inicie un servicio. Si hay una solicitud de inicio pendiente, el servicio
puede usar el startId que se OnStartCommand pasa a para evitar que el servicio se detenga prematuramente. Se
corresponderá con la llamada más reciente StartService a, y se incrementará cada vez que se llame a. startId Por
consiguiente, si una solicitud subsiguiente StartService a aún no ha dado como resultado una OnStartCommand
llamada a, el servicio StopSelfResult puede llamar a y pasarle el startId valor más reciente de que ha recibido (en
StopSelf lugar de simplemente llamar a). Si una llamada a StartService aún no ha dado como resultado una
llamada correspondiente OnStartCommand a, el sistema no detendrá el servicio porque el startId usado en la
StopSelf llamada no se corresponderá con la StartService llamada más reciente.

Vínculos relacionados
StartedServicesDemo (ejemplo)
Android.App.Service
Android.App.StartCommandFlags
Android.App.StartCommandResult
Android.Content.BroadcastReceiver
Android.Content.Intent
Android.OS.Handler
Android.Widget.Toast
Iconos de la barra de estado
Servicios de primer plano
31/07/2019 • 6 minutes to read • Edit Online

Un servicio en primer plano es un tipo especial de un servicio enlazado o un servicio iniciado. En ocasiones, los
servicios realizarán tareas que los usuarios deben tener en cuenta activamente, estos servicios se denominan
servicios en primer plano. Un ejemplo de un servicio en primer plano es una aplicación que proporciona al usuario
las instrucciones mientras conduce o se dirige. Incluso si la aplicación está en segundo plano, todavía es importante
que el servicio tenga suficientes recursos para funcionar correctamente y que el usuario tenga una forma rápida y
cómoda de acceder a la aplicación. En el caso de una aplicación de Android, esto significa que un servicio en primer
plano debe recibir mayor prioridad que un servicio "normal" y Notification un servicio en primer plano debe
proporcionar un valor que indica que Android se mostrará siempre que se esté ejecutando el servicio.
Para iniciar un servicio en primer plano, la aplicación debe enviar un intento que indique a Android que inicie el
servicio. Después, el servicio debe registrarse como servicio en primer plano con Android. Las aplicaciones que se
ejecutan en Android 8,0 (o posterior) deben Context.StartForegroundService usar el método para iniciar el servicio,
mientras que las aplicaciones que se ejecutan en dispositivos con una versión anterior de Android deben usar
Context.StartService

Este C# método de extensión es un ejemplo de cómo iniciar un servicio en primer plano. En Android 8,0 y
versiones posteriores, usará el StartForegroundService método; de lo contrario StartService , se usará el método
anterior.

public static void StartForegroundServiceCompat<T>(this Context context, Bundle args = null) where T : Service
{
var intent = new Intent(context, typeof(T));
if (args != null)
{
intent.PutExtras(args);
}

if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O)


{
context.StartForegroundService(intent);
}
else
{
context.StartService(intent);
}
}

Registro como servicio en primer plano


Una vez que se inicia un servicio en primer plano, debe registrarse en Android mediante la StartForeground
invocación de. Si el servicio se inicia con el Service.StartForegroundService método pero no se registra a sí mismo,
Android detendrá el servicio y marcará la aplicación como no responde.
StartForeground toma dos parámetros, los cuales son obligatorios:
Valor entero que es único dentro de la aplicación para identificar el servicio.
Notification Objeto que Android mostrará en la barra de estado durante el tiempo que se esté ejecutando el
servicio.
Android mostrará la notificación en la barra de estado durante el tiempo que se esté ejecutando el servicio. La
notificación, como mínimo, proporcionará una indicación visual al usuario de que el servicio se está ejecutando.
Idealmente, la notificación debe proporcionar al usuario un acceso directo a la aplicación o, posiblemente, algunos
botones de acción para controlar la aplicación. Un ejemplo de esto es un reproductor – de música que la
notificación que se muestra puede tener botones para pausar o reproducir música, rebobinar a la canción anterior
o pasar a la siguiente canción.
Este fragmento de código es un ejemplo de registro de un servicio como servicio en primer plano:

// This is any integer value unique to the application.


public const int SERVICE_RUNNING_NOTIFICATION_ID = 10000;

public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)


{
// Code not directly related to publishing the notification has been omitted for clarity.
// Normally, this method would hold the code to be run when the service is started.

var notification = new Notification.Builder(this)


.SetContentTitle(Resources.GetString(Resource.String.app_name))
.SetContentText(Resources.GetString(Resource.String.notification_text))
.SetSmallIcon(Resource.Drawable.ic_stat_name)
.SetContentIntent(BuildIntentToShowMainActivity())
.SetOngoing(true)
.AddAction(BuildRestartTimerAction())
.AddAction(BuildStopServiceAction())
.Build();

// Enlist this instance of the service as a foreground service


StartForeground(SERVICE_RUNNING_NOTIFICATION_ID, notification);
}

La notificación anterior mostrará una notificación de la barra de estado similar a la siguiente:

Esta captura de pantalla muestra la notificación expandida en la bandeja de notificación con dos acciones que
permiten al usuario controlar el servicio:
Puede encontrar más información sobre las notificaciones en la sección notificaciones locales de la guía de
notificaciones de Android .

Anular el registro como servicio en primer plano


Un servicio se puede quitar de la lista como un servicio en primer plano llamando StopForeground al método.
StopForeground no detendrá el servicio, pero quitará el icono de notificación y indicará a Android que este servicio
se puede apagar si es necesario.
La notificación de la barra de estado que se muestra también se puede true quitar pasando al método:

StopForeground(true);

Si el servicio se detiene con una llamada a StopSelf o StopService , se quitará la notificación de la barra de estado.

Vínculos relacionados
Android.App.Service
Android.App.Service.StartForeground
Notificaciones locales
ForegroundServiceDemo (ejemplo)
Ejecución de servicios de Android en procesos
remotos
16/08/2019 • 50 minutes to read • Edit Online

Por lo general, todos los componentes de una aplicación de Android se ejecutarán en el mismo proceso. Los
servicios de Android son una excepción importante para esto, ya que se pueden configurar para que se ejecuten en
sus propios procesos y se compartan con otras aplicaciones, incluidas las de otros desarrolladores de Android. En
esta guía se explica cómo crear y usar un servicio remoto de Android con Xamarin.

Información general de servicios fuera de proceso


Cuando se inicia una aplicación, Android crea un proceso en el que se ejecuta la aplicación. Normalmente, todos
los componentes de la aplicación se ejecutarán en este proceso. Los servicios de Android son una excepción
importante para esto, ya que se pueden configurar para que se ejecuten en sus propios procesos y se compartan
con otras aplicaciones, incluidas las de otros desarrolladores de Android. Estos tipos de servicios se conocen como
servicios remotos o servicios fuera de proceso. El código de estos servicios se incluirá en el mismo APK que la
aplicación principal. sin embargo, cuando se inicia el servicio, Android creará un nuevo proceso solo para ese
servicio. Por el contrario, un servicio que se ejecuta en el mismo proceso que el resto de la aplicación a veces se
denomina servicio local.
En general, no es necesario que una aplicación implemente un servicio remoto. Un servicio local es suficiente (y
deseable) para los requisitos de una aplicación en muchos casos. Un fuera de proceso tiene su propio espacio de
memoria que debe ser administrado por Android. Aunque esto introduce más sobrecarga en la aplicación general,
hay algunos escenarios en los que puede ser ventajoso ejecutar un servicio en su propio proceso:
1. Funcionalidad de uso compartido – Algunos desarrolladores de aplicaciones pueden tener varias
aplicaciones y funcionalidad que se comparten entre todas las aplicaciones. El empaquetado de esa
funcionalidad en un servicio Android que se ejecuta en su propio proceso puede simplificar el
mantenimiento de la aplicación. También es posible empaquetar el servicio en su propio APK independiente
e implementarlo de forma independiente del resto de la aplicación.
2. Mejora de la experiencia del usuario – Hay dos formas posibles de que un servicio fuera de proceso
pueda mejorar la experiencia del usuario de la aplicación. La primera forma de tratar con la administración
de memoria. Cuando se produce un ciclo de recolección de elementos no utilizados (GC ), Android pausará
toda la actividad del proceso hasta que se complete el GC. El usuario podría percibir esta pausa como
"entrecortado" o "Jank". Cuando un servicio se ejecuta en su propio proceso, es el proceso de servicio que
está en pausa, no el proceso de la aplicación. Esta pausa será mucho menos perceptible para el usuario, ya
que el proceso de aplicación (y, por lo tanto, la interfaz de usuario) no está en pausa.
En segundo lugar, si los requisitos de memoria de un proceso se vuelven demasiado grandes, Android
puede terminar ese proceso para liberar recursos para el dispositivo. Si un servicio tiene una superficie de
memoria grande y se está ejecutando en el mismo proceso que la interfaz de usuario, cuando Android
recupere forzosamente esos recursos, se apagará la interfaz de usuario, lo que obliga al usuario a iniciar la
aplicación. Sin embargo, si Android cierra un servicio que se ejecuta en su propio proceso, el proceso de la
interfaz de usuario no se ve afectado. La interfaz de usuario puede enlazar (y reiniciar) el servicio, ser
transparente para el usuario y reanudar el funcionamiento normal.
3. Mejorar el rendimiento de la aplicación – El proceso de la interfaz de usuario puede terminarse o cerrarse
independientemente del proceso de servicio. Al mover tareas de inicio largas a un servicio fuera de proceso,
es posible que el tiempo de inicio de la interfaz de usuario se haya mejorado (suponiendo que el proceso de
servicio se mantenga activo entre las veces que se inicia la interfaz de usuario).
En muchos sentidos, el enlace a un servicio que se ejecuta en otro proceso es el mismo que el enlace a un servicio
local. El cliente invocará BindService para enlazar (e iniciar, si es necesario) el servicio. Se
Android.OS.IServiceConnection creará un objeto para administrar la conexión entre el cliente y el servicio. Si el
cliente se enlaza correctamente al servicio, Android devolverá un objeto a través de IServiceConnection que se
puede usar para invocar métodos en el servicio. A continuación, el cliente interactúa con el servicio que usa este
objeto. Para revisar, estos son los pasos para enlazar a un servicio:
Crear una intención – Un intento explícito debe usarse para enlazar con el servicio.
Implementar y crear una instancia IServiceConnection de un objeto – el IServiceConnection objeto actúa
como intermediario entre el cliente y el servicio. Es responsable de supervisar la conexión entre el cliente y el
servidor.
Invocar BindService la llamada – al método enviará el intento y la conexión de servicio creada en los pasos
anteriores a Android, que se encargará de iniciar el servicio y establecer la comunicación entre BindService
cliente y servicio.
La necesidad de cruzar los límites del proceso conlleva una complejidad adicional: la comunicación es
unidireccional (cliente a servidor) y el cliente no puede invocar directamente métodos en la clase de servicio.
Recuerde que cuando un servicio ejecuta el mismo proceso que el cliente, Android proporciona un IBinder objeto
que puede permitir la comunicación bidireccional. Este no es el caso del servicio que se ejecuta en su propio
proceso. Un cliente se comunica con un servicio remoto con la ayuda de la Android.OS.Messenger clase.
Cuando un cliente solicita enlazar con el servicio remoto, Android invocará el Service.OnBind método de ciclo de
vida, que devolverá el objeto interno IBinder encapsulado Messenger por. Es un contenedor fino sobre una
implementación especial IBinder que proporciona el Android SDK. Messenger El Messenger se encarga de la
comunicación entre los dos procesos diferentes. El desarrollador no se preocupe por los detalles de la serialización
de un mensaje, el cálculo de referencias del mensaje en el límite del proceso y, a continuación, su deserialización en
el cliente. Este trabajo lo controla el Messenger objeto. En este diagrama se muestran los componentes de Android
del lado cliente que intervienen cuando un cliente inicia el enlace a un servicio fuera de proceso:
La Service clase del proceso remoto pasa por las mismas devoluciones de llamada del ciclo de vida que pasa un
servicio enlazado en un proceso local, y muchas de las API implicadas son las mismas. Service.OnCreate se usa
para inicializar Handler una e insertarla Messenger en el objeto. Del mismo OnBind modo, se invalida, pero en
lugar de devolver IBinder un objeto, Messenger el servicio devolverá. En este diagrama se ilustra lo que ocurre en
el servicio cuando un cliente se enlaza a él:
Cuando un Message servicio recibe un, lo procesa en la instancia de. Android.OS.Handler El servicio implementará
su propia Handler subclase que debe reemplazar el HandleMessage método. Este método lo invoca Messenger y
Message recibe como parámetro. Inspeccionará los Message metadatos y usará esa información para invocar
métodos en el servicio. Handler
La comunicación unidireccional se produce cuando un cliente crea un Message objeto y lo envía al servicio
mediante el Messenger.Send método. Messenger.Send serializará Message y hará que los datos serializados se
devuelvan a Android, lo que enrutará el mensaje en el límite del proceso y en el servicio. La Messenger que
hospeda el servicio creará un Message objeto a partir de los datos entrantes. Se coloca en una cola, donde los
mensajes se envían de uno en uno Handler a. Message Inspeccionará los metadatos contenidos Message en e
invocará Service los métodos adecuados en. Handler En el diagrama siguiente se muestran estos diversos
conceptos en acción:

En esta guía se explican los detalles de la implementación de un servicio fuera de proceso. Se explica cómo
implementar un servicio diseñado para ejecutarse en su propio proceso y cómo un cliente puede comunicarse con
ese servicio mediante el marco de Messenger trabajo. También se explica brevemente la comunicación
bidireccional: el cliente que envía un mensaje a un servicio y el servicio envía un mensaje de vuelta al cliente. Dado
que los servicios se pueden compartir entre diferentes aplicaciones, en esta guía también se describe una técnica
para limitar el acceso del cliente al servicio mediante los permisos de Android.

IMPORTANT
Bugzilla 51940/GitHub 1950-Services con procesos aislados y clase de aplicación personalizada no se pueden resolver
sobrecargas correctamente informa de que un servicio Xamarin. Android no se iniciará IsolatedProcess correctamente
cuando se true establece en. Esta guía se proporciona para una referencia. Una aplicación de Xamarin. Android todavía debe
ser capaz de comunicarse con un servicio fuera de proceso escrito en Java.

Requisitos
En esta guía se da por supuesto que está familiarizado con la creación de servicios.
Aunque es posible usar las intenciones implícitas con las aplicaciones destinadas a las API de Android anteriores,
esta guía se centrará exclusivamente en el uso de las intenciones explícitas. Las aplicaciones que tienen como
destino Android 5,0 (nivel de API 21) o superior deben usar una intención explícita para enlazar con un servicio;
Esta es la técnica que se mostrará en esta guía.

Crear un servicio que se ejecute en un proceso independiente


Tal y como se ha descrito anteriormente, el hecho de que un servicio se ejecute en su propio proceso significa que
se implican algunas API diferentes. Como introducción rápida, estos son los pasos para enlazar y consumir un
servicio remoto:
Cree la Service subclase de subclase Service – del tipo e implemente los métodos de ciclo de vida para un
servicio enlazado. También es necesario establecer los metadatos que informarán a Android de que el servicio
debe ejecutarse en su propio proceso.
Implementar un Handler esresponsablede Handler analizar las solicitudes de cliente, extraer los parámetros
que se pasaron del cliente e invocar los métodos adecuados en el servicio. –
Cree Messenger una Handler Messenger Service instancia de como se describió anteriormente, cada una de
las cuales debe mantener una instancia de la clase que enrute las solicitudes de cliente a la que se creó en el
paso anterior. –
Un servicio diseñado para ejecutarse en su propio proceso es, fundamentalmente, un servicio enlazado. La clase de
servicio extenderá la Service clase base y se decorará ServiceAttribute con el que contiene los metadatos que
Android necesita agrupar en el manifiesto de Android. Para empezar, las siguientes propiedades de los
ServiceAttribute elementos que son importantes para un servicio fuera de proceso:

1. Exported Esta propiedad debe establecerse en true para permitir que otras aplicaciones interactúen con el
servicio. – El valor predeterminado de esta propiedad es false .
2. Process – Esta propiedad debe establecerse. Se utiliza para especificar el nombre del proceso en el que se
ejecutará el servicio.
3. IsolatedProcess – Esta propiedad habilitará la seguridad adicional, lo que indica a Android que ejecute el
servicio en un espacio aislado aislado con el permiso mínimo para interactuar con el resto del sistema. Consulte
Bugzilla 51940-Services con procesos aislados y clase de aplicación personalizada no se pueden resolver
sobrecargas correctamente.
4. Permission – Es posible controlar el acceso del cliente al servicio mediante la especificación de un permiso que
los clientes deben solicitar (y se les debe conceder).
Para ejecutar un servicio de su propio proceso, Process la propiedad ServiceAttribute de se debe establecer en el
nombre del servicio. Para interactuar con las aplicaciones externas, Exported la propiedad debe establecerse true
en. Si Exported es false , solo los clientes del mismo APK (es decir, la misma aplicación) y que se ejecutan en el
mismo proceso podrán interactuar con el servicio.
El tipo de proceso en el que se ejecutará el servicio dependerá del Process valor de la propiedad. Android
identifica tres tipos diferentes de procesos:
Proceso privado – Un proceso privado es aquél que solo está disponible para la aplicación que lo inició.
Para identificar un proceso como privado, su nombre debe comenzar con un : (punto y coma). El servicio
que se muestra en el fragmento de código anterior y captura de pantalla es un proceso privado. El siguiente
fragmento de código es un ejemplo de ServiceAttribute :

[Service(Name = "com.xamarin.TimestampService",
Process=":timestampservice_process",
Exported=true)]

Proceso global – Un servicio que se ejecuta en un proceso global es accesible para todas las aplicaciones
que se ejecutan en el dispositivo. Un proceso global debe ser un nombre de clase completo que comienza
con un carácter en minúscula. (A menos que se realicen los pasos para proteger el servicio, otras
aplicaciones pueden enlazarse e interactuar con él. La protección del servicio contra el uso no autorizado se
tratará más adelante en esta guía).
[Service(Name = "com.xamarin.TimestampService",
Process="com.xamarin.xample.messengerservice.timestampservice_process",
Exported=true)]

Proceso aislado – Un proceso aislado es un proceso que se ejecuta en su propio espacio aislado, aislado
del resto del sistema y sin permisos especiales propios. Para ejecutar un servicio en un proceso aislado, la
IsolatedProcess propiedad ServiceAttribute de se establece en true como se muestra en este fragmento
de código:

[Service(Name = "com.xamarin.TimestampService",
IsolatedProcess= true,
Process="com.xamarin.xample.messengerservice.timestampservice_process",
Exported=true)]

IMPORTANT
Consulte Bugzilla 51940-Services con procesos aislados y clase de aplicación personalizada no se pueden resolver sobrecargas
correctamente

Un servicio aislado es una forma sencilla de proteger una aplicación y el dispositivo frente a código que no es de
confianza. Por ejemplo, una aplicación puede descargar y ejecutar un script desde un sitio Web. En este caso,
realizar esta operación en un proceso aislado proporciona una capa adicional de seguridad frente a código que no
es de confianza y que pone en peligro el dispositivo Android.

IMPORTANT
Una vez que se ha exportado un servicio, el nombre del servicio no debe cambiar. Si se cambia el nombre del servicio, es
posible que se interrumpan otras aplicaciones que usan el servicio.

Para ver el efecto que tiene Process la propiedad, en la captura de pantalla siguiente se muestra un servicio que se
ejecuta en su propio proceso privado:

En esta captura de Process="com.xamarin.xample.messengerservice.timestampservice_process" pantalla siguiente se


muestra y el servicio que se ejecuta en un proceso global:
Una vez que se ha establecido, el servicio debe implementar un Handler . ServiceAttribute

Implementar un controlador
Para procesar las solicitudes de cliente, el servicio debe Handler implementar un y HandleMessage reemplazar el
methodThis es el método Message toma una instancia de que encapsula la llamada al método desde el cliente y
traduce esa llamada en alguna acción o tarea. que el servicio realizará. El Message objeto expone una propiedad
denominada What que es un valor entero, cuyo significado se comparte entre el cliente y el servicio y se relaciona
con alguna tarea que el servicio debe realizar para el cliente.
En el siguiente fragmento de código de la aplicación de ejemplo se HandleMessage muestra un ejemplo de. En este
ejemplo, hay dos acciones que un cliente puede solicitar al servicio:
La primera acción es un mensaje Hello, World , el cliente ha enviado un mensaje simple al servicio.
La segunda acción invocará un método en el servicio y recuperará una cadena; en este caso, la cadena es un
mensaje que devuelve la hora a la que se inició el servicio y cuánto tiempo se ha estado ejecutando:
public class TimestampRequestHandler : Android.OS.Handler
{
// other code omitted for clarity

public override void HandleMessage(Message msg)


{
int messageType = msg.What;
Log.Debug(TAG, $"Message type: {messageType}.");

switch (messageType)
{
case Constants.SAY_HELLO_TO_TIMESTAMP_SERVICE:
// The client as sent a simple Hello, say in the Android Log.
break;

case Constants.GET_UTC_TIMESTAMP:
// Call methods on the service to retrieve a timestamp message.
break;
default:
Log.Warn(TAG, $"Unknown messageType, ignoring the value {messageType}.");
base.HandleMessage(msg);
break;
}
}
}

También es posible empaquetar los parámetros del servicio en Message . Esto se tratará más adelante en esta guía.
El siguiente tema a tener en cuenta es Messenger crear el objeto para procesar Message los elementos entrantes.
Creación de instancias de Messenger
Como Message seexplicó Handler.HandleMessage anteriormente, la deserialización del objeto y la invocación es
responsabilidad del objeto. Messenger La Messenger clase también proporciona un IBinder objeto que el cliente
utilizará para enviar mensajes al servicio.
Cuando se inicia el servicio, se crea una instancia Messenger del e Handler inserta. Un buen lugar para realizar esta
inicialización es en OnCreate el método del servicio. Este fragmento de código es un ejemplo de un servicio que
inicializa su propio Handler y Messenger :

private Messenger messenger; // Instance variable for the Messenger

public override void OnCreate()


{
base.OnCreate();
messenger = new Messenger(new TimestampRequestHandler(this));
Log.Info(TAG, $"TimestampService is running in process id {Android.OS.Process.MyPid()}.");
}

En este punto, el último paso es que el Service se invalide. OnBind

Implementación de Service. DataBind


Todos los servicios enlazados, tanto si se ejecutan en su propio proceso como si OnBind no, deben implementar el
método. El valor devuelto de este método es algún objeto que el cliente puede utilizar para interactuar con el
servicio. Exactamente el objeto depende de si el servicio es un servicio local o remoto. Aunque un servicio local
devolverá una IBinder implementación personalizada, un servicio remoto devolverá el IBinder que está
encapsulado Messenger pero el que se creó en la sección anterior:
public override IBinder OnBind(Intent intent)
{
Log.Debug(TAG, "OnBind");
return messenger.Binder;
}

Una vez que se hayan realizado estos tres pasos, el servicio remoto se puede considerar completo.

Consumir el servicio
Todos los clientes deben implementar código para poder enlazar y consumir el servicio remoto. Conceptualmente,
desde el punto de vista del cliente, hay muy pocas diferencias entre el enlace con el servicio local o un servicio
remoto. El cliente invoca el BindService método, pasando un intento explícito para identificar el servicio y un
IServiceConnection que ayuda a administrar la conexión entre el cliente y el servicio.

Este fragmento de código es un ejemplo de cómo crear un intento explícito de enlazar a un servicio remoto. La
intención debe identificar el paquete que contiene el servicio y el nombre del servicio. Una manera de establecer
esta información es usar un Android.Content.ComponentName objeto y proporcionarlo a la intención. Este fragmento
de código es un ejemplo:

// This is the package name of the APK, set in the Android manifest
const string REMOTE_SERVICE_COMPONENT_NAME = "com.xamarin.TimestampService";
// This is the name of the service, according the value of ServiceAttribute.Name
const string REMOTE_SERVICE_PACKAGE_NAME = "com.xamarin.xample.messengerservice";

// Provide the package name and the name of the service with a ComponentName object.
ComponentName cn = new ComponentName(REMOTE_SERVICE_PACKAGE_NAME, REMOTE_SERVICE_COMPONENT_NAME);
Intent serviceToStart = new Intent();
serviceToStart.SetComponent(cn);

Cuando se enlaza el servicio, se IServiceConnection.OnServiceConnected invoca el método y IBinder proporciona a


un cliente. Sin embargo, el cliente no usará directamente el IBinder . En su lugar, creará una instancia Messenger
de un objeto IBinder a partir de ese. Este es el Messenger que el cliente usará para interactuar con el servicio
remoto.
El siguiente es un ejemplo de una implementación muy IServiceConnection básica que muestra cómo un cliente
administraría la conexión y la desconexión de un servicio. Observe que el OnServiceConnected método recibe y
IBinder , y el IBinder cliente crea un Messenger a partir de lo siguiente:
public class TimestampServiceConnection : Java.Lang.Object, IServiceConnection
{
static readonly string TAG = typeof(TimestampServiceConnection).FullName;

MainActivity mainActivity;
Messenger messenger;

public TimestampServiceConnection(MainActivity activity)


{
IsConnected = false;
mainActivity = activity;
}

public bool IsConnected { get; private set; }


public Messenger Messenger { get; private set; }

public void OnServiceConnected(ComponentName name, IBinder service)


{
Log.Debug(TAG, $"OnServiceConnected {name.ClassName}");

IsConnected = service != null


Messenger = new Messenger(service);

if (IsConnected)
{
// things to do when the connection is successful. perhaps notify the client? enable UI features?
}
else
{
// things to do when the connection isn't successful.
}
}

public void OnServiceDisconnected(ComponentName name)


{
Log.Debug(TAG, $"OnServiceDisconnected {name.ClassName}");
IsConnected = false;
Messenger = null;

// Things to do when the service disconnects. perhaps notify the client? disable UI features?

}
}

Una vez que se crea la conexión de servicio y el intento, es posible que el cliente BindService llame a e inicie el
proceso de enlace:

IServiceConnection serviceConnection = new TimestampServiceConnection(this);


BindActivity(serviceToStart, serviceConnection, Bind.AutoCreate);

Una vez que el cliente se ha enlazado correctamente al Messenger servicio y está disponible, es posible que el
cliente pueda Messages enviar al servicio.

Envío de mensajes al servicio


Una vez que el cliente está conectado y Messenger tiene un objeto, es posible comunicarse con el servicio mediante
el Message envío de objetos a través Messenger de. Esta comunicación es unidireccional, el cliente envía el mensaje,
pero no se devuelve ningún mensaje del servicio al cliente. En este sentido, Message es un mecanismo de incendio
y olvidar.
La manera preferida de crear Message un objeto es usar el Message.Obtain Factory Method. Este método extraerá
Message un objeto de un grupo global mantenido por Android. Message.Obtain también tiene algunos métodos
sobrecargados que permiten inicializar el Message objeto con los valores y parámetros requeridos por el servicio.
Una vez Message que se crea una instancia de, se envía al servicio mediante una Messenger.Send llamada a. Este
fragmento de código es un ejemplo de creación y distribución de Message un al proceso de servicio:

Message msg = Message.Obtain(null, Constants.SAY_HELLO_TO_TIMESTAMP_SERVICE);


try
{
serviceConnection.Messenger.Send(msg);
}
catch (RemoteException ex)
{
Log.Error(TAG, ex, "There was a error trying to send the message.");
}

Hay varias formas diferentes del Message.Obtainmétodo. En el ejemplo anterior se


Message.Obtain(Handler h, Int32 what) usa. Dado que se trata de una solicitud asincrónica a un servicio fuera de
proceso; no habrá respuesta del servicio, por lo que Handler se establece en. null El segundo parámetro,
Int32 what , se almacenará en la .What propiedad del Message objeto. El .What código del proceso de servicio
utiliza la propiedad para invocar métodos en el servicio.
La Message clase también expone dos propiedades adicionales que pueden ser de uso para el destinatario: Arg1 y
Arg2 . Estas dos propiedades son valores enteros que pueden tener algunos valores especiales acordados que
tienen un significado entre el cliente y el servicio. Por ejemplo, Arg1 puede contener un identificador de cliente
Arg2 y puede contener un número de pedido de compra para ese cliente. Se puede utilizar para establecer las dos
propiedades Message cuando se crea. Method.Obtain(Handler h, Int32 what, Int32 arg1, Int32 arg2) Otra manera
de rellenar estos dos valores es establecer .Arg las .Arg2 propiedades y directamente en Message el objeto
después de que se haya creado.
Pasar valores adicionales al servicio
Es posible pasar datos más complejos al servicio Bundle mediante. En este caso, se pueden colocar valores
adicionales en Bundle y enviarlos junto con el Message estableciendo la propiedad de .Data propiedad antes de
enviar.

Bundle serviceParameters = new Bundle();


serviceParameters.

var msg = Message.Obtain(null, Constants.SERVICE_TASK_TO_PERFORM);


msg.Data = serviceParameters;

messenger.Send(msg);

NOTE
En general, un Message no debe tener una carga superior a 1 MB. El límite de tamaño puede variar en función de la versión
de Android y de cualquier cambio de propietario que el proveedor pueda haber realizado en su implementación del proyecto
de código abierto de Android (AOSP) que se incluye con el dispositivo.

Devolver valores del servicio


La arquitectura de mensajería que se ha explicado en este punto es unidireccional, el cliente envía un mensaje al
servicio. Si es necesario que el servicio devuelva un valor a un cliente, se invierte todo lo que se ha analizado hasta
este punto. El servicio debe crear Message , empaquetar todos los valores devueltos y enviar el Message mediante
Messenger un al cliente. Sin embargo, el servicio no crea su propio Messenger elemento; en su lugar, se basa en el
cliente que crea instancias y Messenger empaqueta como como parte de la solicitud inicial. El servicio enviará
Send el mensaje mediante este proporcionado Messenger por el cliente.

La secuencia de eventos para la comunicación bidireccional es la siguiente:


1. El cliente se enlaza al servicio. Cuando el servicio y el cliente se conectan IServiceConnection , el que mantiene
el cliente tendrá una referencia a un Messenger objeto que se utiliza para transmitir Message s al servicio. Para
evitar confusiones, se hará referencia a este servicio como Messenger.
2. El cliente crea instancias Handler de un (denominado controlador de cliente) y lo usa para inicializar el
Messenger suyo propio (el cliente Messenger). Tenga en cuenta que el servicio Messenger y el cliente
Messenger son dos objetos diferentes que controlan el tráfico en dos direcciones diferentes. El servicio
Messenger controla los mensajes del cliente al servicio, mientras que el cliente Messenger controlará los
mensajes desde el servicio al cliente.
3. El cliente crea un Message objeto y establece la ReplyTo propiedad con el cliente Messenger. A continuación, el
mensaje se envía al servicio mediante el servicio Messenger.
4. El servicio recibe el mensaje del cliente y realiza el trabajo solicitado.
5. Cuando es el momento de que el servicio envíe la respuesta al cliente, Message.Obtain usará para crear un
nuevo Message objeto.
6. Para enviar este mensaje al cliente, el servicio extrae el Messenger del cliente de la .ReplyTo propiedad del
mensaje de cliente y lo utilizará .Send Message para volver al cliente.
7. Cuando el cliente recibe la respuesta Handler , tiene su propio que procesará la Message inspección de la
.What propiedad (y Message , si es necesario, extraerá los parámetros que contiene).

En este código de ejemplo se muestra cómo el cliente creará una instancia Messenger del Message paquete y un
que el servicio debe usar para su respuesta:

Handler clientHandler = new ActivityHandler();


Messenger clientMessenger = new Messenger(activityHandler);

Message msg = Message.Obtain(null, Constants.GET_UTC_TIMESTAMP);


msg.ReplyTo = clientMessenger;

try
{
serviceConnection.Messenger.Send(msg);
}
catch (RemoteException ex)
{
Log.Error(TAG, ex, "There was a problem sending the message.");
}

El servicio debe realizar algunos cambios en su propio Handler para Messenger extraer y usarlo para enviar
respuestas al cliente. Este fragmento de código es un ejemplo de cómo el del Handler servicio crearía Message un
y lo devolvería al cliente:
// This is the message that the service will send to the client.
Message responseMessage = Message.Obtain(null, Constants.RESPONSE_TO_SERVICE);
Bundle dataToReturn = new Bundle();
dataToReturn.PutString(Constants.RESPONSE_MESSAGE_KEY, "This is the result from the service.");
responseMessage.Data = dataToReturn;

// The msg object here is the message that was received by the service. The service will not instantiate a
client,
// It will use the client that is encapsulated by the message from the client.
Messenger clientMessenger = msg.ReplyTo;
if (clientMessenger!= null)
{
try
{
clientMessenger.Send(responseMessage);
}
catch (Exception ex)
{
Log.Error(TAG, ex, "There was a problem sending the message.");
}
}

Tenga en cuenta que en los ejemplos de código Messenger anteriores, la instancia creada por el cliente no es el
mismo objeto que recibe el servicio. Se trata de dos Messenger objetos diferentes que se ejecutan en dos procesos
independientes que representan el canal de comunicación.

Protección del servicio con permisos de Android


Un servicio que se ejecuta en un proceso global es accesible para todas las aplicaciones que se ejecutan en ese
dispositivo Android. En algunas situaciones, esta apertura y disponibilidad no son deseables y es necesario
proteger el servicio contra el acceso desde clientes no autorizados. Una manera de limitar el acceso al servicio
remoto es usar permisos de Android.
Los permisos se pueden identificar mediante Permission la propiedad ServiceAttribute de que decora la
Service subclase. Esto asignará un nombre a un permiso que se debe conceder al cliente al enlazar con el servicio.
Si el cliente no tiene los permisos adecuados, Android producirá una Java.Lang.SecurityException excepción
cuando el cliente intente enlazar con el servicio.
Hay cuatro niveles de permisos diferentes que Android proporciona:
normal – Este es el nivel de permisos predeterminado. Se usa para identificar los permisos de bajo riesgo que
Android puede conceder automáticamente a los clientes que lo soliciten. El usuario no tiene que conceder
explícitamente estos permisos, pero los permisos se pueden ver en la configuración de la aplicación.
firma de – Se trata de una categoría especial de permiso que Android concederá automáticamente a las
aplicaciones que estén firmadas con el mismo certificado. Este permiso se ha diseñado para facilitar a los
desarrolladores de aplicaciones el uso compartido de componentes o datos entre sus aplicaciones sin molestar
al usuario en las aprobaciones de constantes.
signatureOrSystem Esto es muy similar a los permisos de firma descritos anteriormente. – Además de
concederse automáticamente a las aplicaciones firmadas con el mismo certificado, este permiso también se
concederá a las aplicaciones que estén firmadas con el mismo certificado que se usó para firmar las aplicaciones
instaladas con la imagen del sistema Android. Normalmente, los desarrolladores de Android ROM usan este
permiso para permitir que sus aplicaciones funcionen con aplicaciones de terceros. Normalmente, no lo usan las
aplicaciones que están diseñadas para la distribución general para el público en gran medida.
peligrosa – Los permisos peligrosos son aquellos que podrían causar problemas al usuario. Por esta razón, los
permisos peligrosos deben ser aprobados explícitamente por el usuario.
Como signature los normal permisos y se conceden automáticamente en el momento de instalación de Android,
es fundamental que apk que hospeda el servicio se instale antes que el APK que contiene el cliente. Si el cliente se
instala en primer lugar, Android no concederá los permisos. En este caso, será necesario desinstalar el cliente APK,
instalar el servicio APK y, a continuación, volver a instalar el cliente APK.
Hay dos maneras comunes de proteger un servicio con permisos de Android:
1. Implementar la seguridad de nivel de firma – La seguridad de nivel de firma significa que el permiso se
concede automáticamente a las aplicaciones firmadas con la misma clave que se usó para firmar el APK que
contiene el servicio. Esta es una manera sencilla para que los desarrolladores protejan su servicio, pero que
los mantienen accesibles desde sus propias aplicaciones. Los permisos Permission signature de nivel de
firma se declaran estableciendo la propiedad de en: ServiceAttribute

[Service(Name = "com.xamarin.TimestampService",
Process="com.xamarin.TimestampService.timestampservice_process",
Permission="signature")]
public class TimestampService : Service
{
}

2. Crear un permiso personalizado – Es posible que el desarrollador del servicio cree un permiso
personalizado para el servicio. Esta es la mejor opción cuando un desarrollador desea compartir su servicio
con aplicaciones de otros desarrolladores. Un permiso personalizado requiere un poco más de esfuerzo para
implementar y se tratará a continuación.
En la sección siguiente se describe un normal ejemplo simplificado de la creación de un permiso personalizado.
Para obtener más información sobre los permisos de Android, consulte la documentación de Google para ver los
procedimientos recomendados & seguridad. Para obtener más información sobre los permisos de Android,
consulte la sección permisos de la documentación de Android del manifiesto de aplicación para obtener más
información sobre los permisos de Android.

NOTE
En general, Google desaconseja el uso de permisos personalizados , ya que pueden resultar confusos para los usuarios.

Crear un permiso personalizado


Para utilizar un permiso personalizado, el servicio lo declara mientras el cliente solicita explícitamente ese permiso.
Para crear un permiso en el servicio apk, se permission agrega un elemento manifest al elemento en archivo
AndroidManifest. XML. Este permiso debe tener establecidos name los protectionLevel atributos, label y. El
name atributo debe establecerse en una cadena que identifique de forma única el permiso. El nombre se mostrará
en la vista información de la aplicación de la configuración de Android (como se muestra en la sección
siguiente).
El atributo debe establecerse en uno de los cuatro valores de cadena descritos anteriormente.
protectionLevel
label Y description deben hacer referencia a los recursos de cadena y se usan para proporcionar un nombre
descriptivo y una descripción al usuario.
Este fragmento de código es un ejemplo de declaración de permission un atributo personalizado en archivo
AndroidManifest. XML de la apk que contiene el servicio:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1"
android:versionName="1.0"
package="com.xamarin.xample.messengerservice">

<uses-sdk android:minSdkVersion="21" />

<permission android:name="com.xamarin.xample.messengerservice.REQUEST_TIMESTAMP"
android:protectionLevel="signature"
android:label="@string/permission_label"
android:description="@string/permission_description"
/>

<application android:allowBackup="true"
android:icon="@mipmap/icon"
android:label="@string/app_name"
android:theme="@style/AppTheme">

</application>
</manifest>

A continuación, el archivo AndroidManifest. XML del cliente apk debe solicitar explícitamente este nuevo
permiso. Esto se hace agregando el users-permission atributo a archivo AndroidManifest. XML:

<?xml version="1.0" encoding="utf-8"?>


<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1"
android:versionName="1.0"
package="com.xamarin.xample.messengerclient">

<uses-sdk android:minSdkVersion="21" />

<uses-permission android:name="com.xamarin.xample.messengerservice.REQUEST_TIMESTAMP" />

<application
android:allowBackup="true"
android:icon="@mipmap/icon"
android:label="@string/app_name"
android:theme="@style/AppTheme">
</application>
</manifest>

Ver los permisos concedidos a una aplicación


Para ver los permisos que se han concedido a una aplicación, abra la aplicación de configuración de Android y
seleccione aplicaciones. Busque y seleccione la aplicación en la lista. En la pantalla de información de la
aplicación , pulse permisos que mostrarán una vista que muestra todos los permisos concedidos a la aplicación:
Resumen
En esta guía se ha realizado un debate avanzado sobre cómo ejecutar un servicio Android en un proceso remoto.
Se han explicado las diferencias entre un servicio local y otro remoto, junto con algunos motivos por los que un
servicio remoto puede ser útil para la estabilidad y el rendimiento de una aplicación de Android. Después de
explicar cómo implementar un servicio remoto y cómo un cliente puede comunicarse con el servicio, la guía pasó a
proporcionar una manera de limitar el acceso al servicio únicamente desde clientes autorizados.

Vínculos relacionados
Controlador
Mensaje
Alerta
ServiceAttribute
El atributo exportado
Los servicios con procesos aislados y la clase de aplicación personalizada no pueden resolver sobrecargas
correctamente
Procesos y subprocesos
Manifiesto de Android: permisos
Sugerencias de seguridad
MessengerServiceDemo (ejemplo)
Notificaciones del servicio
11/07/2019 • 2 minutes to read • Edit Online

Esta guía describe cómo un servicio de Android puede usar notificaciones locales para enviar información a un
usuario.

Información general de las notificaciones del servicio


Las notificaciones del servicio, permitir que una aplicación mostrar información al usuario, incluso si la aplicación
de Android no está en primer plano. Es posible que una notificación proporcionar acciones del usuario, como
mostrar una actividad desde una aplicación. Ejemplo de código siguiente muestra cómo un servicio podría enviar
una notificación a un usuario:

[Service]
public class MyService: Service
{
// A notification requires an id that is unique to the application.
const int NOTIFICATION_ID = 9000;

public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)


{
// Code omitted for clarity - here is where the service would do something.

// Work has finished, now dispatch anotification to let the user know.
Notification.Builder notificationBuilder = new Notification.Builder(this)
.SetSmallIcon(Resource.Drawable.ic_notification_small_icon)
.SetContentTitle(Resources.GetString(Resource.String.notification_content_title))
.SetContentText(Resources.GetString(Resource.String.notification_content_text));

var notificationManager = (NotificationManager)GetSystemService(NotificationService);


notificationManager.Notify(NOTIFICATION_ID, notificationBuilder.Build());
}
}

Esta captura de pantalla es un ejemplo de la notificación de que se muestra:

Cuando las diapositivas de usuario hacia abajo de la pantalla de notificación en la parte superior, se muestra la
notificación completa:
Actualización de una notificación
Para actualizar una notificación, el servicio se volverá a publicar la notificación usando el mismo identificador de
notificación. Android mostrará o actualizar la notificación en la barra de estado según sea necesario.
void UpdateNotification(string content)
{
var notification = GetNotification(content, pendingIntent);

NotificationManager notificationManager =
(NotificationManager)GetSystemService(Context.NotificationService);
notificationManager.Notify(NOTIFICATION_ID, notification);
}

Notification GetNotification(string content, PendingIntent intent)


{
return new Notification.Builder(this)
.SetContentTitle(tag)
.SetContentText(content)
.SetSmallIcon(Resource.Drawable.NotifyLg)
.SetLargeIcon(BitmapFactory.DecodeResource(Resources, Resource.Drawable.Icon))
.SetContentIntent(intent).Build();
}

Para obtener más información acerca de las notificaciones está disponible en el notificaciones locales sección de la
notificaciones Android guía.

Vínculos relacionados
Notificaciones locales en Android
Receptores de difusión en Xamarin. Android
27/07/2019 • 15 minutes to read • Edit Online

En esta sección se describe cómo usar un receptor de difusión.

Información general del receptor de difusión


Un receptor de difusión es un componente de Android que permite a una aplicación responder a mensajes (
Intent un Android) que difunde el sistema operativo Android o una aplicación. Las difusiones siguen un modelo
– de publicación y suscripción . un evento hace que se publique una difusión y la reciban los componentes
interesados en el evento.
Android identifica dos tipos de difusiones:
Difusión explícita – Estos tipos de difusiones se dirigen a una aplicación específica. El uso más común de una
difusión explícita es iniciar una actividad. Un ejemplo de una difusión explícita cuando una aplicación necesita
marcar un número de teléfono. se enviará un intento dirigido a la aplicación de teléfono en Android y pasará
por el número de teléfono que se va a marcar. Después, Android enrutará el intento a la aplicación de teléfono.
Difusión implícita – Estas difusiones se envían a todas las aplicaciones del dispositivo. Un ejemplo de una
difusión implícita es la ACTION_POWER_CONNECTED intención. Esta intención se publica cada vez que Android
detecta que la batería del dispositivo se está cargando. Android enrutará esta intención a todas las aplicaciones
que se hayan registrado para este evento.
El receptor de difusión es una subclase del BroadcastReceiver tipo y debe reemplazar el OnReceive método.
Android se ejecutará OnReceive en el subproceso principal, por lo que este método debe diseñarse para
ejecutarse rápidamente. Se debe tener cuidado al generar subprocesos OnReceive en porque Android puede
terminar el proceso cuando el método finaliza. Si un receptor de difusión debe realizar un trabajo de larga
ejecución, se recomienda programar un trabajo mediante JobScheduler el o el distribuidor de trabajo de Firebase.
La programación del trabajo con un trabajo se tratará en una guía independiente.
Un filtro de intención se usa para registrar un receptor de difusión para que Android pueda enrutar los mensajes
correctamente. El filtro de intención se puede especificar en tiempo de ejecución (esto se conoce a veces como
receptor registrado en el contexto o como registro dinámico) o se puede definir de forma estática en el manifiesto
de Android (un receptor registrado con el manifiesto). Xamarin. Android proporciona un C# atributo,
IntentFilterAttribute , que registrará de forma estática el filtro de intención (esto se tratará con más detalle más
adelante en esta guía). A partir de Android 8,0, no es posible que una aplicación se registre estáticamente para una
difusión implícita.
La principal diferencia entre el receptor registrado en el manifiesto y el receptor registrado por el contexto es que
un receptor registrado en el contexto solo responderá a las difusiones mientras se ejecuta una aplicación, mientras
que un receptor registrado en el manifiesto puede responder a se difunde aunque es posible que la aplicación no
se esté ejecutando.
Existen dos conjuntos de API para administrar un receptor de difusión y enviar difusiones:
1. Context – La Android.Content.Context clase se puede utilizar para registrar un receptor de difusión que
responderá a los eventos de todo el sistema. También Context se usa para publicar difusiones en todo el
sistema.
2. LocalBroadcastManager Se trata de una API que está disponible a través del paquete NuGet de la biblioteca de
compatibilidad de Xamarin V4. – Esta clase se usa para mantener las difusiones y los receptores de difusión
aislados en el contexto de la aplicación que los utiliza. Esta clase puede ser útil para evitar que otras
aplicaciones respondan a difusiones solo de la aplicación o envíen mensajes a receptores privados.
Un receptor de difusión no puede mostrar cuadros de diálogo y no se recomienda iniciar una actividad desde
dentro de un receptor de difusión. Si un receptor de difusión debe notificar al usuario, debe publicar una
notificación.
No es posible enlazar o iniciar un servicio desde un receptor de difusión.
En esta guía se explica cómo crear un receptor de difusión y cómo registrarlo para que pueda recibir difusiones.

Creación de un receptor de difusión


Para crear un receptor de difusión en Xamarin. Android, una aplicación debe crear una BroadcastReceiver
subclase de la clase, BroadcastReceiverAttribute adornarla con y OnReceive reemplazar el método:

[BroadcastReceiver(Enabled = true, Exported = false)]


public class SampleReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
// Do stuff here.

String value = intent.GetStringExtra("key");


}
}

Cuando Xamarin. Android compila la clase, también actualizará archivo AndroidManifest con los metadatos
necesarios para registrar el receptor. Para un receptor de difusión registrado estáticamente, el Enabled valor de
debe establecerse true en, de lo contrario, Android no podrá crear una instancia del receptor.
La Exported propiedad controla si el receptor de difusión puede recibir mensajes desde fuera de la aplicación. Si
la propiedad no se establece explícitamente, Android determina el valor predeterminado de la propiedad
basándose en si hay algún filtro de intención asociado al receptor de difusión. Si hay al menos un filtro de
intención para el receptor de difusión, Android asumirá que la Exported propiedad es true . Si no hay ningún
filtro de intención asociado al receptor de difusión, Android asumirá que el valor es false .
El OnReceive método recibe una referencia Intent al que se envió al receptor de difusión. Esto hace posible que
el remitente de la intención pase valores al receptor de difusión.
Registrar estáticamente un receptor de difusión con un filtro de intención
Cuando se decora IntentFilterAttribute con, Xamarin. Android agregará el elemento necesario <intent-filter>
al manifiesto de Android en tiempo de compilación. BroadcastReceiver El siguiente fragmento de código es un
ejemplo de receptor de difusión que se ejecutará cuando un dispositivo haya terminado de arrancar (si el usuario
ha concedido los permisos de Android correspondientes):

[BroadcastReceiver(Enabled = true)]
[IntentFilter(new[] { Android.Content.Intent.ActionBootCompleted })]
public class MyBootReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
// Work that should be done when the device boots.
}
}

También es posible crear un filtro de intención que responderá a las intenciones personalizadas. Considere el
ejemplo siguiente:
[BroadcastReceiver(Enabled = true)]
[IntentFilter(new[] { "com.xamarin.example.TEST" })]
public class MySampleBroadcastReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
// Do stuff here
}
}

Es posible que las aplicaciones destinadas a Android 8,0 (nivel de API 26) o posterior no se registren
estáticamente para una difusión implícita. Las aplicaciones todavía se pueden registrar estáticamente para una
difusión explícita. Hay una pequeña lista de difusiones implícitas que están exentas de esta restricción. Estas
excepciones se describen en la guía de excepciones de difusión implícita en la documentación de Android. Las
aplicaciones que están interesadas en difusiones implícitas deben hacerlo dinámicamente mediante el
RegisterReceiver método. Esto se describe a continuación.

Contexto: registro de un receptor de difusión


El registro de contexto (también denominado registro dinámico) de un receptor se realiza invocando el
RegisterReceiver método y se debe anular el registro del receptor de difusión con una llamada
UnregisterReceiver al método. Para evitar la pérdida de recursos, es importante anular el registro del receptor
cuando ya no es relevante para el contexto (la actividad o servicio). Por ejemplo, un servicio puede difundir un
intento de informar a una actividad de que las actualizaciones están disponibles para que se muestren al usuario.
Cuando se inicia la actividad, se registra en esas intenciones. Cuando la actividad se mueve al fondo y ya no es
visible para el usuario, debe anular el registro del receptor porque la interfaz de usuario para mostrar las
actualizaciones ya no está visible. El siguiente fragmento de código es un ejemplo de cómo registrar y anular el
registro de un receptor de difusión en el contexto de una actividad:

[Activity(Label = "MainActivity", MainLauncher = true, Icon = "@mipmap/icon")]


public class MainActivity: Activity
{
MySampleBroadcastReceiver receiver;

protected override void OnCreate(Bundle savedInstanceState)


{
base.OnCreate(savedInstanceState);
receiver = new MySampleBroadcastReceiver()

// Code omitted for clarity


}

protected override OnResume()


{
base.OnResume();
RegisterReceiver(receiver, new IntentFilter("com.xamarin.example.TEST"));
// Code omitted for clarity
}

protected override OnPause()


{
UnregisterReceiver(receiver);
// Code omitted for clarity
base.OnPause();
}
}

En el ejemplo anterior, cuando la actividad entra en primer plano, registrará un receptor de difusión que escuchará
una intención personalizada mediante el método de OnResume ciclo de vida. A medida que la actividad se mueve al
fondo OnPause() , el método anulará el registro del receptor.
Publicar una difusión
Una difusión puede publicarse en todas las aplicaciones instaladas en el dispositivo creando un objeto de
intención y enviándola con SendBroadcast el SendOrderedBroadcast método o.
1. Métodos context. SendBroadcast – Hay varias implementaciones de este método. Estos métodos
difundirán la intención a todo el sistema. Receptores de difusión que recibirán el intento en un orden
indeterminado. Esto proporciona una gran flexibilidad, pero significa que es posible que otras aplicaciones
se registren y reciban la intención. Esto puede suponer un riesgo de seguridad potencial. Es posible que las
aplicaciones necesiten implementar la seguridad adicional para evitar el acceso no autorizado. Una posible
solución es usar LocalBroadcastManager , que solo enviará mensajes dentro del espacio privado de la
aplicación. Este fragmento de código es un ejemplo de cómo enviar una intención con uno de los
SendBroadcast métodos:

Intent message = new Intent("com.xamarin.example.TEST");


// If desired, pass some values to the broadcast receiver.
message.PutExtra("key", "value");
SendBroadcast(message);

Este fragmento de código es otro ejemplo de envío de una difusión Intent.SetAction mediante el método
para identificar la acción:

Intent intent = new Intent();


intent.SetAction("com.xamarin.example.TEST");
intent.PutExtra("key", "value");
SendBroadcast(intent);

2. Context. SendOrderedBroadcast – este método es muy similar a Context.SendBroadcast , con la


diferencia de que la intención se publicará una vez a los receptores, en el orden en que se registraron los
receptores.
LocalBroadcastManager
La biblioteca de compatibilidad con Xamarin V4 proporciona una clase auxiliar LocalBroadcastManager
denominada. LocalBroadcastManager Está diseñado para aplicaciones que no desean enviar o recibir difusiones de
otras aplicaciones del dispositivo. El LocalBroadcastManager solo publicará mensajes en el contexto de la aplicación
y solo en los receptores de difusión registrados LocalBroadcastManager con. Este fragmento de código es un
ejemplo de registro de un receptor de LocalBroadcastManager difusión con:

Android.Support.V4.Content.LocalBroadcastManager.GetInstance(this). RegisterReceiver(receiver, new


IntentFilter("com.xamarin.example.TEST"));

Otras aplicaciones del dispositivo no pueden recibir los mensajes que se publican con LocalBroadcastManager el.
Este fragmento de código muestra cómo enviar una intención mediante LocalBroadcastManager :

Intent message = new Intent("com.xamarin.example.TEST");


// If desired, pass some values to the broadcast receiver.
message.PutExtra("key", "value");
Android.Support.V4.Content.LocalBroadcastManager.GetInstance(this).SendBroadcast(message);

Vínculos relacionados
API de BroadcastReceiver
API context. RegisterReceiver
API context. SendBroadcast
API context. UnregisterReceiver
Intención de API
API de IntentFilter
LocalBroadcastManager (documentos de Android)
Notificaciones locales en la guía de Android
Biblioteca de compatibilidad de Android V4 (NuGet)
Localización de Android
12/07/2019 • 13 minutes to read • Edit Online

Este documento presenta las características de localización de Android SDK y cómo tener acceso a ellos con
Xamarin.

Características de la plataforma Android


En esta sección se describe las características de localización principal de Android. Vaya a la siguiente sección para
ver ejemplos y código específico.
Configuración regional
Los usuarios elegir su idioma en configuración > idioma & entrada. Esta selección controla el idioma que se
muestra y la configuración regional utiliza (p ej. para el formato de número y fecha).
La configuración regional actual puede consultarse mediante el contexto actual Resources :

var lang = Resources.Configuration.Locale; // eg. "es_ES"

Este valor será un identificador de configuración regional que contiene un código de idioma y un código de
configuración regional, separados por un carácter de subrayado. Como referencia, este es un lista de
configuraciones regionales de Java y Android admite las configuraciones regionales a través de StackOverflow.
Estos son algunos ejemplos comunes:
en_US para inglés (Estados Unidos)
es_ES para el idioma de español (España)
ja_JP para japonés (Japón)
zh_CN chino (China)
zh_TW chino (Taiwán)
pt_PT para portugués (Portugal)
pt_BR para portugués (Brasil)
LOCALE_CHANGED
Android genera android.intent.action.LOCALE_CHANGED cuando el usuario cambia su selección de idioma.
Las actividades pueden optar por controlar esto estableciendo el android:configChanges atributo en la actividad,
similar al siguiente:

[Activity (Label = "@string/app_name", MainLauncher = true, Icon="@drawable/launcher",


ConfigurationChanges = ConfigChanges.Locale | ConfigChanges.ScreenSize | ConfigChanges.Orientation)]

Conceptos básicos de la internacionalización en Android


Estrategia de localización de Android tiene las siguientes partes principales:
Carpetas de recursos que contiene cadenas localizadas, imágenes y otros recursos.
GetText método, que se usa para recuperar las cadenas localizadas en el código
@string/id en los archivos AXML, para colocar automáticamente las cadenas localizadas en los diseños.
Carpetas de recursos
Las aplicaciones de Android administran gran parte del contenido de carpetas de recursos, tales como:
diseño -contiene archivos de diseño AXML.
puede dibujar -contiene imágenes y otros recursos drawable.
valores -contiene cadenas.
RAW -contiene archivos de datos.
La mayoría de los desarrolladores ya están familiarizados con el uso de PPP sufijos en el drawable directory
para proporcionar varias versiones de una imagen, lo que Android permite elegir la versión correcta para cada
dispositivo. El mismo mecanismo se usa para proporcionar varias traducciones de idioma por delante de los
directorios de recursos con identificadores de idioma y referencia cultural.

NOTE
Al especificar un lenguaje de nivel superior como es solo dos caracteres son necesarios; sin embargo, al especificar una
configuración regional completa, el formato de nombre de directorio requiere un guión y minúscula r para separar las dos
partes, por ejemplo pt rBR o zh-rCN. Compare esto con el valor devuelto en el código, que tiene un carácter de subrayado
(p ej. pt_BR ). Ambas opciones son diferentes en el valor .NET CultureInfo clase utiliza, que tiene un guión sólo (p ej.
pt-BR ). Tenga en cuenta estas diferencias cuando se trabaja en las plataformas Xamarin.

Formato de archivo Strings.Xml


Un localizado valores directory (p ej. los valores es-es o valores-pt-rBR) debe contener un archivo
denominado Strings.xml que contendrá el texto traducido para esa configuración regional.
Cada cadena traducible es un elemento XML con el recurso de Id. especificado como el name atributo y la cadena
traducida como el valor:

<string name="app_name">TaskyL10n</string>

Deberá escape según las reglas normales de XML y el name debe ser un identificador de recurso de Android
válido (sin espacios ni guiones). Este es un ejemplo del archivo predeterminado cadenas (en inglés) para el
ejemplo:
values/Strings.xml
<resources>
<string name="app_name">TaskyL10n</string>
<string name="taskadd">Add Task</string>
<string name="taskname">Name</string>
<string name="tasknotes">Notes</string>
<string name="taskdone">Done</string>
<string name="taskcancel">Cancel</string>
</resources>

El directorio español valores es-es contiene un archivo con el mismo nombre (Strings.xml) que contiene las
traducciones:
values-es/Strings.xml

<?xml version="1.0" encoding="utf-8"?>


<resources>
<string name="app_name">TaskyLeon</string>
<string name="taskadd">agregar tarea</string>
<string name="taskname">Nombre</string>
<string name="tasknotes">Notas</string>
<string name="taskdone">Completo</string>
<string name="taskcancel">Cancelar</string>
</resources>

Con la configuración de los archivos de cadenas, se pueden hacer referencia a los valores traducidos en ambos
diseños y código.
Archivos de diseño AXML
Para hacer referencia a las cadenas localizadas en archivos de diseño, utilice el @string/id sintaxis. Este
fragmento de código XML de muestra en el ejemplo text establecen con localizados (otros atributos se han
omitido) de identificadores de recursos:

<TextView
android:id="@+id/NameLabel"
android:text="@string/taskname"
... />
<CheckBox
android:id="@+id/chkDone"
android:text="@string/taskdone"
... />

GetText (método )
Para recuperar las cadenas traducidas en el código, utilice el GetText método y pase el identificador de recurso:

var cancelText = Resources.GetText (Resource.String.taskcancel);


Cadenas de cantidad
Recursos de cadena Android también le permiten crear cadenas cantidad que permite a los traductores
proporcionar traducciones diferentes cantidades diferentes, como:
"Hay 1 tarea izquierda".
"Hay 2 tareas que quedan por hacer."
(en lugar de un tipo genérico "hay n tareas izquierda").
En el Strings.xml

<plurals name="numberOfTasks">
<!--
As a developer, you should always supply "one" and "other"
strings. Your translators will know which strings are actually
needed for their language.
-->
<item quantity="one">There is %d task left.</item>
<item quantity="other">There are %d tasks still to do.</item>
</plurals>

Para representar el uso de la cadena completa la GetQuantityString método, pasando el identificador de recurso
y el valor que se muestre (que se pasan dos veces). El segundo parámetro se usa Android para determinar que
quantity string para usar, el tercer parámetro es el valor realmente se sustituyen en la cadena (ambos son
necesarios).

var translated = Resources.GetQuantityString (


Resource.Plurals.numberOfTasks, taskcount, taskcount);`

Válido quantity conmutadores son:


cero
one
Dos
Algunos
many
otras
Se describe con más detalle en la docs Android. Si un idioma determinado no requiere el control "especiales", los
quantity se pasará por alto las cadenas (por ejemplo, inglés solo usa one y other ; al especificar un zero
cadena no tiene ningún efecto, no se usará).
Imágenes
Imágenes localizadas siguen las mismas reglas que los archivos de cadenas: todas las imágenes que se hace
referencia en la aplicación deben colocarse en drawable directorios por lo que hay una acción de reserva.
Las imágenes específicas de configuración regional, a continuación, se deben colocar en carpetas drawable
calificadas como drawable-es o drawable-ja (también se pueden agregar especificadores PPP ).
En esta captura de pantalla, cuatro imágenes se guardan en el drawable directorio, pero solo uno, flag.png, ha
localizado copias en otros directorios.
Otros tipos de recursos
También puede proporcionar otros tipos de alternativa, los recursos específicos del idioma incluidos los diseños,
animaciones y los archivos sin formato. Esto significa que podría proporcionar un diseño de pantalla específico
para uno o varios de los idiomas de destino, por ejemplo podría crear un diseño específicamente para alemán
que permite que las etiquetas de texto muy largos.
Android 4.2 introdujo la compatibilidad con derecha para idiomas de izquierda (RTL ) si establece la configuración
de la aplicación android:supportsRtl="true" . El calificador de recursos "ldrtl" puede incluirse en un nombre de
directorio que contiene los diseños personalizados que están diseñados para mostrar de derecha a izquierda.
Para obtener más información sobre los nombres de directorio de recursos y de reserva, consulte la
documentación de Android proporcionar recursos alternativos.
Nombre de la aplicación
El nombre de la aplicación es fácil de localizar mediante el uso de un @string/id en para el MainLauncher
actividad:

[Activity (Label = "@string/app_name", MainLauncher = true, Icon="@drawable/launcher",


ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.Locale)]

Idiomas de derecha a izquierda (RTL )


Android 4.2 y versiones más reciente proporciona compatibilidad completa para los diseños de derecha a
izquierda, se describe en detalle en la blog de soporte técnico nativo de derecha a izquierda.
Cuando se usa Android 4.2 (API nivel 17) y la alineación de versiones más reciente, se pueden especificar valores
con start y end en lugar de left y right (por ejemplo android:paddingStart ). También hay nuevas API,
como LayoutDirection , TextDirection , y TextAlignment para ayudar a crear pantallas que se adaptan para los
lectores de derecha a izquierda.
La siguiente captura de pantalla muestra la localizado Tasky ejemplo en árabe:
La siguiente captura de pantalla muestra la localizado Tasky ejemplo en hebreo:

Texto de derecha a izquierda se localiza mediante Strings.xml archivos en la misma manera que el texto de
izquierda a derecha.

Pruebas
Asegúrese de probar exhaustivamente la configuración regional predeterminada. La aplicación se bloqueará si no
se puede cargar los recursos predeterminados por algún motivo (es decir, que faltan).
Emulador de pruebas
Hacer referencia a Google las pruebas en un emulador de Android sección para obtener instrucciones sobre
cómo establecer un emulador en una configuración regional específica mediante el shell de ADB.

adb shell setprop persist.sys.locale fr-CA;stop;sleep 5;start

Pruebas de dispositivos
Para realizar pruebas en un dispositivo, cambiar el idioma en el configuración app.

TIP
Realizar una nota de los iconos y la ubicación de los elementos de menú para que se puede revertir el lenguaje a la
configuración original.

Resumen
En este artículo se trata los aspectos básicos de localización de aplicaciones Android mediante la administración
de recursos integradas. Puede obtener más información acerca de i18n y L10n para iOS, Android y aplicaciones
multiplataforma (incluido Xamarin.Forms) en esta guía multiplataforma.

Vínculos relacionados
Tasky (localizada en el código) (ejemplo)
Localización de recursos de Android
Información general de localización de multiplataforma
Localización de Xamarin.Forms
Localización de iOS
Permisos en Xamarin. Android
27/07/2019 • 18 minutes to read • Edit Online

Información general
Las aplicaciones de Android se ejecutan en su propio espacio aislado y, por motivos de seguridad, no tienen
acceso a determinados recursos del sistema o hardware del dispositivo. El usuario debe conceder explícitamente
el permiso a la aplicación para que pueda usar estos recursos. Por ejemplo, una aplicación no puede tener acceso
al GPS en un dispositivo sin permiso explícito del usuario. Android producirá una Java.Lang.SecurityException
excepción si una aplicación intenta tener acceso a un recurso protegido sin permiso.
El desarrollador de la aplicación declara los permisos en archivo AndroidManifest. XML cuando se desarrolla
la aplicación. Android tiene dos flujos de trabajo diferentes para obtener el consentimiento del usuario para esos
permisos:
En el caso de las aplicaciones destinadas a Android 5,1 (nivel de API 22) o inferior, la solicitud de permiso se
produjo cuando se instaló la aplicación. Si el usuario no ha concedido los permisos, no se instalará la
aplicación. Una vez instalada la aplicación, no hay ninguna manera de revocar los permisos excepto
desinstalando la aplicación.
A partir de Android 6,0 (nivel de API 23), a los usuarios se les dio más control sobre los permisos. pueden
conceder o revocar permisos, siempre y cuando la aplicación esté instalada en el dispositivo. En esta captura
de pantalla se muestra la configuración de permisos de la aplicación Google contacts. Muestra los distintos
permisos y permite al usuario habilitar o deshabilitar permisos:

Las aplicaciones de Android deben comprobar en tiempo de ejecución para ver si tienen permiso de acceso a un
recurso protegido. Si la aplicación no tiene permiso, debe realizar solicitudes mediante las nuevas API
proporcionadas por el Android SDK para que el usuario conceda los permisos. Los permisos se dividen en dos
categorías:
Permisos normales – Se trata de permisos que suponen un pequeño riesgo de seguridad para la seguridad
o la privacidad del usuario. Android 6,0 concederá automáticamente permisos normales en el momento de la
instalación. Consulte la documentación de Android para obtener una lista completa de los permisos normales.
Permisos peligrosos – A diferencia de los permisos normales, los permisos peligrosos son aquellos que
protegen la seguridad o la privacidad del usuario. El usuario debe concederlas explícitamente. El envío o la
recepción de un mensaje SMS es un ejemplo de una acción que requiere un permiso peligroso.
IMPORTANT
La categoría a la que pertenece un permiso puede cambiar con el tiempo. Es posible que un permiso categorizado como
permiso "normal" se pueda elevar en los niveles de API futuros a un permiso peligroso.

Los permisos peligrosos se subdividen en grupos de permisos. Un grupo de permisos contendrá permisos que
están relacionados lógicamente. Cuando el usuario concede el permiso a un miembro de un grupo de permisos,
Android concede automáticamente permiso a todos los miembros de ese grupo. Por ejemplo, el STORAGE grupo
de permisos contiene los WRITE_EXTERNAL_STORAGE permisos READ_EXTERNAL_STORAGE y. Si el usuario concede el
permiso READ_EXTERNAL_STORAGE a, el WRITE_EXTERNAL_STORAGE permiso se concede automáticamente al mismo
tiempo.
Antes de solicitar uno o más permisos, se recomienda proporcionar una lógica en lo que respecta a la razón por
la que la aplicación requiere el permiso antes de solicitar el permiso. Una vez que el usuario entiende la razón, la
aplicación puede solicitar permiso al usuario. Al comprender el razonamiento, el usuario puede tomar una
decisión informada si desea conceder el permiso y comprender las repercusiones en caso contrario.
Todo el flujo de trabajo de comprobación y solicitud de permisos se conoce como comprobación de permisos en
tiempo de ejecución y se puede resumir en el diagrama siguiente:
La biblioteca de compatibilidad de Android transporta algunas de las nuevas API para los permisos de versiones
anteriores de Android. Estas API de traslado comprobarán automáticamente la versión de Android en el
dispositivo, por lo que no es necesario realizar una comprobación de nivel de API cada vez.
En este documento se explica cómo agregar permisos a una aplicación de Xamarin. Android y cómo las
aplicaciones destinadas a Android 6,0 (nivel de API 23) o superior deben realizar una comprobación de permisos
en tiempo de ejecución.

NOTE
Es posible que los permisos del hardware afecten al modo en que la aplicación se filtra por Google Play. Por ejemplo, si la
aplicación requiere el permiso para la cámara, Google Play no mostrará la aplicación en el Google Play Store en un
dispositivo que no tenga una cámara instalada.

Requisitos
Se recomienda encarecidamente que los proyectos de Xamarin. Android incluyan el paquete NuGet Xamarin.
Android. support. compat . Este paquete trasladará las API específicas de permisos a versiones anteriores de
Android, lo que proporciona una interfaz común sin necesidad de comprobar constantemente la versión de
Android en la que se ejecuta la aplicación.

Solicitar permisos del sistema


El primer paso para trabajar con los permisos de Android es declarar los permisos en el archivo de manifiesto de
Android. Esto se debe hacer independientemente del nivel de API que destino la aplicación.
Las aplicaciones que tienen como destino Android 6,0 o posterior no pueden suponer que, como el usuario
concedió permiso en algún momento del pasado, el permiso será válido la próxima vez. Una aplicación destinada
a Android 6,0 siempre debe realizar una comprobación de permiso en tiempo de ejecución. Las aplicaciones
destinadas a Android 5,1 o inferior no necesitan realizar una comprobación de permisos en tiempo de ejecución.

NOTE
Las aplicaciones solo deben solicitar los permisos que requieran.

Declarar permisos en el manifiesto


Los permisos se agregan al archivo archivo AndroidManifest. XML con el uses-permission elemento. Por
ejemplo, si una aplicación va a buscar la posición del dispositivo, requiere permisos de ubicación correctos y del
curso. Los dos elementos siguientes se agregan al manifiesto:

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />


<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Visual Studio
Visual Studio para Mac
Es posible declarar los permisos mediante la compatibilidad de la herramienta integrada en Visual Studio:
1. Haga doble clic en propiedades en el Explorador de soluciones y seleccione la pestaña manifiesto de
Android en el ventana Propiedades:
2. Si la aplicación aún no tiene un archivo AndroidManifest. XML, haga clic en no se encontró archivo
AndroidManifest. Xml. Haga clic para agregar una, como se muestra a continuación:

3. Seleccione los permisos que necesita la aplicación en la lista de permisos necesarios y guárdelos:

Xamarin. Android agregará automáticamente algunos permisos en el momento de la compilación para depurar
las compilaciones. Esto hará que la depuración de la aplicación sea más sencilla. En concreto, dos permisos
importantes son INTERNET y READ_EXTERNAL_STORAGE . Estos permisos definidos automáticamente no aparecerán
en la lista de permisos necesarios . Sin embargo, las compilaciones de versión solo usan los permisos que se
establecen explícitamente en la lista de permisos necesarios .
En el caso de las aplicaciones que tienen como destino Android 5.1 (nivel de API 22) o inferior, no es necesario
hacer nada más. Las aplicaciones que se ejecutarán en Android 6,0 (API 23 nivel 23) o superior deben continuar
con la siguiente sección sobre cómo realizar comprobaciones de permisos en tiempo de ejecución.
Comprobaciones de permisos en tiempo de ejecución en Android 6,0
El ContextCompat.CheckSelfPermission método (disponible con la biblioteca de compatibilidad de Android) se usa
para comprobar si se ha concedido un permiso específico. Este método devolverá Android.Content.PM.Permission
una enumeración que tiene uno de dos valores:
Permission.Granted – Se ha concedido el permiso especificado.
Permission.Denied – No se ha concedido el permiso especificado.

Este fragmento de código es un ejemplo de cómo comprobar el permiso de cámara en una actividad:

if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.Camera) == (int)Permission.Granted)


{
// We have permission, go ahead and use the camera.
}
else
{
// Camera permission is not granted. If necessary display rationale & request.
}

Es aconsejable informar al usuario sobre por qué es necesario un permiso para una aplicación, de modo que se
pueda tomar una decisión informada para conceder el permiso. Un ejemplo de esto sería una aplicación que
toma fotos y las etiqueta geográficamente. Está claro al usuario que el permiso de cámara es necesario, pero
puede que no esté claro por qué la aplicación también necesita la ubicación del dispositivo. El razonamiento debe
mostrar un mensaje para ayudar al usuario a entender por qué es conveniente el permiso de ubicación y que se
requiere el permiso de la cámara.
El ActivityCompat.ShouldShowRequestPermissionRationale método se usa para determinar si se debe mostrar al
usuario la lógica. Este método devolverá true si se debe mostrar el razonamiento para un permiso
determinado. En esta captura de pantalla se muestra un ejemplo de un snackbar que se muestra en una
aplicación que explica el motivo por el que la aplicación necesita conocer la ubicación del dispositivo:

Si el usuario concede el permiso, se


ActivityCompat.RequestPermissions(Activity activity, string[] permissions, int requestCode) debe llamar al
método. Este método requiere los siguientes parámetros:
actividad de – Se trata de la actividad que solicita los permisos y que se va a notificar mediante Android de
los resultados.
permisos de – Una lista de los permisos que se solicitan.
antes si requestcode Valor entero que se usa para hacer coincidir los resultados de la solicitud de permiso
con RequestPermissions una llamada. – Este valor debería ser mayor que cero.

Este fragmento de código es un ejemplo de los dos métodos que se han analizado. En primer lugar, se realiza una
comprobación para determinar si se debe mostrar la racionalización de permisos. Si se va a mostrar la
justificación, se muestra un snackbar con la lógica. Si el usuario hace clic en Aceptar en snackbar, la aplicación
solicitará los permisos. Si el usuario no acepta la razón, la aplicación no debe continuar para solicitar permisos. Si
no se muestra la racionalización, la actividad solicitará el permiso:
if (ActivityCompat.ShouldShowRequestPermissionRationale(this, Manifest.Permission.AccessFineLocation))
{
// Provide an additional rationale to the user if the permission was not granted
// and the user would benefit from additional context for the use of the permission.
// For example if the user has previously denied the permission.
Log.Info(TAG, "Displaying camera permission rationale to provide additional context.");

var requiredPermissions = new String[] { Manifest.Permission.AccessFineLocation };


Snackbar.Make(layout,
Resource.String.permission_location_rationale,
Snackbar.LengthIndefinite)
.SetAction(Resource.String.ok,
new Action<View>(delegate(View obj) {
ActivityCompat.RequestPermissions(this, requiredPermissions, REQUEST_LOCATION);
}
)
).Show();
}
else
{
ActivityCompat.RequestPermissions(this, new String[] { Manifest.Permission.Camera }, REQUEST_LOCATION);
}

RequestPermission se puede llamar a aunque el usuario ya haya concedido el permiso. Las llamadas posteriores
no son necesarias, pero proporcionan al usuario la oportunidad de confirmar (o revocar) el permiso. Cuando
RequestPermission se llama a, el control se entrega al sistema operativo, que mostrará una interfaz de usuario
para aceptar los permisos:

Una vez finalizado el usuario, Android devolverá los resultados a la actividad a través de
OnRequestPermissionResult un método de devolución de llamada,. Este método forma parte de la interfaz
ActivityCompat.IOnRequestPermissionsResultCallback que debe ser implementada por la actividad. Esta interfaz
tiene un único método, OnRequestPermissionsResult , que se invocará mediante Android para informar a la
actividad de las opciones del usuario. Si el usuario ha concedido el permiso, la aplicación puede continuar y usar
el recurso protegido. A continuación se muestra un ejemplo OnRequestPermissionResult de cómo implementar:
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[]
grantResults)
{
if (requestCode == REQUEST_LOCATION)
{
// Received permission result for camera permission.
Log.Info(TAG, "Received response for Location permission request.");

// Check if the only required permission has been granted


if ((grantResults.Length == 1) && (grantResults[0] == Permission.Granted)) {
// Location permission has been granted, okay to retrieve the location of the device.
Log.Info(TAG, "Location permission has now been granted.");
Snackbar.Make(layout, Resource.String.permission_available_camera, Snackbar.LengthShort).Show();
}
else
{
Log.Info(TAG, "Location permission was NOT granted.");
Snackbar.Make(layout, Resource.String.permissions_not_granted, Snackbar.LengthShort).Show();
}
}
else
{
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
}

Resumen
En esta guía se describe cómo agregar y comprobar los permisos en un dispositivo Android. Las diferencias en el
modo en que los permisos funcionan entre aplicaciones Android anteriores (nivel de API < 23) y nuevas
aplicaciones Android (nivel de API > 22). Se ha explicado cómo realizar comprobaciones de permisos en tiempo
de ejecución en Android 6,0.

Vínculos relacionados
Lista de permisos normales
Aplicación de ejemplo de permisos en tiempo de ejecución
Controlar permisos en Xamarin. Android
Gráficos y animación de Android
19/08/2019 • 34 minutes to read • Edit Online

Android proporciona un marco de trabajo muy rico y diverso para admitir animaciones y gráficos 2D. En este
tema se presentan estos marcos de trabajo y se describe cómo crear animaciones y gráficos personalizados para
su uso en una aplicación de Xamarin. Android.

Información general
A pesar de que se ejecutan en dispositivos que tradicionalmente tienen una capacidad limitada, las aplicaciones
móviles con mayor clasificación suelen tener una experiencia de usuario sofisticada, completada con gráficos de
alta calidad y animaciones que proporcionan una sensación intuitiva, dinámica y receptiva. A medida que las
aplicaciones móviles son más sofisticadas, los usuarios han empezado a esperar más y más de aplicaciones.
Afortunadamente para nosotros, las plataformas móviles modernas tienen marcos muy eficaces para crear
animaciones sofisticadas y gráficos personalizados a la vez que conservan la facilidad de uso. Esto permite a los
desarrolladores agregar interactividad enriquecida con muy poco esfuerzo.
Los marcos de API de interfaz de usuario en Android pueden dividirse en dos categorías aproximadamente:
Gráficos y animación.
Los gráficos se dividen en enfoques diferentes para hacer gráficos 2D y 3D. los gráficos 3D están disponibles a
través de una serie de marcos de trabajo integrados como OpenGL ES (una versión específica para móviles de
OpenGL ) y marcos de terceros como monogame (un kit de herramientas multiplataforma compatible con XNA
Toolkit). Aunque los gráficos 3D no se encuentran dentro del ámbito de este artículo, examinaremos las técnicas de
dibujo 2D integradas.
Android proporciona dos API diferentes para crear gráficos 2D. Uno es un enfoque declarativo de alto nivel y el
otro mediante programación API de bajo nivel:
Recursos Dibujables – Se usan para crear gráficos personalizados mediante programación o (más
normalmente) incrustando instrucciones de dibujo en archivos XML. Los recursos que se pueden dibujar se
suelen definir como archivos XML que contienen instrucciones o acciones para que Android represente un
gráfico 2D.
Lienzo de – se trata de una API de bajo nivel que implica dibujar directamente en un mapa de bits
subyacente. Proporciona un control muy exhaustivo sobre lo que se muestra.
Además de estas técnicas de gráficos 2D, Android también proporciona varias maneras de crear animaciones:
Animaciones Dibujables Android también admite animaciones de fotogramas fotogramas conocidas
como animación dibujable. – Esta es la API de animación más sencilla. Android se carga secuencialmente y
muestra los recursos que se dibujan en secuencia (muy parecido a un dibujo).
Ver animaciones Las animaciones de vista son las API de animación originales en Android y están
disponibles en todas las versiones de Android. – Esta API está limitada, ya que solo funcionará con objetos
de vista y solo puede realizar transformaciones simples en esas vistas. Las animaciones de vista se definen
normalmente en los archivos XML /Resources/anim que se encuentran en la carpeta.
Animaciones de propiedades Android 3,0 presentó un nuevo conjunto de API de animación conocido
como animaciones de propiedades. – Estas nuevas API incorporan un sistema extensible y flexible que se
puede usar para animar las propiedades de cualquier objeto, no solo los objetos de vista. Esta flexibilidad
permite encapsular animaciones en clases distintas que harán que el uso compartido del código sea más
sencillo.
Las animaciones de vista son más adecuadas para las aplicaciones que deben ser compatibles con las API
anteriores a Android 3,0 (nivel de API 11). De lo contrario, las aplicaciones deben usar las API de animación de
propiedades más recientes por las razones mencionadas anteriormente.
Todos estos marcos son opciones viables; sin embargo, siempre que sea posible, se deben proporcionar
preferencias a las animaciones de propiedades, ya que es una API más flexible con la que trabajar. Las animaciones
de propiedades permiten encapsular la lógica de animación en clases distintas que facilita el uso compartido de
código y simplifica el mantenimiento del código.

Accesibilidad
Los gráficos y las animaciones ayudan a que las aplicaciones Android sean atractivas y divertidas de usar. sin
embargo, es importante recordar que algunas interacciones se producen a través de screenreaders, dispositivos de
entrada alternativos o con el zoom asistido. Además, algunas interacciones pueden producirse sin capacidades de
audio.
Las aplicaciones son más fáciles de usar en estas situaciones si se han diseñado pensando en la accesibilidad:
proporcionar sugerencias y ayuda de navegación en la interfaz de usuario, y garantizar que hay contenido de texto
o descripciones de los elementos gráficos de la interfaz de usuario.
Consulte la guía de accesibilidad de Google para obtener más información sobre cómo se usan las API de
accesibilidad de Android.

Gráficos 2D
Los recursos que se pueden dibujar son una técnica popular en aplicaciones Android. Como con otros recursos, los
recursos que se pueden – dibujar son declarativos que se definen en archivos XML. Este enfoque permite una
separación limpia del código de los recursos. Esto puede simplificar el desarrollo y el mantenimiento, ya que no es
necesario cambiar el código para actualizar o cambiar los gráficos en una aplicación de Android. Sin embargo,
aunque los recursos que se pueden dibujar son útiles para muchos requisitos gráficos sencillos y comunes, carecen
de la eficacia y el control de la API de canvas.
La otra técnica, con el objeto Canvas , es muy similar a la de otros marcos de API tradicionales, como System.
Drawing o el dibujo principal de iOS. El uso del objeto Canvas proporciona el máximo control sobre cómo se crean
los gráficos 2D. Es adecuado para situaciones en las que un recurso que se puede dibujar no funcionará o será
difícil de trabajar con él. Por ejemplo, puede ser necesario dibujar un control deslizante personalizado cuya
apariencia cambiará en función de los cálculos relacionados con el valor del control deslizante.
Vamos a examinar los recursos que se van a dibujar en primer lugar. Son más sencillas y cubren los casos de
dibujo personalizados más comunes.
Recursos Dibujables
Los recursos que se pueden dibujar se definen en un archivo XML /Resources/drawable en el directorio. A
diferencia de la incrustación de PNG o JPEG, no es necesario proporcionar versiones específicas de densidad de
recursos que se pueda dibujar. En tiempo de ejecución, una aplicación de Android cargará estos recursos y usará
las instrucciones de estos archivos XML para crear gráficos 2D. Android define varios tipos diferentes de recursos
que se dibujan:
ShapeDrawable – Se trata de un objeto dibujable que dibuja una forma geométrica primitiva y aplica un
conjunto limitado de efectos gráficos en esa forma. Son muy útiles para cosas como la personalización de
botones o la configuración del fondo de TextViews. Veremos un ejemplo de cómo usar un ShapeDrawable
más adelante en este artículo.
StateListDrawable – Se trata de un recurso que se dibuja y que cambiará la apariencia según el estado de un
widget/control. Por ejemplo, un botón puede cambiar su apariencia en función de si está presionado o no.
LayerDrawable – Este recurso dibujable que apilará varios drawables uno encima de otro. En la captura de
pantalla siguiente se muestra un ejemplo de un LayerDrawable :

TransitionDrawable Se trata de una LayerDrawable, pero con una diferencia. – Un TransitionDrawable es


capaz de animar una capa que se muestra encima de otra encima.
LevelListDrawable Esto es muy similar a un StateListDrawable en que mostrará una imagen basada en
determinadas condiciones. – Sin embargo, a diferencia de StateListDrawable, LevelListDrawable muestra
una imagen basada en un valor entero. Un ejemplo de una LevelListDrawable sería Mostrar la fuerza de una
señal WiFi. A medida que cambia la intensidad de la señal Wi-Fi, el dibujo que se muestra cambiará en
consecuencia.
ScaleDrawable/ClipDrawable – Como su nombre implica, estos Drawables proporcionan la funcionalidad
de escalado y recorte. El ScaleDrawable escalará otro dibujable, mientras que el ClipDrawable recortará
otro dibujable.
InsetDrawable – Este dibujo se aplicará a los lados de otro recurso que se dibuja. Se utiliza cuando una vista
necesita un fondo menor que los límites reales de la vista.
XML BitmapDrawable – este archivo es un conjunto de instrucciones, en XML, que se realizarán en un mapa
de bits real. Algunas acciones que Android puede realizar son el mosaico, la interpolación y el suavizado de
contorno. Uno de los usos muy comunes de esto es poner en mosaico un mapa de bits a través del fondo de
un diseño.
Ejemplo dibujable
Echemos un vistazo a un ejemplo rápido de cómo crear un gráfico 2D con un ShapeDrawable . Un ShapeDrawable
puede definir una de las cuatro formas básicas: rectángulo, óvalo, línea y anillo. También es posible aplicar efectos
básicos, como el degradado, el color y el tamaño. El siguiente XML es un ShapeDrawable que se puede encontrar
en el proyecto complementario AnimationsDemo (en el Resources/drawable/shape_rounded_blue_rect.xml archivo).
Define un rectángulo con un fondo de degradado púrpura y esquinas redondeadas:

<?xml version="1.0" encoding="utf-8"?>


<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<!-- Specify a gradient for the background -->
<gradient android:angle="45"
android:startColor="#55000066"
android:centerColor="#00000000"
android:endColor="#00000000"
android:centerX="0.75" />

<padding android:left="5dp"
android:right="5dp"
android:top="5dp"
android:bottom="5dp" />

<corners android:topLeftRadius="10dp"
android:topRightRadius="10dp"
android:bottomLeftRadius="10dp"
android:bottomRightRadius="10dp" />
</shape>

Podemos hacer referencia a este recurso que se puede dibujar mediante declaración en un diseño u otro dibujable,
tal y como se muestra en el siguiente XML:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#33000000">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:background="@drawable/shape_rounded_blue_rect"
android:text="@string/message_shapedrawable" />
</RelativeLayout>

Los recursos Dibujables también se pueden aplicar mediante programación. En el fragmento de código siguiente
se muestra cómo establecer mediante programación el fondo de una TextView:

TextView tv = FindViewById<TextView>(Resource.Id.shapeDrawableTextView);
tv.SetBackgroundResource(Resource.Drawable.shape_rounded_blue_rect);

Para ver el aspecto que tendría esto, ejecute el proyecto AnimationsDemo y seleccione el elemento dibujado por la
forma en el menú principal. Deberíamos ver algo parecido a la captura de pantalla siguiente:

Para obtener más información sobre los elementos XML y la sintaxis de los recursos que se van a dibujar, consulte
la documentación de Google.
Usar la API de dibujo de Canvas
Los Drawables son eficaces pero tienen sus limitaciones. Algunas cosas no son posibles o muy complejas (por
ejemplo: aplicar un filtro a una imagen tomada por una cámara en el dispositivo). Sería muy difícil aplicar la
reducción de ojos rojos mediante un recurso que se puede dibujar. En su lugar, la API de canvas permite que una
aplicación tenga un control muy específico para cambiar los colores de una parte específica de la imagen.
Una clase que se usa normalmente con el lienzo es la clase Paint . Esta clase contiene información de color y estilo
sobre cómo dibujar. Se usa para proporcionar elementos como un color y una transparencia.
La API de canvas usa el modelo de la pintor para dibujar gráficos 2D. Las operaciones se aplican en capas
sucesivas unas de otras. Cada operación cubrirá parte del mapa de bits subyacente. Cuando el área se superpone a
un área dibujada anteriormente, el nuevo dibujo ocultará el antiguo de forma parcial o totalmente. Esta es la
misma manera que muchas otras API de dibujo como los gráficos principales de System. Drawing y iOS.
Hay dos maneras de obtener un Canvas objeto. La primera forma implica definir un objeto de mapa de bits y, a
Canvas continuación, crear una instancia de un objeto con él. Por ejemplo, el fragmento de código siguiente crea
un nuevo lienzo con un mapa de bits subyacente:

Bitmap bitmap = Bitmap.CreateBitmap(100, 100, Bitmap.Config.Argb8888);


Canvas canvas = new Canvas(b);

La otra manera de obtener un Canvas objeto es mediante el método de devolución de llamada OnDraw que se
proporciona a la clase base de vista . Android llama a este método cuando decide que una vista debe dibujarse y
pasar un Canvas objeto para la vista con la que trabajar.
La clase Canvas expone métodos para proporcionar las instrucciones Draw mediante programación. Por ejemplo:
Canvas. DrawPaint – rellena el mapa de bits del lienzo completo con el dibujo especificado.
Canvas. DrawPath – dibuja la forma geométrica especificada utilizando la pintura especificada.
Canvas. DrawText – dibuja el texto en el lienzo con el color especificado. El texto se dibuja en la x,y
ubicación.
Dibujo con la API de Canvas
Veamos un ejemplo de la API de canvas en acción. En el fragmento de código siguiente se muestra cómo dibujar
una vista:

public class MyView : View


{
protected override void OnDraw(Canvas canvas)
{
base.OnDraw(canvas);
Paint green = new Paint {
AntiAlias = true,
Color = Color.Rgb(0x99, 0xcc, 0),
};
green.SetStyle(Paint.Style.FillAndStroke);

Paint red = new Paint {


AntiAlias = true,
Color = Color.Rgb(0xff, 0x44, 0x44)
};
red.SetStyle(Paint.Style.FillAndStroke);

float middle = canvas.Width * 0.25f;


canvas.DrawPaint(red);
canvas.DrawRect(0, 0, middle, canvas.Height, green);
}
}

Este código anterior crea primero una pintura roja y un objeto de pintura verde. Rellena el contenido del lienzo con
rojo y, a continuación, indica al lienzo que dibuje un rectángulo verde que sea el 25% del ancho del lienzo. Un
ejemplo de esto puede verse en AnimationsDemo el proyecto que se incluye con el código fuente de este artículo. Al
iniciar la aplicación y seleccionar el elemento de dibujo en el menú principal, deberíamos tener una pantalla similar
a la siguiente:
Animación
Usuarios como cosas que se mueven en sus aplicaciones. Las animaciones son una excelente manera de mejorar la
experiencia del usuario de una aplicación y ayudar a deshacerla. Las mejores animaciones son las que los usuarios
no tienen en cuenta porque se sienten naturales. Android proporciona las siguientes tres API para animaciones:
Ver animación – Esta es la API original. Estas animaciones están asociadas a una vista específica y pueden
realizar transformaciones simples en el contenido de la vista. Debido a su simplicidad, esta API sigue siendo
útil para cosas como animaciones alfa, giros, etc.
Animación de propiedades – Las animaciones de propiedades se introdujeron en Android 3,0. Permiten a
una aplicación animar casi todo. Las animaciones de propiedad se pueden utilizar para cambiar cualquier
propiedad de cualquier objeto, aunque ese objeto no esté visible en la pantalla.
Animación dibujable – Este es un recurso dibujado especial que se usa para aplicar un efecto de
animación muy simple a los diseños.
En general, la animación de propiedades es el sistema preferido que se va a usar, ya que es más flexible y ofrece
más características.
Ver animaciones
Las animaciones de vista se limitan a las vistas y solo pueden realizar animaciones en valores como los puntos de
inicio y final, el tamaño, la rotación y la transparencia. Estos tipos de animaciones se conocen normalmente como
animaciones de interpolación. Las animaciones de vista se pueden definir – de dos maneras mediante
programación en el código o mediante archivos XML. Los archivos XML son la manera preferida de declarar
animaciones de vista, ya que son más legibles y fáciles de mantener.
Los archivos XML de animación se almacenarán en /Resources/anim el directorio de un proyecto de Xamarin.
Android. Este archivo debe tener uno de los siguientes elementos como elemento raíz:
alpha – Una animación de fundido de salida o de fundido.
rotate – Animación de giro.
scale – Animación de cambio de tamaño.
translate – Movimiento horizontal y/o vertical.
set – Contenedor que puede contener uno o varios elementos de animación.

De forma predeterminada, todas las animaciones de un archivo XML se aplicarán simultáneamente. Para que las
animaciones se realicen de forma android:startOffset secuencial, establezca el atributo en uno de los elementos
definidos anteriormente.
Es posible afectar a la tasa de cambio en una animación mediante el uso deun interpolador. Un interpolador
permite acelerar, repetir o desacelerar los efectos de animación. El marco de trabajo de Android proporciona varios
interpoladores listos para el cuadro, como (pero sin limitarse a):
AccelerateInterpolatorEstos interpoladores aumentan o reducen la velocidad de cambio de una animación.
/ DecelerateInterpolator –
BounceInterpolator – el cambio se rebota al final.
LinearInterpolator – la tasa de cambios es constante.

El siguiente código XML muestra un ejemplo de un archivo de animación que combina algunos de estos
elementos:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android=http://schemas.android.com/apk/res/android
android:shareInterpolator="false">

<scale android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:fromXScale="1.0"
android:toXScale="1.4"
android:fromYScale="1.0"
android:toYScale="0.6"
android:pivotX="50%"
android:pivotY="50%"
android:fillEnabled="true"
android:fillAfter="false"
android:duration="700" />

<set android:interpolator="@android:anim/accelerate_interpolator">
<scale android:fromXScale="1.4"
android:toXScale="0.0"
android:fromYScale="0.6"
android:toYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:fillEnabled="true"
android:fillBefore="false"
android:fillAfter="true"
android:startOffset="700"
android:duration="400" />

<rotate android:fromDegrees="0"
android:toDegrees="-45"
android:toYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:fillEnabled="true"
android:fillBefore="false"
android:fillAfter="true"
android:startOffset="700"
android:duration="400" />
</set>
</set>

Esta animación realizará todas las animaciones simultáneamente. La animación de la primera escala ampliará la
imagen horizontalmente y la reducirá verticalmente y, a continuación, la imagen se girará de manera simultánea
45 grados en el sentido contrario a las agujas del reloj y se reducirá en la pantalla.
La animación se puede aplicar mediante programación a una vista si se infla la animación y, a continuación, se
aplica a una vista. Android proporciona la clase Android.Views.Animations.AnimationUtils auxiliar que impondrá un
recurso de animación y devolverá una instancia de. Android.Views.Animations.Animation Este objeto se aplica a una
vista mediante una StartAnimation llamada a y Animation pasando el objeto. En el fragmento de código siguiente
se muestra un ejemplo de esto:

Animation myAnimation = AnimationUtils.LoadAnimation(Resource.Animation.MyAnimation);


ImageView myImage = FindViewById<ImageView>(Resource.Id.imageView1);
myImage.StartAnimation(myAnimation);

Ahora que tenemos un conocimiento fundamental de cómo funcionan las animaciones de vistas, permite moverse
a animaciones de propiedades.
Animaciones de propiedades
Los animadores de propiedades son una nueva API que se presentó en Android 3,0. Proporcionan una API más
extensible que se puede usar para animar cualquier propiedad en cualquier objeto.
Todas las animaciones de propiedades las crean las instancias de la subclase de animación . Las aplicaciones no
usan directamente esta clase, sino que usan una de sus subclases:
ValueAnimator – Esta clase es la clase más importante en toda la API de animación de propiedades. Calcula
los valores de las propiedades que se deben cambiar. ViewAnimator No actualiza directamente esos valores;
en su lugar, genera eventos que se pueden usar para actualizar objetos animados.
ObjectAnimator Esta clase es una subclase de ValueAnimator . – Está diseñado para simplificar el proceso de
animación de objetos aceptando un objeto de destino y una propiedad para actualizar.
AnimationSet – Esta clase es responsable de orquestar cómo se ejecutan las animaciones en relación con
otras. Las animaciones pueden ejecutarse simultáneamente, secuencialmente o con un retraso especificado
entre ellas.
Los evaluadores son clases especiales que los animadores usan para calcular los nuevos valores durante una
animación. En la caja, Android proporciona los siguientes evaluadores:
IntEvaluator – Calcula los valores de las propiedades de entero.
FloatEvaluator – Calcula los valores de las propiedades float.
ArgbEvaluator – Calcula los valores de las propiedades de color.
Si la propiedad que se está animando no es float un int , o el color, las aplicaciones pueden crear su propio
evaluador implementando la ITypeEvaluator interfaz. (La implementación de evaluadores personalizados queda
fuera del ámbito de este tema).
Usar ValueAnimator
Hay dos partes en cualquier animación: calcular valores animados y después establecer esos valores en las
propiedades de algún objeto. ValueAnimator solo calculará los valores, pero no funcionará directamente en
objetos. En su lugar, los objetos se actualizarán dentro de los controladores de eventos que se invocarán durante la
duración de la animación. Este diseño permite actualizar varias propiedades de un valor animado.
Puede obtener una instancia de ValueAnimator mediante una llamada a uno de los siguientes métodos de fábrica:
ValueAnimator.OfInt
ValueAnimator.OfFloat
ValueAnimator.OfObject

Una vez hecho esto, la ValueAnimator instancia debe tener su conjunto de duración y, a continuación, se puede
iniciar. En el ejemplo siguiente se muestra cómo animar un valor de 0 a 1 en el intervalo de 1000 milisegundos:

ValueAnimator animator = ValueAnimator.OfInt(0, 100);


animator.SetDuration(1000);
animator.Start();

Pero, el fragmento de código anterior no es muy útil – . el animador se ejecutará, pero no hay ningún destino para
el valor actualizado. La Animator clase generará el evento de actualización cuando decida que es necesario
informar a los agentes de escucha de un nuevo valor. Las aplicaciones pueden proporcionar un controlador de
eventos para responder a este evento, tal y como se muestra en el siguiente fragmento de código:
MyCustomObject myObj = new MyCustomObject();
myObj.SomeIntegerValue = -1;

animator.Update += (object sender, ValueAnimator.AnimatorUpdateEventArgs e) =>


{
int newValue = (int) e.Animation.AnimatedValue;
// Apply this new value to the object being animated.
myObj.SomeIntegerValue = newValue;
};

Ahora que tenemos una descripción de ValueAnimator , le permite obtener más información ObjectAnimator sobre.
Usar ObjectAnimator
ObjectAnimator es una subclase de ViewAnimator que combina el motor de control de tiempo y el ValueAnimator
cálculo de valores de con la lógica necesaria para conectar controladores de eventos. El ValueAnimator requiere
que las aplicaciones conecten explícitamente un – controlador ObjectAnimator de eventos se encargará de este
paso.
La API de ObjectAnimator es muy similar a la API de ViewAnimator , pero requiere que proporcione el objeto y el
nombre de la propiedad que se va a actualizar. En el ejemplo siguiente se muestra un ejemplo ObjectAnimator del
uso de:

MyCustomObject myObj = new MyCustomObject();


myObj.SomeIntegerValue = -1;

ObjectAnimator animator = ObjectAnimator.OfFloat(myObj, "SomeIntegerValue", 0, 100);


animator.SetDuration(1000);
animator.Start();

Como puede ver en el fragmento de código anterior, ObjectAnimator puede reducir y simplificar el código
necesario para animar un objeto.
Animaciones Dibujables
La API de animación final es la API de animación dibujable. Las animaciones Dibujables cargan una serie de
recursos que se puedan dibujar uno tras otro y los muestran secuencialmente, de forma similar a un dibujo
animado.
Los recursos Dibujables se definen en un archivo XML que tiene <animation-list> un elemento como el elemento
raíz y una serie <item> de elementos que definen cada fotograma de la animación. Este archivo XML se almacena
en la /Resource/drawable carpeta de la aplicación. El siguiente código XML es un ejemplo de una animación
dibujable:

<animation-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/asteroid01" android:duration="100" />
<item android:drawable="@drawable/asteroid02" android:duration="100" />
<item android:drawable="@drawable/asteroid03" android:duration="100" />
<item android:drawable="@drawable/asteroid04" android:duration="100" />
<item android:drawable="@drawable/asteroid05" android:duration="100" />
<item android:drawable="@drawable/asteroid06" android:duration="100" />
</animation-list>

Esta animación se ejecutará a través de seis fotogramas. El android:duration atributo declara cuánto tiempo se
mostrará cada fotograma. El siguiente fragmento de código muestra un ejemplo de cómo crear una animación
dibujable e iniciarla cuando el usuario hace clic en un botón de la pantalla:
AnimationDrawable _asteroidDrawable;

protected override void OnCreate(Bundle bundle)


{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);

_asteroidDrawable = (Android.Graphics.Drawables.AnimationDrawable)
Resources.GetDrawable(Resource.Drawable.spinning_asteroid);

ImageView asteroidImage = FindViewById<ImageView>(Resource.Id.imageView2);


asteroidImage.SetImageDrawable((Android.Graphics.Drawables.Drawable) _asteroidDrawable);

Button asteroidButton = FindViewById<Button>(Resource.Id.spinAsteroid);


asteroidButton.Click += (sender, e) =>
{
_asteroidDrawable.Start();
};
}

En este momento, hemos tratado las bases de las API de animación disponibles en una aplicación de Android.

Resumen
En este artículo se presentaron muchos nuevos conceptos y API para ayudar a agregar algunos gráficos a una
aplicación de Android. En primer lugar, se han descrito las distintas API de gráficos 2D y se ha mostrado cómo
Android permite a las aplicaciones dibujar directamente en la pantalla mediante un objeto Canvas. También vimos
algunas técnicas alternativas que permiten la creación declarativa de gráficos mediante archivos XML. En este caso,
nos centramos en describir las API antiguas y nuevas para crear animaciones en Android.

Vínculos relacionados
Demostración de animaciones (ejemplo)
Animación y gráficos
Uso de animaciones para que la Mobile Apps sea vida
AnimationDrawable
Canvas
Animador de objetos
Animación de valores
Arquitecturas de CPU
16/08/2019 • 7 minutes to read • Edit Online

Xamarin. Android admite varias arquitecturas de CPU, incluidos los dispositivos de 32 bits y de 64 bits. En este
artículo se explica cómo dirigir una aplicación a una o varias arquitecturas de CPU compatibles con Android.

Información general sobre arquitecturas de CPU


Al preparar la aplicación para su lanzamiento, debe especificar las arquitecturas de CPU de la plataforma que
admite la aplicación. Un APK único puede contener código máquina para admitir varias arquitecturas diferentes.
Cada colección de código específico de la arquitectura está asociada a una interfaz binaria de aplicación (ABI).
Cada ABI define cómo se espera que este código máquina interactúe con Android en tiempo de ejecución. Para
obtener más información sobre cómo funciona, consulte dispositivos & de varios núcleos Xamarin. Android.

Cómo especificar las arquitecturas admitidas


Visual Studio
Visual Studio para Mac
Normalmente, se selecciona explícitamente una arquitectura (o arquitecturas) cuando la aplicación está
configurada para su lanzamiento. Cuando la aplicación está configurada para depurar, se habilitan las opciones
usar tiempo de ejecución compartido y usar implementación rápida , lo que deshabilita la selección de
arquitectura explícita.
En Visual Studio, haga clic con el botón derecho en el proyecto en el Explorador de soluciones y seleccione
propiedades. En la página Opciones de Android , consulte la sección Propiedades de empaquetado y
compruebe que la opción usar el tiempo de ejecución compartido está deshabilitada (la desactivación permite
seleccionar explícitamente qué Abi se admite). Haga clic en el botón Opciones avanzadas y, en arquitecturas
admitidas, compruebe las arquitecturas que desea admitir:

Xamarin.Android admite las siguientes arquitecturas:


armeabi – CPU basadas en ARM que admiten al menos el conjunto de instrucciones ARMv5TE. Tenga en
armeabi cuenta que no es seguro para subprocesos y no debe usarse en dispositivos de varias CPU.

NOTE
A partir de Xamarin. Android 9,2, armeabi ya no se admite.

armeabi-v7a – CPU basadas en ARM con operaciones de punto flotante de hardware y varios
dispositivos de CPU (SMP ). Tenga en armeabi-v7a cuenta que el código del equipo no se ejecutará en los
dispositivos ARMv5.
arm64-v8a – CPU basadas en la arquitectura ARMv8 de 64 bits.
x86 – CPU que admiten el conjunto de instrucciones x86 (o IA-32). Este conjunto de instrucciones es
equivalente al de Pentium Pro, incluidas las instrucciones MMX, SSE, SSE2 e SSE3.
x86_64 CPU que admiten el conjunto de instrucciones x86 de 64 bits (también conocido como x64 y
AMD64).
armeabi-v7a De forma predeterminada, Xamarin. Android es para las compilaciones de versión . Este valor
proporciona un rendimiento significativamente mejor armeabi que. Si tiene como destino una plataforma ARM
de 64 bits (como el nexo 9), seleccione arm64-v8a . Si va a implementar la aplicación en un dispositivo x86,
seleccione x86 . Si el dispositivo x86 de destino usa una arquitectura de CPU de 64 bits x86_64 , seleccione.

Establecer como destino varias plataformas


Para tener como destino varias arquitecturas de CPU, puede seleccionar más de una ABI (a costa de un tamaño
de archivo APK mayor). Puede usar la opción generar un paquete (. apk) por la ABI seleccionada (descrita
en establecer propiedades de empaquetado) para crear un apk independiente para cada arquitectura admitida.
No tiene que seleccionar arm64-v8a o x86_64 para tener como destino dispositivos de 64 bits; no es necesaria la
compatibilidad con 64 bits para ejecutar la aplicación en el hardware de 64 bits. Por ejemplo, los dispositivos
ARM de 64 bits (como el nexo 9) pueden ejecutar aplicaciones configuradas para armeabi-v7a . La principal
ventaja de habilitar la compatibilidad con 64 bits es hacer que la aplicación pueda abordar más memoria.

NOTE
A partir de agosto de 2018 se necesitarán nuevas aplicaciones para alcanzar el nivel 26 de la API, y a partir de agosto de
2019 se requerirá que las aplicaciones proporcionen versiones de 64 bits además de la versión de 32 bits.

Información adicional
En algunas situaciones, puede que tenga que crear un APK independiente para cada arquitectura (para reducir el
tamaño de la APK o porque la aplicación tiene bibliotecas compartidas que son específicas de una arquitectura de
CPU determinada). Para obtener más información sobre este enfoque, vea compilar apk específicos de ABI.
Control de giro
16/08/2019 • 16 minutes to read • Edit Online

En este tema se describe cómo controlar los cambios de orientación de dispositivos en Xamarin. Android. En él se
explica cómo trabajar con el sistema de recursos de Android para cargar automáticamente recursos para una
orientación de dispositivo determinada, así como cómo controlar mediante programación los cambios de
orientación.

Información general
Dado que los dispositivos móviles se giran con facilidad, la rotación integrada es una característica estándar de
los sistemas operativos móviles. Android proporciona un marco de trabajo sofisticado para tratar el giro dentro
de las aplicaciones, si la interfaz de usuario se crea mediante declaración en XML o mediante programación en
código. Cuando se controlan automáticamente los cambios de diseño declarativos en un dispositivo girado, una
aplicación puede beneficiarse de la estrecha integración con el sistema de recursos de Android. En el caso del
diseño mediante programación, los cambios se deben controlar manualmente. Esto permite un mayor control en
tiempo de ejecución, pero a costa de más trabajo para el desarrollador. Una aplicación también puede optar por
no participar en el reinicio de la actividad y tomar el control manual de los cambios de orientación.
En esta guía se examinan los siguientes temas de orientación:
Rotación de diseño declarativo – Cómo usar el sistema de recursos de Android para compilar
aplicaciones que tienen en cuenta la orientación, incluida la forma de cargar los diseños y drawables para
las orientaciones particulares.
Rotación de diseño mediante programación – Cómo agregar controles mediante programación y
cómo controlar manualmente los cambios de orientación.

Controlar la rotación mediante declaración con diseños


Al incluir archivos en carpetas que siguen las convenciones de nomenclatura, Android carga automáticamente los
archivos correspondientes cuando cambia la orientación. Esto incluye compatibilidad con:
Recursos de diseño – Especificar los archivos de diseño que se inflan para cada orientación.
Recursos Dibujables – Que especifica qué drawables se cargan para cada orientación.
Recursos de diseño
De forma predeterminada, los archivos de Android XML (AXML ) incluidos en la carpeta recursos/diseño se
usan para representar vistas para una actividad. Los recursos de esta carpeta se utilizan para la orientación
vertical y horizontal si no se proporcionan recursos de diseño adicionales específicamente para el panorama.
Considere la estructura del proyecto creada por la plantilla de proyecto predeterminada:
Este proyecto crea un único archivo Main. axml en la carpeta recursos/diseño . Cuando se llama al OnCreate
método de la actividad, se infla la vista definida en Main. axml, que declara un botón como se muestra en el
código XML siguiente:

<?xml version="1.0" encoding="utf-8"?>


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Button
android:id="@+id/myButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"/>
</LinearLayout>

Si el dispositivo se gira a la orientación horizontal, se llama de OnCreate nuevo al método de la actividad y se


infla el mismo archivo Main. axml , tal y como se muestra en la siguiente captura de pantalla:
Diseños específicos de la orientación
Además de la carpeta de diseño (que de forma predeterminada es vertical y también se puede llamar
explícitamente al Puerto de diseño mediante la layout-land inclusión de una carpeta denominada), una aplicación
puede definir las vistas que necesita en el entorno sin ningún cambio de código.
Supongamos que el archivo Main. axml contiene el siguiente código XML:

<?xml version="1.0" encoding="utf-8"?>


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:text="This is portrait"
android:layout_height="wrap_content"
android:layout_width="fill_parent" />
</RelativeLayout>

Si se agrega al proyecto una carpeta denominada layout-Land que contiene un archivo Main. axml adicional, si
se aumenta el diseño en horizontal, se cargará en Android el archivo Main. axml recién agregado. Considere la
versión horizontal del archivo Main. axml que contiene el código siguiente (para simplificar, este XML es similar
a la versión vertical predeterminada del código, pero usa una cadena diferente en TextView ):

<?xml version="1.0" encoding="utf-8"?>


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:text="This is landscape"
android:layout_height="wrap_content"
android:layout_width="fill_parent" />
</RelativeLayout>

Al ejecutar este código y girar el dispositivo de vertical a horizontal, se muestra la nueva carga de XML, como se
muestra a continuación:
Recursos Dibujables
Durante la rotación, Android trata los recursos que se dibujan de manera similar a los recursos de diseño. En este
caso, el sistema obtiene el drawables de las carpetas Resources /drawable y Resources -Land , respectivamente.
Por ejemplo, suponga que el proyecto incluye una imagen con el nombre Monkey. png en la carpeta Resources
/drawable , donde se hace referencia ImageView a drawable desde un en XML similar al siguiente:

<ImageView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="@drawable/monkey"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true" />

Supongamos también que se incluye una versión diferente de Monkey. png en recursos/tierras Dibujables. Al
igual que con los archivos de diseño, cuando se gira el dispositivo, los cambios Dibujables para la orientación
determinada, como se muestra a continuación:
Controlar la rotación mediante programación
A veces, definimos diseños en el código. Esto puede ocurrir por diversos motivos, como limitaciones técnicas,
preferencias del desarrollador, etc. Cuando se agregan controles mediante programación, una aplicación debe
tener en cuenta manualmente la orientación del dispositivo, que se administra automáticamente al usar recursos
XML.
Agregar controles en el código
Para agregar controles mediante programación, una aplicación debe realizar los siguientes pasos:
Cree un diseño.
Establezca los parámetros de diseño.
Crear controles.
Establecer los parámetros de diseño del control.
Agregue controles al diseño.
Establezca el diseño como la vista de contenido.
Por ejemplo, considere una interfaz de usuario que consta de un TextView único control agregado
RelativeLayout a, tal como se muestra en el código siguiente.
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);

// create a layout
var rl = new RelativeLayout (this);

// set layout parameters


var layoutParams = new RelativeLayout.LayoutParams (ViewGroup.LayoutParams.FillParent,
ViewGroup.LayoutParams.FillParent);
rl.LayoutParameters = layoutParams;

// create TextView control


var tv = new TextView (this);

// set TextView's LayoutParameters


tv.LayoutParameters = layoutParams;
tv.Text = "Programmatic layout";

// add TextView to the layout


rl.AddView (tv);

// set the layout as the content view


SetContentView (rl);
}

Este código crea una instancia de una RelativeLayout clase y establece su LayoutParameters propiedad. La
LayoutParams clase es la manera de Android de encapsular cómo se colocan los controles de forma reutilizable.
Una vez creada una instancia de un diseño, se pueden crear y agregar controles. Los controles también
LayoutParameters tienen, TextView como en este ejemplo. Una vez creado, se agrega RelativeLayout a y al
establecer RelativeLayout como la vista de contenido da como resultado que la aplicación muestre TextView el,
tal y como se muestra: TextView

Detectar orientación en el código


Si una aplicación intenta cargar una interfaz de usuario diferente para cada orientación cuando OnCreate se
llama a (esto ocurrirá cada vez que se gire un dispositivo), debe detectar la orientación y, a continuación, cargar el
código de interfaz de usuario deseado. Android tiene una clase denominada WindowManager , que se puede usar
para determinar la rotación del dispositivo actual a través de la WindowManager.DefaultDisplay.Rotation propiedad,
como se muestra a continuación:

protected override void OnCreate (Bundle bundle)


{
base.OnCreate (bundle);

// create a layout
var rl = new RelativeLayout (this);

// set layout parameters


var layoutParams = new RelativeLayout.LayoutParams (ViewGroup.LayoutParams.FillParent,
ViewGroup.LayoutParams.FillParent);
rl.LayoutParameters = layoutParams;

// get the initial orientation


var surfaceOrientation = WindowManager.DefaultDisplay.Rotation;
// create layout based upon orientation
RelativeLayout.LayoutParams tvLayoutParams;

if (surfaceOrientation == SurfaceOrientation.Rotation0 || surfaceOrientation ==


SurfaceOrientation.Rotation180) {
tvLayoutParams = new RelativeLayout.LayoutParams (ViewGroup.LayoutParams.FillParent,
ViewGroup.LayoutParams.WrapContent);
} else {
tvLayoutParams = new RelativeLayout.LayoutParams (ViewGroup.LayoutParams.FillParent,
ViewGroup.LayoutParams.WrapContent);
tvLayoutParams.LeftMargin = 100;
tvLayoutParams.TopMargin = 100;
}

// create TextView control


var tv = new TextView (this);
tv.LayoutParameters = tvLayoutParams;
tv.Text = "Programmatic layout";

// add TextView to the layout


rl.AddView (tv);

// set the layout as the content view


SetContentView (rl);
}

Este código establece el TextView que se va a colocar en 100 píxeles desde la parte superior izquierda de la
pantalla, animando automáticamente al nuevo diseño, cuando se gira a horizontal, como se muestra aquí:
Impedir el reinicio de la actividad
Además de controlar todo en OnCreate , una aplicación también puede impedir que una actividad se reinicie
cuando cambie la orientación estableciendo ConfigurationChanges en el de la ActivityAttribute manera
siguiente:

[Activity (Label = "CodeLayoutActivity", ConfigurationChanges=Android.Content.PM.ConfigChanges.Orientation |


Android.Content.PM.ConfigChanges.ScreenSize)]

Ahora, cuando se gira el dispositivo, la actividad no se reinicia. Para controlar manualmente el cambio de
orientación en este caso, una actividad puede invalidar el OnConfigurationChanged método y determinar la
orientación desde el Configuration objeto que se pasa, como en la nueva implementación de la actividad
siguiente:
[Activity (Label = "CodeLayoutActivity", ConfigurationChanges=Android.Content.PM.ConfigChanges.Orientation |
Android.Content.PM.ConfigChanges.ScreenSize)]
public class CodeLayoutActivity : Activity
{
TextView _tv;
RelativeLayout.LayoutParams _layoutParamsPortrait;
RelativeLayout.LayoutParams _layoutParamsLandscape;

protected override void OnCreate (Bundle bundle)


{
// create a layout
// set layout parameters
// get the initial orientation

// create portrait and landscape layout for the TextView


_layoutParamsPortrait = new RelativeLayout.LayoutParams (ViewGroup.LayoutParams.FillParent,
ViewGroup.LayoutParams.WrapContent);

_layoutParamsLandscape = new RelativeLayout.LayoutParams (ViewGroup.LayoutParams.FillParent,


ViewGroup.LayoutParams.WrapContent);
_layoutParamsLandscape.LeftMargin = 100;
_layoutParamsLandscape.TopMargin = 100;

_tv = new TextView (this);

if (surfaceOrientation == SurfaceOrientation.Rotation0 || surfaceOrientation ==


SurfaceOrientation.Rotation180) {
_tv.LayoutParameters = _layoutParamsPortrait;
} else {
_tv.LayoutParameters = _layoutParamsLandscape;
}

_tv.Text = "Programmatic layout";


rl.AddView (_tv);
SetContentView (rl);
}

public override void OnConfigurationChanged (Android.Content.Res.Configuration newConfig)


{
base.OnConfigurationChanged (newConfig);

if (newConfig.Orientation == Android.Content.Res.Orientation.Portrait) {
_tv.LayoutParameters = _layoutParamsPortrait;
_tv.Text = "Changed to portrait";
} else if (newConfig.Orientation == Android.Content.Res.Orientation.Landscape) {
_tv.LayoutParameters = _layoutParamsLandscape;
_tv.Text = "Changed to landscape";
}
}
}

Aquí los TextView's parámetros de diseño se inicializan tanto horizontal como vertical. Las variables de clase
contienen los parámetros, junto TextView con el propio, ya que la actividad no se volverá a crear cuando cambie
la orientación. El código todavía utiliza surfaceOrientartion en OnCreate para establecer TextView el diseño
inicial de. Después, controla OnConfigurationChanged todos los cambios de diseño posteriores.
Cuando se ejecuta la aplicación, Android carga los cambios de la interfaz de usuario a medida que se produce la
rotación del dispositivo y no reinicia la actividad.

Impedir el reinicio de la actividad para los diseños declarativos


Los reinicios de actividad causados por la rotación de dispositivos también se pueden evitar si se define el diseño
en XML. Por ejemplo, se puede usar este enfoque si se desea evitar un reinicio de actividad (por razones de
rendimiento, quizás) y no es necesario cargar nuevos recursos para distintas orientaciones.
Para ello, sigue el mismo procedimiento que usamos con un diseño mediante programación. Simplemente
establezca ConfigurationChanges ActivityAttribute en, como hicimos en el CodeLayoutActivity anterior.
Cualquier código que deba ejecutarse para el cambio de orientación se puede implementar de nuevo en
OnConfigurationChanged el método.

Mantener el estado durante los cambios de orientación


Tanto si se controla la rotación de forma declarativa como mediante programación, todas las aplicaciones de
Android deben implementar las mismas técnicas para administrar el estado cuando cambia la orientación del
dispositivo. La administración del estado es importante porque el sistema reinicia una actividad en ejecución
cuando se gira un dispositivo Android. Android hace esto para facilitar la carga de recursos alternativos, como
diseños y drawables de elementos diseñados específicamente para una orientación determinada. Cuando se
reinicia, la actividad pierde cualquier estado transitorio que pueda haber almacenado en variables de clase local.
Por lo tanto, si una actividad depende del estado, debe conservar su estado en el nivel de la aplicación. Una
aplicación necesita controlar el guardado y la restauración de cualquier estado de aplicación que desee conservar
entre los cambios de orientación.
Para obtener más información sobre el estado persistente en Android, consulte la guía del ciclo de vida de la
actividad.

Resumen
En este artículo se explica cómo usar las capacidades integradas de Android para trabajar con la rotación. En
primer lugar, se explicó cómo usar el sistema de recursos de Android para crear aplicaciones con reconocimiento
de orientación. A continuación, se muestra cómo agregar controles en el código y cómo controlar los cambios de
orientación manualmente.

Vínculos relacionados
Demostración de rotación (ejemplo)
Ciclo de vida de la actividad
Control de los cambios en tiempo de ejecución
Cambio de orientación de pantalla rápida
Audio de Android
19/08/2019 • 20 minutes to read • Edit Online

El sistema operativo Android proporciona una amplia compatibilidad para multimedia, que engloba audio y
vídeo. Esta guía se centra en el audio en Android y trata la reproducción y grabación de audio mediante el
reproductor de audio integrado y las clases de grabadora, así como la API de audio de bajo nivel. También se
explica cómo trabajar con eventos de audio difundidos por otras aplicaciones, para que los desarrolladores
puedan compilar aplicaciones con el comportamiento correcto.

Información general
Los dispositivos móviles modernos han adoptado una funcionalidad que anteriormente habría requerido piezas
dedicadas – de cámaras de equipos, reproductores de música y grabadores de vídeo. Por este motivo, los marcos
multimedia se han convertido en una característica de primera clase en las API móviles.
Android proporciona una amplia compatibilidad con multimedia. En este artículo se examina el trabajo con audio
en Android y se tratan los temas siguientes:
1. Reproducir audio con MediaPlayer Usar la MediaPlayer clase integrada para reproducir audio, incluidos
los archivos de audio locales y los archivos de audio transmitidos AudioTrack con la clase. –
2. Grabar audio Usar la MediaRecorder clase integrada para grabar audio. –
3. Trabajar con notificaciones de audio – El uso de notificaciones de audio para crear aplicaciones con un
comportamiento correcto que respondan correctamente a eventos (por ejemplo, llamadas telefónicas
entrantes) al suspender o cancelar las salidas de audio.
4. Trabajar con audio de bajo nivel Reproducción de audio mediante AudioTrack la clase escribiendo
directamente en los búferes de memoria. – Grabar audio mediante la AudioRecord clase y leer directamente
desde los búferes de memoria.

Requisitos
En esta guía se requiere Android 2,0 (nivel de API 5) o posterior. Tenga en cuenta que la depuración de audio en
Android debe realizarse en un dispositivo.
Es necesario solicitar los RECORD_AUDIO permisos en archivo AndroidManifest. XML:
Reproducir audio con la clase MediaPlayer
La manera más sencilla de reproducir audio en Android es con la clase integrada MediaPlayer . MediaPlayer puede
reproducir archivos locales o remotos pasando la ruta de acceso del archivo. Sin embargo MediaPlayer , es muy
sensible al estado y al llamar a uno de sus métodos en un estado incorrecto se producirá una excepción. Es
importante interactuar con MediaPlayer en el orden que se describe a continuación para evitar errores.
Inicializar y reproducir
La reproducción de MediaPlayer audio con requiere la siguiente secuencia:
1. Cree una instancia de un nuevo objeto MediaPlayer .
2. Configure el archivo para que se reproduzca mediante el método SetDataSource .
3. Llame al método Prepare para inicializar el reproductor.
4. Llame al método Start para iniciar la reproducción de audio.
En el ejemplo de código siguiente se muestra este uso:
protected MediaPlayer player;
public void StartPlayer(String filePath)
{
if (player == null) {
player = new MediaPlayer();
} else {
player.Reset();
player.SetDataSource(filePath);
player.Prepare();
player.Start();
}
}

Suspender y reanudar la reproducción


La reproducción se puede suspender llamando al método PAUSE :

player.Pause();

Para reanudar la reproducción en pausa, llame al método Start . Esto se reanudará desde la ubicación en pausa en
la reproducción:

player.Start();

La llamada al método Stop en el reproductor finaliza una reproducción en curso:

player.Stop();

Cuando el reproductor ya no se necesita, se deben liberar los recursos llamando al método Release :

player.Release();

Uso de la clase MediaRecorder para grabar audio


El consecuencia MediaPlayer de la grabación de audio en Android es la clase MediaRecorder . Al igual que, es
sensible al estado y realiza transiciones a través de varios Estados para llegar al punto en el que puede comenzar a
grabar. MediaPlayer Para grabar audio, se debe establecer RECORD_AUDIO el permiso. Para obtener instrucciones
sobre cómo establecer permisos de aplicación, vea Working with archivo AndroidManifest. XML.
Inicializar y grabar
La grabación de audio MediaRecorder con requiere los pasos siguientes:
1. Cree una instancia de un nuevo objeto MediaRecorder .
2. Especifique el dispositivo de hardware que se va a usar para capturar la entrada de audio a través del
método SetAudioSource .
3. Establezca el formato de audio del archivo de salida mediante el método SetOutputFormat . Para obtener
una lista de los tipos de audio compatibles, vea formatos multimedia compatibles con Android.
4. Llame al método SetAudioEncoder para establecer el tipo de codificación de audio.
5. Llame al método SetOutputFile para especificar el nombre del archivo de salida en el que se escriben los
datos de audio.
6. Llame al método Prepare para inicializar la grabadora.
7. Llame al método Start para iniciar la grabación.
En el ejemplo de código siguiente se muestra esta secuencia:

protected MediaRecorder recorder;


void RecordAudio (String filePath)
{
try {
if (File.Exists (filePath)) {
File.Delete (filePath);
}
if (recorder == null) {
recorder = new MediaRecorder (); // Initial state.
} else {
recorder.Reset ();
recorder.SetAudioSource (AudioSource.Mic);
recorder.SetOutputFormat (OutputFormat.ThreeGpp);
recorder.SetAudioEncoder (AudioEncoder.AmrNb);
// Initialized state.
recorder.SetOutputFile (filePath);
// DataSourceConfigured state.
recorder.Prepare (); // Prepared state
recorder.Start (); // Recording state.
}
} catch (Exception ex) {
Console.Out.WriteLine( ex.StackTrace);
}
}

Detener la grabación
Para detener la grabación, llame Stop al método MediaRecorder en:

recorder.Stop();

Limpieza
Una vez que MediaRecorder se haya detenido, llame al método RESET para volver a ponerlo en su estado de
inactividad:

recorder.Reset();

Cuando MediaRecorder ya no se necesita, sus recursos deben liberarse llamando al método Release:

recorder.Release();

Administración de notificaciones de audio


La clase AudioManager
La clase AudioManager proporciona acceso a las notificaciones de audio que permiten a las aplicaciones saber
cuándo se producen los eventos de audio. Este servicio también proporciona acceso a otras características de
audio, como el control de volumen y de modo de timbre. Permite AudioManager que una aplicación controle las
notificaciones de audio para controlar la reproducción de audio.
Administrar el foco de audio
Los recursos de audio del dispositivo (la grabadora y el reproductor integrados) son compartidos por todas las
aplicaciones en ejecución.
Conceptualmente, esto es similar a las aplicaciones de un equipo de escritorio en el que solo una aplicación tiene el
foco de teclado: después de seleccionar una de las aplicaciones en ejecución al hacer clic en ella, la entrada del
teclado solo se dirige a esa aplicación.
El foco de audio es una idea similar y evita que más de una aplicación reproduzca o grabe audio al mismo tiempo.
Es más complicado que el foco de teclado porque es un – factor voluntario de que la aplicación puede omitir el
hecho de que actualmente no tiene el – foco de audio y se reproduce, ya que hay diferentes tipos de foco de audio
que se pueden requiere. Por ejemplo, si solo se espera que el solicitante reproduzca audio durante un tiempo muy
breve, puede solicitar el foco transitorio.
Se puede conceder el foco de audio inmediatamente, o bien denegarse y concederse en un momento posterior. Por
ejemplo, si una aplicación solicita el foco de audio durante una llamada telefónica, se le denegará, pero es posible
que se le conceda el foco una vez finalizada la llamada telefónica. En este caso, se registra un agente de escucha
para responder en consecuencia si se quita el foco de audio. La solicitud del foco de audio se usa para determinar
si es correcto reproducir o grabar audio.
Para obtener más información sobre el foco de audio, consulte Administración del foco de audio.
Registrar la devolución de llamada para el foco de audio
El registro de FocusChangeListener la devolución de IOnAudioChangeListener llamada desde es una parte
importante de la obtención y liberación del foco de audio. Esto se debe a que la concesión del foco de audio se
puede diferir hasta un momento posterior. Por ejemplo, una aplicación puede solicitar reproducir música mientras
hay una llamada de teléfono en curso. No se concederá el foco de audio hasta que finalice la llamada telefónica.
Por esta razón, el objeto GetAudioFocus AudioManager de devolución de llamada se pasa como un parámetro al
método de y es esta llamada que registra la devolución de llamada. Si el foco de audio se deniega inicialmente,
pero se concede posteriormente, la aplicación OnAudioFocusChange se informa invocando en la devolución de
llamada. Se usa el mismo método para indicar a la aplicación que se está quitando el foco de audio.
Cuando la aplicación ha terminado de usar los recursos AbandonFocus AudioManager de audio, llama al método de y
pasa de nuevo a la devolución de llamada. Esto anula el registro de la devolución de llamada y libera los recursos
de audio para que otras aplicaciones puedan obtener el foco de audio.
Solicitar el foco de audio
Los pasos necesarios para solicitar los recursos de audio del dispositivo son los siguientes:
1. Obtener un identificador para el AudioManager servicio de sistema.
2. Cree una instancia de la clase de devolución de llamada.
3. Solicite los recursos de audio del dispositivo llamando al RequestAudioFocus método AudioManager en. Los
parámetros son el objeto de devolución de llamada, el tipo de secuencia (música, llamada de voz, anillo, etc.)
y el tipo de derecho de acceso que se solicita (los recursos de audio se pueden solicitar momentáneamente
o durante un período indefinido, por ejemplo).
4. Si se concede la solicitud, el playMusic método se invoca inmediatamente y el audio comienza a
reproducirse.
5. Si se deniega la solicitud, no se realiza ninguna otra acción. En este caso, el audio solo se reproducirá si la
solicitud se concede en otro momento.
En el ejemplo de código siguiente se muestran estos pasos:
Boolean RequestAudioResources(INotificationReceiver parent)
{
AudioManager audioMan = (AudioManager) GetSystemService(Context.AudioService);
AudioManager.IOnAudioFocusChangeListener listener = new MyAudioListener(this);
var ret = audioMan.RequestAudioFocus (listener, Stream.Music, AudioFocus.Gain );
if (ret == AudioFocusRequest.Granted) {
playMusic();
return (true);
} else if (ret == AudioFocusRequest.Failed) {
return (false);
}
return (false);
}

Liberación del foco de audio


Cuando se completa la reproducción de la pista, se AbandonFocus invoca el AudioManager método en. Esto permite
a otra aplicación obtener los recursos de audio del dispositivo. Otras aplicaciones recibirán una notificación de este
cambio de foco de audio si han registrado sus propios agentes de escucha.

API de audio de bajo nivel


Las API de audio de bajo nivel proporcionan un mayor control sobre la reproducción y grabación de audio, ya que
interactúan directamente con los búferes de memoria en lugar de usar los URI de archivo. Hay algunos escenarios
en los que es preferible este enfoque. Estos escenarios incluyen:
1. Al reproducirse desde archivos de audio cifrados.
2. Al reproducir una sucesión de clips cortos.
3. Transmisión por secuencias de audio.
Clase AudioTrack
La clase AudioTrack utiliza las API de audio de bajo nivel para grabar y es el equivalente de bajo nivel de la
MediaPlayer clase.

Inicializar y reproducir
Para reproducir audio, se debe crear una AudioTrack nueva instancia de. La lista de argumentos que se pasa al
constructor especifica cómo reproducir el ejemplo de audio contenido en el búfer. Los argumentos son:
1. Tipo – de flujo voz, tono, música, sistema o alarma.
2. Frecuencia – : la frecuencia de muestreo expresada en Hz.
3. Mono o – estéreo de configuración del canal.
4. Formato – de audio de 8 bits o codificación de 16 bits.
5. Tamaño – de búfer en bytes.
6. Streaming – en modo de búfer o static.
Después de la construcción, se invoca el método Play de AudioTrack para configurarlo de modo que comience a
reproducirse. La escritura del búfer de audio AudioTrack en inicia la reproducción:
void PlayAudioTrack(byte[] audioBuffer)
{
AudioTrack audioTrack = new AudioTrack(
// Stream type
Stream.Music,
// Frequency
11025,
// Mono or stereo
ChannelOut.Mono,
// Audio encoding
Android.Media.Encoding.Pcm16bit,
// Length of the audio clip.
audioBuffer.Length,
// Mode. Stream or static.
AudioTrackMode.Stream);

audioTrack.Play();
audioTrack.Write(audioBuffer, 0, audioBuffer.Length);
}

Pausar y detener la reproducción


Llame al método PAUSE para pausar la reproducción:

audioTrack.Pause();

La llamada al método Stop terminará la reproducción de forma permanente:

audioTrack.Stop();

Reparación
Cuando AudioTrack ya no se necesita, sus recursos deben liberarse llamando a Release:

audioTrack.Release();

La clase AudioRecord
La clase AudioRecord es el equivalente de AudioTrack en el lado de grabación. Al AudioTrack igual que, usa
búferes de memoria directamente, en lugar de archivos y URI. Requiere que el RECORD_AUDIO permiso se
establezca en el manifiesto.
Inicializar y grabar
El primer paso consiste en construir un nuevo objeto AudioRecord . La lista de argumentos que se pasa al
constructor proporciona toda la información necesaria para la grabación. A diferencia de AudioTrack en, donde los
argumentos son en gran medida enumeraciones, los argumentos AudioRecord equivalentes en son enteros. Entre
ellas se incluyen las siguientes:
1. Origen de entrada de audio de hardware, como el micrófono.
2. Tipo – de flujo voz, tono, música, sistema o alarma.
3. Frecuencia – : la frecuencia de muestreo expresada en Hz.
4. Mono o – estéreo de configuración del canal.
5. Formato – de audio de 8 bits o codificación de 16 bits.
6. Tamaño de búfer: en bytes
Una vez construida, se invoca su método StartRecording. AudioRecord Ahora está listo para empezar a grabar. Lee
AudioRecord continuamente el búfer de audio para la entrada y escribe esta entrada en un archivo de audio.

void RecordAudio()
{
byte[] audioBuffer = new byte[100000];
var audRecorder = new AudioRecord(
// Hardware source of recording.
AudioSource.Mic,
// Frequency
11025,
// Mono or stereo
ChannelIn.Mono,
// Audio encoding
Android.Media.Encoding.Pcm16bit,
// Length of the audio clip.
audioBuffer.Length
);
audRecorder.StartRecording();
while (true) {
try
{
// Keep reading the buffer while there is audio input.
audRecorder.Read(audioBuffer, 0, audioBuffer.Length);
// Write out the audio file.
} catch (Exception ex) {
Console.Out.WriteLine(ex.Message);
break;
}
}
}

Detener la grabación
La llamada al método Stop finaliza la grabación:

audRecorder.Stop();

Reparación
Cuando el AudioRecord objeto ya no es necesario, al llamar a su método Release se liberan todos los recursos
asociados a él:

audRecorder.Release();

Resumen
El sistema operativo Android proporciona un marco de trabajo eficaz para reproducir, grabar y administrar audio.
En este artículo se ha explicado cómo reproducir y grabar audio mediante las MediaPlayer clases MediaRecorder y
de alto nivel. A continuación, se ha explorado cómo usar las notificaciones de audio para compartir los recursos de
audio del dispositivo entre las distintas aplicaciones. Por último, se trata de cómo reproducir y grabar audio
mediante las API de bajo nivel, que se interforman directamente con los búferes de memoria.

Vínculos relacionados
Trabajar con audio (ejemplo)
Media Player
Grabadora de medios
Administrador de audio
Pista de audio
Grabadora de audio
Notificaciones en Xamarin. Android
31/07/2019 • 3 minutes to read • Edit Online

En esta sección se explica cómo implementar notificaciones en Xamarin. Android. Describe los distintos
elementos de la interfaz de usuario de una notificación de Android y describe las API implicadas en la creación y
visualización de una notificación.

Notificaciones locales en Android


En esta sección se explica cómo implementar notificaciones locales en Xamarin. Android. Se describen los
distintos elementos de la interfaz de usuario de una notificación de Android y se describen las API relacionadas
con la creación y visualización de una notificación.

Tutorial: uso de notificaciones locales en Xamarin. Android


En este tutorial se explica cómo usar las notificaciones locales en una aplicación de Xamarin. Android. Muestra los
aspectos básicos de la creación y publicación de una notificación. Cuando el usuario hace clic en la notificación en
el cajón de notificaciones, inicia una segunda actividad.

Información adicional
Mensajería en la nube Firebase – Firebase Cloud Messaging (FCM ) es un servicio que facilita la mensajería entre
aplicaciones móviles y aplicaciones de servidor. La mensajería en la nube Firebase se puede usar para
implementar notificaciones remotas (también denominadas notificaciones de envío) en aplicaciones de Xamarin.
Android.
Notificaciones – Este tema de desarrollador de Android es la guía definitiva para las notificaciones de Android.
Incluye una sección de consideraciones de diseño que le ayuda a diseñar las notificaciones para que cumplan las
directrices de la interfaz de usuario de Android. Proporciona más información sobre la navegación previa al inicio
de una actividad y explica cómo mostrar el progreso en una notificación y controlar la reproducción multimedia
en la pantalla de bloqueo.
NotificationListenerService – Este servicio Android permite que la aplicación escuche (e interactúe con) todas las
notificaciones publicadas en el dispositivo Android, no solo las notificaciones que la aplicación está registrada
para recibir. Tenga en cuenta que el usuario debe conceder explícitamente permiso a la aplicación para que pueda
escuchar notificaciones en el dispositivo.

Vínculos relacionados
Notificaciones locales (ejemplo)
Notificaciones remotas (ejemplo)
Notificaciones locales en Android
19/08/2019 • 57 minutes to read • Edit Online

En esta sección se muestra cómo implementar notificaciones locales en Xamarin. Android. Se explican los
distintos elementos de la interfaz de usuario de una notificación de Android y se describen las API implicadas
en la creación y visualización de una notificación.

Información general sobre las notificaciones locales


Android proporciona dos áreas controladas por el sistema para mostrar los iconos de notificación y la
información de notificación al usuario. Cuando se publica una notificación por primera vez, su icono se
muestra en el área de notificación, tal como se muestra en la siguiente captura de pantalla:

Para obtener detalles sobre la notificación, el usuario puede abrir el cajón de notificaciones (que expande cada
icono de notificación para mostrar el contenido de la notificación) y realizar las acciones asociadas a las
notificaciones. En la captura de pantalla siguiente se muestra un cajón de notificaciones que se corresponde
con el área de notificación mostrada anteriormente:

Las notificaciones de Android usan dos tipos de diseños:


Diseño base – formato de presentación compacto y fijo.
Diseño expandido – un formato de presentación que se puede expandir hasta un tamaño mayor para
mostrar más información.
En las secciones siguientes se explica cada uno de estos tipos de diseño (y cómo crearlos).
NOTE
Esta guía se centra en las API de NotificationCompat de la biblioteca de compatibilidad de Android. Estas API
garantizarán la máxima compatibilidad con versiones anteriores de Android 4,0 (nivel de API 14).

Diseño base
Todas las notificaciones de Android se basan en el formato de diseño base, que, como mínimo, incluye los
siguientes elementos:
1. Un icono de notificación, que representa la aplicación de origen, o el tipo de notificación si la aplicación
admite distintos tipos de notificaciones.
2. El títulode la notificación o el nombre del remitente si la notificación es un mensaje personal.
3. Mensaje de notificación.
4. Marcade tiempo.
Estos elementos se muestran como se muestra en el diagrama siguiente:

Los diseños base se limitan a 64 píxeles independientes de densidad (DP ) en altura. Android crea este estilo de
notificación básico de forma predeterminada.
Opcionalmente, las notificaciones pueden mostrar un icono grande que representa la aplicación o la foto del
remitente. Cuando se usa un icono grande en una notificación en Android 5,0 y versiones posteriores, el icono
de notificación pequeña se muestra como un distintivo en el icono grande:

A partir de Android 5,0, las notificaciones también pueden aparecer en la pantalla de bloqueo:
El usuario puede hacer doble punteo en la notificación de la pantalla de bloqueo para desbloquear el
dispositivo y saltar a la aplicación que originó esa notificación, o bien deslizar para descartar la notificación. Las
aplicaciones pueden establecer el nivel de visibilidad de una notificación para controlar lo que se muestra en la
pantalla de bloqueo y los usuarios pueden elegir si desea que se muestre contenido confidencial en las
notificaciones de la pantalla de bloqueo.
Android 5,0 presentó un formato de presentación de notificaciones de alta prioridad denominado " Head -up".
Las notificaciones de los cabezales se desplazan hacia abajo desde la parte superior de la pantalla durante unos
segundos y, a continuación, se revierten al área de notificación:

Las notificaciones de cabezales permiten que la interfaz de usuario del sistema Coloque información
importante delante del usuario sin interrumpir el estado de la actividad que se está ejecutando actualmente.
Android incluye compatibilidad con los metadatos de notificación para que las notificaciones se puedan
ordenar y mostrar de manera inteligente. Los metadatos de notificación también controlan el modo en que se
presentan las notificaciones en la pantalla de bloqueo y en formato de cabeza. Las aplicaciones pueden
establecer los siguientes tipos de metadatos de notificación:
Prioridad de – El nivel de prioridad determina cómo y cuándo se presentan las notificaciones. Por
ejemplo, en Android 5,0, las notificaciones de alta prioridad se muestran como notificaciones de cabeza.
Visibilidad de – Especifica la cantidad de contenido de notificación que se va a mostrar cuando
aparezca la notificación en la pantalla de bloqueo.
Categoría de Informa al sistema de cómo controlar la notificación en varias circunstancias, como
cuando el dispositivo está en modo no molesta. –

NOTE
La visibilidad y la categoría se introdujeron en Android 5,0 y no están disponibles en versiones anteriores de Android.
A partir de Android 8,0, los canales de notificación se utilizan para controlar cómo se presentan las notificaciones al
usuario.

Diseños expandidos
A partir de Android 4,1, las notificaciones se pueden configurar con estilos de diseño expandidos que permiten
al usuario expandir el alto de la notificación para ver más contenido. Por ejemplo, en el ejemplo siguiente se
muestra una notificación de diseño expandida en modo de contrato:

Cuando se expande esta notificación, se revela todo el mensaje:

Android admite tres estilos de diseño expandidos para las notificaciones de evento único:
Big Text – En el modo de contrato, muestra un extracto de la primera línea del mensaje seguido de dos
puntos. En el modo expandido, muestra el mensaje completo (como se muestra en el ejemplo anterior).
Bandeja de entrada – En el modo de contrato, muestra el número de mensajes nuevos. En el modo
expandido, muestra el primer mensaje de correo electrónico o una lista de los mensajes en la bandeja de
entrada.
Imagen de – En el modo de contrato, solo muestra el texto del mensaje. En el modo expandido, muestra
el texto y una imagen.
Más allá de la notificación básica (más adelante en este artículo) se explica cómo crear notificaciones de texto,
de bandeja de entraday de imagen .

Canales de notificación
A partir de Android 8,0 (Oreo), puede usar la característica de canales de notificación para crear un canal
personalizable por el usuario para cada tipo de notificación que desea mostrar. Los canales de notificación
permiten agrupar las notificaciones para que todas las notificaciones enviadas a un canal presenten el mismo
comportamiento. Por ejemplo, podría tener un canal de notificación destinado a notificaciones que requieran
atención inmediata y un canal "más silencioso" independiente que se use para mensajes informativos.
La aplicación de YouTube que se instala con Android Oreo enumera dos categorías de notificación: Descargar
notificaciones y notificaciones generales:
Cada una de estas categorías corresponde a un canal de notificación. La aplicación de YouTube implementa un
canal de notificaciones de descarga y un canal de notificaciones generales . El usuario puede pulsar
Descargar notificaciones, que muestra la pantalla de configuración del canal de notificaciones de descarga
de la aplicación:
En esta pantalla, el usuario puede modificar el comportamiento del canal de las notificaciones de descarga
haciendo lo siguiente:
Establezca el nivel de importancia en urgente, alto, medioo bajo, lo que configura el nivel de
interrupción de sonido y visual.
Activar o desactivar el punto de notificación.
Activar o desactivar la luz intermitente.
Mostrar u ocultar notificaciones en la pantalla de bloqueo.
Invalide la configuración de no molestar .
El canal de notificaciones generales tiene una configuración similar:

Tenga en cuenta que no tiene control absoluto sobre el modo en que los canales de notificación – interactúan
con el usuario. el usuario puede modificar la configuración de cualquier canal de notificación en el dispositivo,
tal como se ve en las capturas de pantallas anteriores. Sin embargo, puede configurar los valores
predeterminados (como se describe a continuación). Como se muestra en estos ejemplos, la nueva
característica de canales de notificación permite proporcionar a los usuarios un mayor control sobre los
distintos tipos de notificaciones.

Creación de notificaciones
Para crear una notificación en Android, use la clase NotificationCompat. Builder del paquete NuGet Xamarin.
Android. support. V4 . Esta clase permite crear y publicar notificaciones en versiones anteriores de Android.
NotificationCompat.Builder también se describe.

NotificationCompat.Builder proporciona métodos para establecer las diversas opciones en una notificación,
como:
El contenido, incluido el título, el texto del mensaje y el icono de notificación.
Estilo de la notificación, como el estilo de texto grande, bandeja de entradao imagen .
La prioridad de la notificación: mínima, baja, predeterminada, alta o máxima. En Android 8,0 y versiones
posteriores, la prioridad se establece a través de un canal de notificación.
La visibilidad de la notificación en la pantalla de bloqueo: pública, privada o secreta.
Metadatos de categoría que ayudan a Android a clasificar y filtrar la notificación.
Una intención opcional que indica que una actividad se inicia cuando se puntea la notificación.
IDENTIFICADOR del canal de notificación en el que se publicará la notificación (Android 8,0 y
versiones posteriores).
Después de establecer estas opciones en el generador, se genera un objeto de notificación que contiene la
configuración. Para publicar la notificación, se pasa este objeto de notificación al Administradorde
notificaciones. Android proporciona la clase NotificationManager , que es responsable de publicar
notificaciones y mostrarla al usuario. Se puede obtener una referencia a esta clase desde cualquier contexto,
como una actividad o un servicio.
Creación de un canal de notificación
Las aplicaciones que se ejecutan en Android 8,0 deben crear un canal de notificación para las notificaciones. Un
canal de notificación requiere los tres datos siguientes:
Una cadena de identificador que es única para el paquete que identificará el canal.
Nombre del canal que se va a mostrar al usuario. El nombre debe tener entre 1 y 40 caracteres.
Importancia del canal.
Las aplicaciones deberán comprobar la versión de Android que se están ejecutando. Los dispositivos que
ejecutan versiones anteriores a Android 8,0 no deben crear un canal de notificación. El método siguiente es un
ejemplo de cómo crear un canal de notificación en una actividad:

void CreateNotificationChannel()
{
if (Build.VERSION.SdkInt < BuildVersionCodes.O)
{
// Notification channels are new in API 26 (and not a part of the
// support library). There is no need to create a notification
// channel on older versions of Android.
return;
}

var channelName = Resources.GetString(Resource.String.channel_name);


var channelDescription = GetString(Resource.String.channel_description);
var channel = new NotificationChannel(CHANNEL_ID, channelName, NotificationImportance.Default)
{
Description = channelDescription
};

var notificationManager = (NotificationManager) GetSystemService(NotificationService);


notificationManager.CreateNotificationChannel(channel);
}

Se debe crear el canal de notificación cada vez que se cree la actividad. En el CreateNotificationChannel caso
del método, debe llamarse en OnCreate el método de una actividad.
Crear y publicar una notificación
Para generar una notificación en Android, siga estos pasos:
1. Cree una instancia NotificationCompat.Builder de un objeto.
2. Llame a varios métodos en NotificationCompat.Builder el objeto para establecer las opciones de
notificación.
3. Llame al método Build del NotificationCompat.Builder objeto para crear una instancia de un objeto de
notificación.
4. Llame al método Notify del administrador de notificaciones para publicar la notificación.
Debe proporcionar al menos la siguiente información para cada notificación:
Un icono pequeño (24x24 DP de tamaño)
Un título corto
El texto de la notificación
En el ejemplo de código siguiente se muestra cómo NotificationCompat.Builder utilizar para generar una
notificación básica. Observe que los métodos NotificationCompat.Builder admiten el encadenamiento de
métodos; es decir, cada método devuelve el objeto de generador para que pueda usar el resultado de la última
llamada al método para invocar la siguiente llamada al método:

// Instantiate the builder and set notification elements:


NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
.SetContentTitle ("Sample Notification")
.SetContentText ("Hello World! This is my first notification!")
.SetSmallIcon (Resource.Drawable.ic_notification);

// Build the notification:


Notification notification = builder.Build();

// Get the notification manager:


NotificationManager notificationManager =
GetSystemService (Context.NotificationService) as NotificationManager;

// Publish the notification:


const int notificationId = 0;
notificationManager.Notify (notificationId, notification);

En este ejemplo, se crea NotificationCompat.Builder una instancia builder de un nuevo objeto denominado,
junto con el identificador del canal de notificación que se va a usar. Se establecen el título y el texto de la
notificación, y el icono de notificación se carga desde Resources /drawable/ic_notification. png. La llamada
al método del generador de Build notificaciones crea un objeto de notificación con esta configuración. El
siguiente paso consiste en llamar Notify al método del administrador de notificaciones. Para buscar el
administrador de notificaciones, GetSystemService llame a, como se mostró anteriormente.
El Notify método acepta dos parámetros: el identificador de notificación y el objeto de notificación. El
identificador de notificación es un entero único que identifica la notificación en la aplicación. En este ejemplo, el
identificador de notificación se establece en cero (0); sin embargo, en una aplicación de producción, querrá
asignar a cada notificación un identificador único. Reutilizar el valor del identificador anterior en una llamada a
Notify hace que se sobrescriba la última notificación.

Cuando este código se ejecuta en un dispositivo Android 5,0, genera una notificación similar a la del ejemplo
siguiente:
El icono de notificación se muestra en el lado izquierdo de la notificación – esta imagen de un “círculo tengo”
un canal alfa para que Android pueda dibujar un fondo circular gris detrás. También puede proporcionar un
icono sin un canal alfa. Para mostrar una imagen fotográfica como un icono, consulte formato de iconos
grandes más adelante en este tema.
La marca de tiempo se establece automáticamente, pero puede invalidar esta configuración mediante una
llamada al método SetWhen del generador de notificaciones. Por ejemplo, en el ejemplo de código siguiente se
establece la marca de tiempo en la hora actual:

builder.SetWhen (Java.Lang.JavaSystem.CurrentTimeMillis());

Habilitar sonido y vibración


Si desea que la notificación también emita un sonido, puede llamar al método SetDefaults del generador de
notificaciones y pasar la NotificationDefaults.Sound marca:

// Instantiate the notification builder and enable sound:


NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
.SetContentTitle ("Sample Notification")
.SetContentText ("Hello World! This is my first notification!")
.SetDefaults (NotificationDefaults.Sound)
.SetSmallIcon (Resource.Drawable.ic_notification);

Esta llamada a SetDefaults hará que el dispositivo reproduzca un sonido cuando se publique la notificación. Si
desea que el dispositivo vibra en lugar de reproducir un sonido, puede pasar NotificationDefaults.Vibrate a
SetDefaults. si desea que el dispositivo reproduzca un sonido y vibrar el dispositivo, puede pasar ambas
marcas a SetDefaults :

builder.SetDefaults (NotificationDefaults.Sound | NotificationDefaults.Vibrate);

Si habilita el sonido sin especificar un sonido para reproducir, Android usa el sonido predeterminado de la
notificación del sistema. Sin embargo, puede cambiar el sonido que se reproducirá llamando al método
SetSound del generador de notificaciones. Por ejemplo, para reproducir el sonido de alarma con la notificación
(en lugar del sonido de notificación predeterminado), puede obtener el URI del sonido de alarma desde el
RingtoneManager y pasarlo a SetSound :

builder.SetSound (RingtoneManager.GetDefaultUri(RingtoneType.Alarm));

Como alternativa, puede usar el sonido de tono predeterminado del sistema para su notificación:

builder.SetSound (RingtoneManager.GetDefaultUri(RingtoneType.Ringtone));

Después de crear un objeto de notificación, es posible establecer las propiedades de notificación en el objeto
de notificación (en lugar de configurarlos de antemano a través NotificationCompat.Builder de los métodos).
Por ejemplo, en lugar de llamar al SetDefaults método para habilitar la vibración en una notificación, puede
modificar directamente la marca de bits de la propiedad de valores predeterminados de la notificación:
// Build the notification:
Notification notification = builder.Build();

// Turn on vibrate:
notification.Defaults |= NotificationDefaults.Vibrate;

Este ejemplo hace que el dispositivo vibra cuando se publica la notificación.


Actualización de una notificación
Si desea actualizar el contenido de una notificación una vez publicada, puede volver a usar el objeto existente
NotificationCompat.Builder para crear un nuevo objeto de notificación y publicar esta notificación con el
identificador de la última notificación. Por ejemplo:

// Update the existing notification builder content:


builder.SetContentTitle ("Updated Notification");
builder.SetContentText ("Changed to this message.");

// Build a notification object with updated content:


notification = builder.Build();

// Publish the new notification with the existing ID:


notificationManager.Notify (notificationId, notification);

En este ejemplo, el objeto NotificationCompat.Builder existente se usa para crear un nuevo objeto de
notificación con un título y un mensaje distintos. El nuevo objeto de notificación se publica con el identificador
de la notificación anterior y esto actualiza el contenido de la notificación publicada anteriormente:

El cuerpo de la notificación anterior se reutiliza – solo el título y el texto de la notificación cambia mientras la
notificación se muestra en el cajón de notificaciones. El texto del título cambia de "notificación de ejemplo" a
"notificación actualizada" y el texto del mensaje cambia de "Hola mundo. Esta es mi primera notificación. en
"cambio a este mensaje".
Una notificación permanece visible hasta que se produce una de estas tres acciones:
El usuario descarta la notificación (o pulsa Borrar todo).
La aplicación realiza una llamada a NotificationManager.Cancel , pasando el identificador de notificación
único que se asignó cuando se publicó la notificación.
La aplicación llama NotificationManager.CancelAll a.

Para obtener más información sobre cómo actualizar las notificaciones de Android, consulte modificar una
notificación.
Inicio de una actividad a partir de una notificación
En Android, es habitual asociar una notificación a una acción – que se inicia cuando el usuario pulsa la
notificación. Esta actividad puede residir en otra aplicación o incluso en otra tarea. Para agregar una acción a
una notificación, se crea un objeto PendingIntent y se asocia PendingIntent con la notificación. Un
PendingIntent es un tipo especial de intención que permite a la aplicación de destinatario ejecutar un
fragmento de código predefinido con los permisos de la aplicación de envío. Cuando el usuario pulsa la
notificación, Android inicia la actividad especificada por PendingIntent .
El siguiente fragmento de código muestra cómo crear una notificación con un PendingIntent que iniciará la
actividad de la MainActivity aplicación de origen:

// Set up an intent so that tapping the notifications returns to this app:


Intent intent = new Intent (this, typeof(MainActivity));

// Create a PendingIntent; we're only using one PendingIntent (ID = 0):


const int pendingIntentId = 0;
PendingIntent pendingIntent =
PendingIntent.GetActivity (this, pendingIntentId, intent, PendingIntentFlags.OneShot);

// Instantiate the builder and set notification elements, including pending intent:
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
.SetContentIntent (pendingIntent)
.SetContentTitle ("Sample Notification")
.SetContentText ("Hello World! This is my first action notification!")
.SetSmallIcon (Resource.Drawable.ic_notification);

// Build the notification:


Notification notification = builder.Build();

// Get the notification manager:


NotificationManager notificationManager =
GetSystemService (Context.NotificationService) as NotificationManager;

// Publish the notification:


const int notificationId = 0;
notificationManager.Notify (notificationId, notification);

Este código es muy similar al código de notificación de la sección anterior, excepto en que PendingIntent se
agrega un al objeto de notificación. En este ejemplo, el PendingIntent está asociado a la actividad de la
aplicación de origen antes de pasarse al método SetContentIntent del generador de notificaciones. La
PendingIntentFlags.OneShot marca se pasa PendingIntent.GetActivity al método para que PendingIntent se
use solo una vez. Cuando se ejecuta este código, se muestra la siguiente notificación:

Al pulsar esta notificación, el usuario vuelve a la actividad de origen.


En una aplicación de producción, la aplicación debe controlar la pila de retroceso cuando el usuario presiona el
botón atrás dentro de la actividad de notificación (si no está familiarizado con las tareas de Android y la pila de
retroceso, consulte tareas y pila de retroceso). En la mayoría de los casos, la navegación hacia atrás de la
actividad de notificación debe devolver al usuario de la aplicación y volver a la pantalla principal. Para
administrar la pila de retroceso, la aplicación usa la clase TaskStackBuilder para crear PendingIntent un con
una pila de retroceso.
Otra consideración real es que la actividad de origen puede necesitar enviar datos a la actividad de notificación.
Por ejemplo, la notificación puede indicar que ha llegado un mensaje de texto, y la actividad de notificación
(una pantalla de visualización de mensajes), requiere el identificador del mensaje para mostrar el mensaje al
usuario. La actividad que crea el PendingIntent puede usar el método Intent . PutExtra para agregar datos (por
ejemplo, una cadena) al intento de modo que estos datos se pasen a la actividad de notificación.
En el ejemplo de código siguiente se muestra cómo TaskStackBuilder usar para administrar la pila de
retroceso y se incluye un ejemplo de cómo enviar una cadena de un solo mensaje a una actividad
SecondActivity de notificación denominada:
// Setup an intent for SecondActivity:
Intent secondIntent = new Intent (this, typeof(SecondActivity));

// Pass some information to SecondActivity:


secondIntent.PutExtra ("message", "Greetings from MainActivity!");

// Create a task stack builder to manage the back stack:


TaskStackBuilder stackBuilder = TaskStackBuilder.Create(this);

// Add all parents of SecondActivity to the stack:


stackBuilder.AddParentStack (Java.Lang.Class.FromType (typeof (SecondActivity)));

// Push the intent that starts SecondActivity onto the stack:


stackBuilder.AddNextIntent (secondIntent);

// Obtain the PendingIntent for launching the task constructed by


// stackbuilder. The pending intent can be used only once (one shot):
const int pendingIntentId = 0;
PendingIntent pendingIntent =
stackBuilder.GetPendingIntent (pendingIntentId, PendingIntentFlags.OneShot);

// Instantiate the builder and set notification elements, including


// the pending intent:
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
.SetContentIntent (pendingIntent)
.SetContentTitle ("Sample Notification")
.SetContentText ("Hello World! This is my second action notification!")
.SetSmallIcon (Resource.Drawable.ic_notification);

// Build the notification:


Notification notification = builder.Build();

// Get the notification manager:


NotificationManager notificationManager =
GetSystemService (Context.NotificationService) as NotificationManager;

// Publish the notification:


const int notificationId = 0;
notificationManager.Notify (notificationId, notification);

En este ejemplo de código, la aplicación consta de dos actividades MainActivity : (que contiene el código de
notificación anterior) SecondActivity , y la pantalla que el usuario ve después de puntear en la notificación.
Cuando se ejecuta este código, se presenta una notificación simple (similar al ejemplo anterior). Al pulsar la
notificación, el usuario SecondActivity recibe la pantalla:

El mensaje de cadena (que se pasa al PutExtra método de la intención) SecondActivity se recupera en a


través de esta línea de código:

// Get the message from the intent:


string message = Intent.Extras.GetString ("message", "");
Este mensaje recuperado, "Greetings from MainActivity!," se muestra SecondActivity en la pantalla, tal como
se muestra en la captura de pantalla anterior. Cuando el usuario presiona el botón atrás mientras está
SecondActivity en, la navegación conduce a la aplicación y vuelve a la pantalla anterior al inicio de la
aplicación.
Para obtener más información sobre la creación de intenciones pendientes, vea PendingIntent.

Más allá de la notificación básica


Las notificaciones tienen como valor predeterminado un formato de diseño base simple en Android, pero
puede mejorar este formato básico NotificationCompat.Builder realizando llamadas de método adicionales. En
esta sección, aprenderá a agregar un icono de foto grande a la notificación y verá ejemplos de cómo crear
notificaciones de diseño expandidas.
Formato de iconos grandes
Las notificaciones de Android suelen mostrar el icono de la aplicación de origen (en el lado izquierdo de la
notificación). Sin embargo, las notificaciones pueden mostrar una imagen o una foto (un icono grande) en
lugar del icono pequeño estándar. Por ejemplo, una aplicación de mensajería podría mostrar una foto del
remitente en lugar del icono de la aplicación.
Este es un ejemplo de una notificación – básica de Android 5,0 que muestra solo el icono de aplicación
pequeña:

Y a continuación se muestra una captura de pantalla de la notificación después de modificarla para – mostrar
un icono grande, se usa un icono creado a partir de una imagen de un Monkey de código Xamarin:

Tenga en cuenta que cuando se presenta una notificación en formato de iconos grandes, el icono de aplicación
pequeña se muestra como un distintivo en la esquina inferior derecha del icono grande.
Para usar una imagen como un icono grande en una notificación, se llama al método SetLargeIcon del
generador de notificaciones y se pasa un mapa de bits de la imagen. A diferencia SetSmallIcon de
SetLargeIcon , solo acepta un mapa de bits. Para convertir un archivo de imagen en un mapa de bits, se usa la
clase BitmapFactory . Por ejemplo:

builder.SetLargeIcon (BitmapFactory.DecodeResource (Resources, Resource.Drawable.monkey_icon));

Este código de ejemplo abre el archivo de imagen en Resources /drawable/monkey_icon. png, lo convierte
en un mapa de bits y pasa NotificationCompat.Builder el mapa de bits resultante a. Normalmente, la resolución
de la imagen de origen es mayor que – el icono pequeño pero no es mucho mayor. Una imagen demasiado
grande podría producir operaciones de cambio de tamaño innecesarias que podrían retrasar el envío de la
notificación.
Estilo de texto grande
El estilo de texto grande es una plantilla de diseño expandida que se usa para mostrar mensajes largos en las
notificaciones. Al igual que todas las notificaciones de diseño expandidas, la notificación de Big Text se muestra
inicialmente en un formato de presentación compacto:

En este formato, solo se muestra un extracto del mensaje, finalizado en dos puntos. Cuando el usuario arrastra
hacia abajo en la notificación, se expande para mostrar el mensaje de notificación completo:

Este formato de diseño expandido también incluye texto de resumen en la parte inferior de la notificación. El
alto máximo de la notificación de Big Text es 256 DP.
Para crear una notificación de texto grande , cree una instancia NotificationCompat.Builder de un objeto, como
antes, y, a continuación, cree una instancia y NotificationCompat.Builder agregue un objeto BigTextStyle al
objeto. Este es un ejemplo:

// Instantiate the Big Text style:


Notification.BigTextStyle textStyle = new Notification.BigTextStyle();

// Fill it with text:


string longTextMessage = "I went up one pair of stairs.";
longTextMessage += " / Just like me. ";
//...
textStyle.BigText (longTextMessage);

// Set the summary text:


textStyle.SetSummaryText ("The summary text goes here.");

// Plug this style into the builder:


builder.SetStyle (textStyle);

// Create the notification and publish it ...

En este ejemplo, el texto del mensaje y el texto de resumen se BigTextStyle almacenan textStyle en el objeto
() antes de pasarse a NotificationCompat.Builder.
Estilo de imagen
El estilo de imagen (también denominado estilo Big Picture ) es un formato de notificación expandido que se
puede usar para mostrar una imagen en el cuerpo de una notificación. Por ejemplo, una aplicación de captura
de pantalla o una aplicación fotográfica puede usar el estilo de notificación de imagen para proporcionar al
usuario una notificación de la última imagen capturada. Tenga en cuenta que el alto máximo de la notificación
de imagen – es 256 DP Android cambiará el tamaño de la imagen para ajustarse a esta restricción de alto
máximo, dentro de los límites de memoria disponible.
Al igual que todas las notificaciones de diseño expandidas, las notificaciones de imagen se muestran en primer
lugar en un formato compacto que muestra un extracto del texto del mensaje adjunto:
Cuando el usuario se arrastra hacia abajo en la notificación de imagen , se expande para mostrar una imagen.
Por ejemplo, esta es la versión expandida de la notificación anterior:

Tenga en cuenta que cuando la notificación se muestra en formato compacto, muestra el texto de la
notificación (el texto que se pasa al SetContentText método del generador de notificaciones, como se mostró
anteriormente). Sin embargo, cuando la notificación se expande para mostrar la imagen, muestra el texto de
resumen sobre la imagen.
Para crear una notificación de imagen , cree una instancia NotificationCompat.Builder de un objeto como
antes y, a continuación, cree e inserte un NotificationCompat.Builder objeto BigPictureStyle en el objeto. Por
ejemplo:

// Instantiate the Image (Big Picture) style:


Notification.BigPictureStyle picStyle = new Notification.BigPictureStyle();

// Convert the image to a bitmap before passing it into the style:


picStyle.BigPicture (BitmapFactory.DecodeResource (Resources, Resource.Drawable.x_bldg));

// Set the summary text that will appear with the image:
picStyle.SetSummaryText ("The summary text goes here.");

// Plug this style into the builder:


builder.SetStyle (picStyle);

// Create the notification and publish it ...

Al igual que el método SetLargeIcon de NotificationCompat.Builder , el método BigPicture de


BigPictureStyle requiere un mapa de bits de la imagen que desea mostrar en el cuerpo de la notificación. En
este ejemplo, el método DecodeResource de BitmapFactory lee el archivo de imagen ubicado en Resources
/drawable/x_bldg. png y lo convierte en un mapa de bits.
También puede mostrar imágenes que no están empaquetadas como un recurso. Por ejemplo, el siguiente
código de ejemplo carga una imagen desde la tarjeta SD local y la muestra en una notificación de imagen :
// Using the Image (Big Picture) style:
Notification.BigPictureStyle picStyle = new Notification.BigPictureStyle();

// Read an image from the SD card, subsample to half size:


BitmapFactory.Options options = new BitmapFactory.Options();
options.InSampleSize = 2;
string imagePath = "/sdcard/Pictures/my-tshirt.jpg";
picStyle.BigPicture (BitmapFactory.DecodeFile (imagePath, options));

// Set the summary text that will appear with the image:
picStyle.SetSummaryText ("Check out my new T-Shirt!");

// Plug this style into the builder:


builder.SetStyle (picStyle);

// Create notification and publish it ...

En este ejemplo, se carga el archivo de imagen que se encuentra en /sdcard/Pictures/My-Tshirt.jpg , se


cambia el tamaño a la mitad de su tamaño original y, a continuación, se convierte en un mapa de bits para su
uso en la notificación:

Si no conoce el tamaño del archivo de imagen de antemano, es una buena idea encapsular la llamada a
BitmapFactory. DecodeFile en un controlador – de excepciones. se OutOfMemoryError puede producir una
excepción si la imagen es demasiado grande para que Android cambie de tamaño.
Para obtener más información sobre cómo cargar y descodificar imágenes de mapa de bits de gran tamaño,
consulte carga eficaz de mapas de bits grandes.
Estilo de bandeja de entrada
El formato de bandeja de entrada es una plantilla de diseño expandida diseñada para mostrar líneas de texto
independientes (por ejemplo, un resumen de bandeja de entrada de correo electrónico) en el cuerpo de la
notificación. La notificación de formato de bandeja de entrada se muestra primero en un formato compacto:

Cuando el usuario arrastra hacia abajo en la notificación, se expande para mostrar un resumen de correo
electrónico como se muestra en la siguiente captura de pantalla:
Para crear una notificación de bandeja de entrada , cree NotificationCompat.Builder una instancia de un
objeto, como antes, y agregue un NotificationCompat.Builder objeto InboxStyle a. Este es un ejemplo:

// Instantiate the Inbox style:


Notification.InboxStyle inboxStyle = new Notification.InboxStyle();

// Set the title and text of the notification:


builder.SetContentTitle ("5 new messages");
builder.SetContentText ("chimchim@xamarin.com");

// Generate a message summary for the body of the notification:


inboxStyle.AddLine ("Cheeta: Bananas on sale");
inboxStyle.AddLine ("George: Curious about your blog post");
inboxStyle.AddLine ("Nikko: Need a ride to Evolve?");
inboxStyle.SetSummaryText ("+2 more");

// Plug this style into the builder:


builder.SetStyle (inboxStyle);

Para agregar nuevas líneas de texto al cuerpo de la notificación, llame al método AddLine del InboxStyle
objeto (el alto máximo de la notificación de bandeja de entrada es 256 DP ). Tenga en cuenta que, a diferencia
del estilo Big Text , el estilo Inbox es compatible con líneas de texto individuales en el cuerpo de la notificación.
También puede usar el estilo de bandeja de entrada para cualquier notificación que necesite Mostrar líneas
individuales de texto en un formato expandido. Por ejemplo, el estilo de notificación de bandeja de entrada se
puede usar para combinar varias notificaciones pendientes – en una notificación de resumen; puede actualizar
una única notificación de estilo de bandeja de entrada con nuevas líneas de contenido de notificación (consulte
Actualizar una notificación anterior), en lugar de generar una secuencia continua de notificaciones nuevas,
principalmente similares.

Configuración de metadatos
NotificationCompat.Builder incluye métodos a los que se puede llamar para establecer metadatos sobre la
notificación, como la prioridad, la visibilidad y la categoría. Android usa esta información — junto con la
configuración — de preferencias del usuario para determinar cómo y cuándo mostrar las notificaciones.
Configuración de prioridad
Las aplicaciones que se ejecutan en Android 7,1 y menos necesitan establecer la prioridad directamente en la
propia notificación. La configuración de prioridad de una notificación determina dos resultados cuando se
publica la notificación:
Donde aparece la notificación en relación con otras notificaciones. Por ejemplo, las notificaciones de
prioridad alta se presentan por encima de las notificaciones de prioridad inferior en el cajón de
notificaciones, independientemente de Cuándo se publicó cada notificación.
Si la notificación se muestra en el formato de notificación de cara al día (Android 5,0 y versiones
posteriores). Solo las notificaciones de prioridad alta y máxima se muestran como notificaciones de
suscripción.
Xamarin. Android define las siguientes enumeraciones para establecer la prioridad de la notificación:
NotificationPriority.Max – Alerta al usuario de una condición urgente o crítica (por ejemplo, una
llamada entrante, instrucciones para activar o una alerta de emergencia). En dispositivos Android 5,0 y
versiones posteriores, las notificaciones de prioridad máxima se muestran en el formato de cara arriba.
NotificationPriority.High – Informa al usuario de eventos importantes (como correos electrónicos
importantes o la llegada de mensajes de chat en tiempo real). En los dispositivos Android 5,0 y
versiones posteriores, las notificaciones de prioridad alta se muestran en formato de cara a arriba.
NotificationPriority.Default – Notifica al usuario las condiciones que tienen un nivel de importancia
medio.
NotificationPriority.Low – Para información no urgente a la que se debe informar al usuario (por
ejemplo, recordatorios de actualizaciones de software o actualizaciones de red social).
NotificationPriority.Min – Para obtener información general que el usuario solo advierte al ver las
notificaciones (por ejemplo, la información de ubicación o información meteorológica).
Para establecer la prioridad de una notificación, llame al método SetPriority del NotificationCompat.Builder
objeto, pasando el nivel de prioridad. Por ejemplo:

builder.SetPriority (NotificationPriority.High);

En el ejemplo siguiente, la notificación de alta prioridad, "un mensaje importante" aparece en la parte superior
del cajón de notificaciones:

Dado que se trata de una notificación de prioridad alta, también se muestra como una notificación de cara
arriba de la pantalla de actividad actual del usuario en Android 5,0:
En el ejemplo siguiente, se muestra la notificación de prioridad baja "pensamiento para el día" bajo una
notificación de nivel de batería de prioridad superior:

Dado que la notificación "pensamiento durante el día" es una notificación de prioridad baja, Android no la
mostrará en formato de cabeza.

NOTE
En Android 8,0 y versiones posteriores, la prioridad de la configuración del canal de notificación y del usuario
determinará la prioridad de la notificación.

Configuración de visibilidad
A partir de Android 5,0, la configuración de visibilidad está disponible para controlar la cantidad de contenido
de notificación que aparece en la pantalla de bloqueo seguro. Xamarin. Android define las siguientes
enumeraciones para establecer la visibilidad de la notificación:
NotificationVisibility.Public – El contenido completo de la notificación se muestra en la pantalla de
bloqueo seguro.
NotificationVisibility.Private – En la pantalla de bloqueo seguro solo se muestra información esencial
(por ejemplo, el icono de notificación y el nombre de la aplicación que la registró), pero el resto de los
detalles de la notificación están ocultos. Todas las notificaciones tienen NotificationVisibility.Private
como valor predeterminado.
NotificationVisibility.Secret – No se muestra nada en la pantalla de bloqueo seguro, ni siquiera en el
icono de notificación. El contenido de la notificación solo está disponible después de que el usuario
desbloquea el dispositivo.
Para establecer la visibilidad de una notificación, las aplicaciones llaman SetVisibility al método
NotificationCompat.Builder del objeto y pasan la configuración de visibilidad. Por ejemplo, esta llamada a
SetVisibility realiza la notificación Private :

builder.SetVisibility (NotificationVisibility.Private);

Cuando se Private envía una notificación, solo se muestra el nombre y el icono de la aplicación en la pantalla
de bloqueo seguro. En lugar del mensaje de notificación, el usuario ve "desbloquear el dispositivo para ver esta
notificación":
En este ejemplo, NotificationsLab es el nombre de la aplicación de origen. Esta versión censurada de la
notificación solo aparece cuando la pantalla de bloqueo es segura (es decir, protegida mediante PIN, patrón o
contraseña) – si la pantalla de bloqueo no es segura, el contenido completo de la notificación está disponible en
la pantalla de bloqueo.
Configuración de categorías
A partir de Android 5,0, las categorías predefinidas están disponibles para clasificar y filtrar las notificaciones.
Xamarin. Android proporciona las siguientes enumeraciones para estas categorías:
Notification.CategoryCall – Llamada telefónica entrante.
Notification.CategoryMessage – Mensaje de texto entrante.
Notification.CategoryAlarm – Una condición de alarma o una expiración del temporizador.
Notification.CategoryEmail – Mensaje de correo electrónico entrante.
Notification.CategoryEvent – Un evento de calendario.
Notification.CategoryPromo – Un mensaje o anuncio promocional.
Notification.CategoryProgress – Progreso de una operación en segundo plano.
Notification.CategorySocial – Actualización de redes sociales.
Notification.CategoryError – Error de una operación en segundo plano o proceso de autenticación.
Notification.CategoryTransport – Actualización de reproducción de medios.
Notification.CategorySystem – Reservado para uso del sistema (estado del sistema o del dispositivo).
Notification.CategoryService – Indica que se está ejecutando un servicio en segundo plano.
Notification.CategoryRecommendation – Un mensaje de recomendación relacionado con la aplicación que
se está ejecutando actualmente.
Notification.CategoryStatus – Información sobre el dispositivo.

Cuando se ordenan las notificaciones, la prioridad de la notificación tiene prioridad sobre la configuración de la
categoría. Por ejemplo, una notificación de alta prioridad se mostrará como un aviso, incluso si pertenece a la
Promo categoría. Para establecer la categoría de una notificación, se llama al SetCategory método
NotificationCompat.Builder del objeto, pasando el valor de la categoría. Por ejemplo:

builder.SetCategory (Notification.CategoryCall);

La característica no molestar (novedad en Android 5,0) filtra las notificaciones en función de las categorías. Por
ejemplo, la pantalla no molestar en configuración permite al usuario excluir las notificaciones de llamadas
telefónicas y mensajes:
Cuando el usuario configura no molesta para bloquear todas las interrupciones excepto las llamadas
telefónicas (como se muestra en la captura de pantalla anterior), Android permite que se presenten
notificaciones con un valor de categoría de Notification.CategoryCall cuando el dispositivo está en nomodo
de molestar. Tenga en Notification.CategoryAlarm cuenta que las notificaciones no se bloquean nunca en el
modo no molestar.
En el ejemplo LocalNotifications se muestra cómo NotificationCompat.Builder usar para iniciar una segunda
actividad desde una notificación. Este código de ejemplo se explica en el tutorial uso de notificaciones locales
en Xamarin. Android .
Estilos de notificación
Para crear notificaciones de estilo Big Text, Imageo Inbox en NotificationCompat.Builder la bandeja de entrada
con, la aplicación debe usar las versiones de compatibilidad de estos estilos. Por ejemplo, para usar el estilo Big
Text , cree una NotificationCompat.BigTextstyle instancia de:

NotificationCompat.BigTextStyle textStyle = new NotificationCompat.BigTextStyle();

// Plug this style into the builder:


builder.SetStyle (textStyle);

Del mismo modo, la aplicación NotificationCompat.InboxStyle puede NotificationCompat.BigPictureStyle usar


y para los estilos de imagen y bandeja de entrada , respectivamente.
Categoría y prioridad de la notificación
NotificationCompat.Builder admite el SetPriority método (disponible a partir de Android 4,1 ). Sin embargo,
SetCategory el método no es compatible NotificationCompat.Builder con porque las categorías forman parte
del nuevo sistema de metadatos de notificación que se presentó en Android 5,0.
Para admitir versiones anteriores de Android, donde SetCategory no está disponible, el código puede
comprobar el nivel de API en tiempo de ejecución para SetCategory llamar condicionalmente cuando el nivel
de API es igual o mayor que Android 5,0 (nivel de API 21):

if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.Lollipop) {


builder.SetCategory (Notification.CategoryEmail);
}

En este ejemplo, la plataforma de destino de la aplicación está establecida en Android 5,0 y la versión
mínima de Android está establecida en Android 4,1 (nivel de API 16) . Dado SetCategory que está
disponible en el nivel de API 21 y versiones posteriores, este SetCategory código de ejemplo solo llamará
cuando esté disponible SetCategory – ; no se llamará cuando el nivel de API sea inferior a 21.
Visibilidad de la pantalla de bloqueo
Dado que Android no admitía las notificaciones de la pantalla de bloqueo antes de Android 5,0
NotificationCompat.Builder (nivel de API SetVisibility 21 ), no admite el método. Como se explicó
anteriormente SetCategory para, el código puede comprobar el nivel de API en tiempo SetVisiblity de
ejecución y llamar solo cuando está disponible:

if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.Lollipop) {


builder.SetVisibility (Notification.Public);
}

Resumen
En este artículo se explica cómo crear notificaciones locales en Android. Se ha descrito la anatomía de una
notificación, se ha explicado NotificationCompat.Builder cómo usar para crear notificaciones, cómo aplicar
estilo a las notificaciones en los formatos de iconos grandes, de texto grande, de imágenes y de bandeja de
entrada , cómo establecer la configuración de los metadatos de notificación, como prioridad, visibilidad y
categoría, y cómo iniciar una actividad desde una notificación. En este artículo también se describe cómo
funciona esta configuración de notificaciones con las nuevas características de cabeza de seguridad, pantalla de
bloqueo y no molestar que se introdujeron en Android 5,0. Por último, aprendió a usar
NotificationCompat.Builder para mantener la compatibilidad con las notificaciones con versiones anteriores de
Android.
Para obtener instrucciones sobre el diseño de notificaciones para Android, vea Notificaciones.

Vínculos relacionados
NotificationsLab (ejemplo)
LocalNotifications (ejemplo)
Tutorial de notificaciones locales en Android
Notificar al usuario
Aviso
NotificationManager
NotificationCompat.Builder
PendingIntent
Tutorial: uso de notificaciones locales en Xamarin.
Android
31/07/2019 • 9 minutes to read • Edit Online

En este tutorial se muestra cómo usar las notificaciones locales en las aplicaciones de Xamarin. Android. Muestra
los aspectos básicos de la creación y publicación de una notificación local. Cuando el usuario hace clic en la
notificación en el área de notificación, inicia una segunda actividad.

Información general
En este tutorial, se creará una aplicación de Android que genera una notificación cuando el usuario hace clic en un
botón de una actividad. Cuando el usuario hace clic en la notificación, inicia una segunda actividad que muestra el
número de veces que el usuario hizo clic en el botón de la primera actividad.
En las siguientes capturas de pantallas se muestran algunos ejemplos de esta aplicación:

NOTE
Esta guía se centra en las API de NotificationCompat de la biblioteca de compatibilidad de Android. Estas API garantizarán la
máxima compatibilidad con versiones anteriores de Android 4,0 (nivel de API 14).

Crear el proyecto
Para empezar, vamos a crear un nuevo proyecto de Android con la plantilla de aplicación de Android . Vamos a
llamar a este proyecto LocalNotifications. (Si no está familiarizado con la creación de proyectos de Xamarin.
Android, consulte Hello, Android).
Edite el archivo de recursos Values/Strings. XML para que contenga dos recursos de cadena adicionales que se
usarán cuando sea el momento de crear el canal de notificación:
<?xml version="1.0" encoding="utf-8"?>

<resources>
<string name="Hello">Hello World, Click Me!</string>
<string name="ApplicationName">Notifications</string>

<string name="channel_name">Local Notifications</string>


<string name="channel_description">The count from MainActivity.</string>
</resources>

Adición del paquete de NuGet Android. support. V4


En este tutorial, estamos usando NotificationCompat.Builder para compilar nuestra notificación local. Tal como se
explica en las notificaciones locales, debemos incluir la biblioteca de compatibilidad de Android V4 NuGet en
NotificationCompat.Builder nuestro proyecto para usar.

A continuación, vamos a editar MainActivity.CS y agregaremos using la siguiente instrucción para que los
Android.Support.V4.App tipos de estén disponibles para nuestro código:

using Android.Support.V4.App;

Además, debemos aclarar el compilador que estamos usando la Android.Support.V4.App versión de en lugar de
TaskStackBuilder la Android.App versión. Agregue la siguiente using instrucción para resolver cualquier
ambigüedad:

using TaskStackBuilder = Android.Support.V4.App.TaskStackBuilder;

Crear el canal de notificación


A continuación, agregue un método MainActivity a que creará un canal de notificación (si es necesario):

void CreateNotificationChannel()
{
if (Build.VERSION.SdkInt < BuildVersionCodes.O)
{
// Notification channels are new in API 26 (and not a part of the
// support library). There is no need to create a notification
// channel on older versions of Android.
return;
}

var name = Resources.GetString(Resource.String.channel_name);


var description = GetString(Resource.String.channel_description);
var channel = new NotificationChannel(CHANNEL_ID, name, NotificationImportance.Default)
{
Description = description
};

var notificationManager = (NotificationManager) GetSystemService(NotificationService);


notificationManager.CreateNotificationChannel(channel);
}

Actualice el OnCreate método para llamar a este nuevo método:


protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);

CreateNotificationChannel();
}

Definir el identificador de notificación


Se necesitará un identificador único para el canal de notificación y notificación. Vamos a editar MainActivity.CS y
agregaremos la siguiente variable de instancia estática MainActivity a la clase:

static readonly int NOTIFICATION_ID = 1000;


static readonly string CHANNEL_ID = "location_notification";
internal static readonly string COUNT_KEY = "count";

Agregar código para generar la notificación


A continuación, es necesario crear un nuevo controlador de eventos para el Click evento de botón. Agregue el
método siguiente a MainActivity :

void ButtonOnClick(object sender, EventArgs eventArgs)


{
// Pass the current button press count value to the next activity:
var valuesForActivity = new Bundle();
valuesForActivity.PutInt(COUNT_KEY, count);

// When the user clicks the notification, SecondActivity will start up.
var resultIntent = new Intent(this, typeof(SecondActivity));

// Pass some values to SecondActivity:


resultIntent.PutExtras(valuesForActivity);

// Construct a back stack for cross-task navigation:


var stackBuilder = TaskStackBuilder.Create(this);
stackBuilder.AddParentStack(Class.FromType(typeof(SecondActivity)));
stackBuilder.AddNextIntent(resultIntent);

// Create the PendingIntent with the back stack:


var resultPendingIntent = stackBuilder.GetPendingIntent(0, (int) PendingIntentFlags.UpdateCurrent);

// Build the notification:


var builder = new NotificationCompat.Builder(this, CHANNEL_ID)
.SetAutoCancel(true) // Dismiss the notification from the notification area when the user
clicks on it
.SetContentIntent(resultPendingIntent) // Start up this activity when the user clicks the
intent.
.SetContentTitle("Button Clicked") // Set the title
.SetNumber(count) // Display the count in the Content Info
.SetSmallIcon(Resource.Drawable.ic_stat_button_click) // This is the icon to display
.SetContentText($"The button has been clicked {count} times."); // the message to display.

// Finally, publish the notification:


var notificationManager = NotificationManagerCompat.From(this);
notificationManager.Notify(NOTIFICATION_ID, builder.Build());

// Increment the button press count:


count++;
}

El OnCreate método de MainActivity debe hacer la llamada para crear el canal de notificación y asignar
ButtonOnClick el método al Click evento del botón (Reemplace el controlador de eventos de delegado que
proporciona la plantilla):

protected override void OnCreate(Bundle bundle)


{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);

CreateNotificationChannel();

// Display the "Hello World, Click Me!" button and register its event handler:
var button = FindViewById<Button>(Resource.Id.MyButton);
button.Click += ButtonOnClick;
}

Crear una segunda actividad


Ahora es necesario crear otra actividad que Android mostrará cuando el usuario haga clic en la notificación.
Agregue otra actividad de Android al proyecto denominado SecondActivity. Abra SecondActivity.CS y
reemplace su contenido por este código:

using System;
using Android.App;
using Android.OS;
using Android.Widget;

namespace LocalNotifications
{
[Activity(Label = "Second Activity")]
public class SecondActivity : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);

// Get the count value passed to us from MainActivity:


var count = Intent.Extras.GetInt(MainActivity.COUNT_KEY, -1);

// No count was passed? Then just return.


if (count <= 0)
{
return;
}

// Display the count sent from the first activity:


SetContentView(Resource.Layout.Second);
var txtView = FindViewById<TextView>(Resource.Id.textView1);
txtView.Text = $"You clicked the button {count} times in the previous activity.";
}
}
}

También debemos crear un diseño de recursos para SecondActivity. Agregue un nuevo archivo de diseño de
Android a su proyecto denominado Second. axml. Edite Second. axml y pegue el siguiente código de diseño:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:minWidth="25px"
android:minHeight="25px">
<TextView
android:text=""
android:textAppearance="?android:attr/textAppearanceLarge"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/textView1" />
</LinearLayout>

Icono Agregar un aviso


Por último, agregue un icono pequeño que aparecerá en el área de notificación cuando se inicie la notificación.
Puede copiar este icono en el proyecto o crear su propio icono personalizado. Asigne el nombre archivo de_icono
IC_STAT_Button click. png y cópielo en la carpeta Resources /drawable . No olvide usar agregar > elemento
existente... para incluir este archivo de icono en el proyecto.
Ejecución de la aplicación
Compile y ejecute la aplicación. Debería aparecer la primera actividad, similar a la siguiente captura de pantalla:

Al hacer clic en el botón, debe observar que el icono pequeño de la notificación aparece en el área de notificación:
Si desliza el dedo hacia abajo y expone el cajón de notificaciones, debería ver la notificación:

Al hacer clic en la notificación, debe desaparecer y la otra actividad debe iniciarse – en un aspecto similar al de la
siguiente captura de pantalla:
Felicidades. En este punto, ha completado el tutorial de notificaciones locales de Android y tiene un ejemplo en
funcionamiento al que puede hacer referencia. Hay muchas más notificaciones que se han mostrado aquí, por lo
que si desea más información, eche un vistazo a la documentación de Google sobrelas notificaciones.

Resumen
Este tutorial se NotificationCompat.Builder usa para crear y Mostrar notificaciones. Mostraba un ejemplo básico
de cómo iniciar una segunda actividad como una manera de responder a la interacción del usuario con la
notificación y demostró la transferencia de datos de la primera actividad a la segunda actividad.

Vínculos relacionados
LocalNotifications (ejemplo)
Canales de notificación de Android Oreo
Aviso
NotificationManager
NotificationCompat.Builder
PendingIntent
Toque y gestos en Xamarin. Android
16/08/2019 • 4 minutes to read • Edit Online

Las pantallas táctiles en muchos de los dispositivos de hoy en día permiten a los usuarios interactuar de forma
rápida y eficaz con los dispositivos de una manera natural e intuitiva. Esta interacción no se limita solo a la sencilla
detección táctil: también es posible usar movimientos. Por ejemplo, el gesto de acercamiento a zoom es un
ejemplo muy común de esto al reducir una parte de la pantalla con dos dedos que el usuario puede acercar o
alejar. En esta guía se examinan los gestos táctiles y en Android.

Información general táctil


iOS y Android son similares en las maneras en que controlan el toque. Ambos pueden admitir puntos de contacto
con varios toques en los gestos complejos y de pantalla. En esta guía se presentan algunas de las similitudes en los
conceptos, así como las peculiaridades de la implementación de funciones táctiles y gestos en ambas plataformas.
Android usa un MotionEvent objeto para encapsular los datos táctiles y métodos en el objeto de vista para
escuchar los toques.
Además de capturar los datos táctiles, tanto iOS como Android proporcionan medios para interpretar los patrones
de los toques en los gestos. Estos reconocedores de gestos se pueden usar a su vez para interpretar comandos
específicos de la aplicación, como un giro de una imagen o un turno de una página. Android proporciona una serie
de gestos admitidos, así como recursos para facilitar la adición de gestos personalizados complejos.
Tanto si trabaja en Android o iOS, la elección entre los reconocedores de gestos y los toques puede ser una
confusión. En esta guía se recomienda que, en general, se proporcione la preferencia a los reconocedores de
gestos. Los reconocedores de gestos se implementan como clases discretas, que proporcionan una mayor
separación de preocupaciones y una mejor encapsulación. Esto facilita el uso compartido de la lógica entre
diferentes vistas, lo que reduce la cantidad de código escrito.
En esta guía se sigue un formato similar para cada sistema operativo: en primer lugar, se introducen y explican las
API táctiles de la plataforma, ya que son la base sobre la que se compilan las interacciones táctiles. A continuación,
profundizamos en el mundo de los reconocedores de gestos: primero, explorando algunos gestos comunes y
terminando con la creación de gestos personalizados para las aplicaciones. Por último, verá cómo realizar un
seguimiento de los dedos individuales mediante el seguimiento táctil de bajo nivel para crear un programa de
pintado con el dedo.

Secciones
Entrada táctil de Android
Tutorial: Uso de Touch en Android
Seguimiento multitáctil

Resumen
En esta guía se ha examinado el toque en Android. En ambos sistemas operativos, hemos aprendido a habilitar
Touch y a responder a los eventos Touch. A continuación, hemos aprendido sobre los gestos y algunos de los
reconocedores de gestos que proporcionan Android e iOS para administrar algunos de los escenarios más
comunes. Hemos examinado cómo crear gestos personalizados e implementarlos en aplicaciones. En un tutorial se
han mostrado los conceptos y las API de cada sistema operativo en acción, y también se ha visto cómo realizar un
seguimiento de los dedos individuales.
Vínculos relacionados
Inicio táctil de Android (ejemplo)
Android Touch final (ejemplo)
Pintura (ejemplo)
Entrada táctil de Android
16/08/2019 • 12 minutes to read • Edit Online

De forma similar a iOS, Android crea un objeto que contiene datos sobre la interacción física del usuario con – la
Android.View.MotionEvent pantalla de un objeto. Este objeto contiene datos, como la acción que se lleva a cabo,
dónde tuvo lugar el toque, cuánta presión se aplicó, etc. Un MotionEvent objeto divide el movimiento en hasta los
valores siguientes:
Código de acción que describe el tipo de movimiento, como el toque inicial, el movimiento táctil a través de
la pantalla o la finalización táctil.
Un conjunto de valores de eje que describen la posición de MotionEvent y otras propiedades de
movimiento, como el lugar en el que se está llevando a cabo el toque, Cuándo tuvo lugar el toque y cuánta
presión se usó. Los valores de los ejes pueden variar en función del dispositivo, por lo que en la lista anterior
no se describen todos los valores de los ejes.
El MotionEvent objeto se pasará a un método adecuado en una aplicación. Hay tres maneras de que una aplicación
de Xamarin. Android responda a un evento Touch:
Asignar un controlador de eventos View.Touch a : Android.Views.View la clase tiene
EventHandler<View.TouchEventArgs> una a la que las aplicaciones pueden asignar un controlador. Este es un
comportamiento típico de .NET.
Implementar View.IOnTouchListener : las instancias de esta interfaz pueden asignarse a un objeto de vista
mediante la vista. SetOnListener forma. Es funcionalmente equivalente a asignar un controlador de eventos
al View.Touch evento. Si hay algunas lógicas comunes o compartidas que pueden necesitar muchas vistas
diferentes cuando se tocan, será más eficaz crear una clase e implementar este método que asignar cada
vista a su propio controlador de eventos.
Override View.OnTouchEvent : todas las vistas de la subclase Android.Views.View de Android. Cuando se toca
una vista, Android llama a OnTouchEvent y le pasa un MotionEvent objeto como parámetro.

NOTE
No todos los dispositivos Android admiten pantallas táctiles.

Al agregar la siguiente etiqueta al archivo de manifiesto, Google Play solo muestra la aplicación en los dispositivos
que están habilitados para tocar:

<uses-configuration android:reqTouchScreen="finger" />

Gestos
Un gesto es una forma dibujada a mano en la pantalla táctil. Los gestos pueden tener uno o varios trazos, cada uno
de los cuales consta de una secuencia de puntos creados por un punto de contacto distinto con la pantalla. Android
puede admitir muchos tipos diferentes de gestos, desde un Fling simple a través de la pantalla, a gestos complejos
que implican múltiples toques.
Android proporciona el Android.Gestures espacio de nombres específicamente para administrar y responder a los
gestos. En el corazón de todos los gestos hay una clase especial Android.Gestures.GestureDetector denominada.
Como implica el nombre, esta clase escuchará los movimientos y eventos en función de MotionEvents los
proporcionados por el sistema operativo.
Para implementar un detector de gestos, una actividad debe crear GestureDetector instancias de una clase y
proporcionar IOnGestureListener una instancia de, como se muestra en el siguiente fragmento de código:

GestureOverlayView.IOnGestureListener myListener = new MyGestureListener();


_gestureDetector = new GestureDetector(this, myListener);

Una actividad también debe implementar OnTouchEvent y pasar MotionEvent al detector de gestos. En el
fragmento de código siguiente se muestra un ejemplo de esto:

public override bool OnTouchEvent(MotionEvent e)


{
// This method is in an Activity
return _gestureDetector.OnTouchEvent(e);
}

Cuando una instancia de GestureDetector identifica un movimiento de interés, se lo notificará a la actividad o


aplicación mediante la generación de un evento o a través GestureDetector.IOnGestureListener de una devolución
de llamada proporcionada por. Esta interfaz proporciona seis métodos para los distintos gestos:
Down : se llama cuando se produce una derivación, pero no se libera.
OnFling : se le llama cuando se produce una Fling y proporciona datos sobre el toque inicial y final que
desencadenó el evento.
OnLongPress : se le llama cuando se produce una presión larga.
Onscroll : se llama cuando se produce un evento de desplazamiento.
OnShowPress : se le llama después de que se haya producido una excepción y no se ha realizado un evento
de movimiento o de arriba.
OnSingleTapUp : se le llama cuando se produce un solo punteo.
En muchos casos, las aplicaciones solo pueden estar interesadas en un subconjunto de gestos. En este caso, las
aplicaciones deben extender la clase GestureDetector. SimpleOnGestureListener e invalidar los métodos que
corresponden a los eventos que le interesan.

Gestos personalizados
Los gestos son una excelente manera de que los usuarios puedan interactuar con una aplicación. Las API que
vimos hasta ahora serían suficientes para los gestos sencillos, pero podrían resultar un poco onerosos para gestos
más complicados. Para ayudar con gestos más complicados, Android proporciona otro conjunto de API en el
espacio de nombres de Android. gestos que facilitará parte de la carga asociada a los gestos personalizados.
Crear gestos personalizados
Desde Android 1,6, la Android SDK incluye una aplicación preinstalada en el emulador llamado gestos de gestos.
Esta aplicación permite a los desarrolladores crear gestos predefinidos que se pueden incrustar en una aplicación.
En la captura de pantalla siguiente se muestra un ejemplo de gestos del generador:
Se puede encontrar una versión mejorada de esta aplicación denominada herramienta de gestos Google Play. La
herramienta de gestos es muy similar al generador de gestos, salvo que le permite probar los gestos después de
haberlos creado. En la siguiente captura de pantalla se muestra el generador de gestos:
La herramienta de gestos es un poco más útil para crear gestos personalizados, ya que permite que los gestos se
prueben a medida que se crean y que se pueden acceder fácilmente a través de Google Play.
La herramienta de gestos le permite crear un gesto dibujando en la pantalla y asignando un nombre. Una vez
creados los gestos, se guardan en un archivo binario en la tarjeta SD del dispositivo. Este archivo debe recuperarse
desde el dispositivo y, a continuación, empaquetarse con una aplicación en la carpeta/Resources/RAW. Este archivo
se puede recuperar desde el emulador mediante el Android Debug Bridge. En el ejemplo siguiente se muestra
cómo copiar el archivo de un archivo de Galaxy Nexus en el directorio de recursos de una aplicación:

$ adb pull /storage/sdcard0/gestures <projectdirectory>/Resources/raw

Una vez que haya recuperado el archivo, se debe empaquetar con la aplicación en el directorio/Resources/RAW. La
forma más fácil de usar este archivo de gestos es cargar el archivo en un GestureLibrary, como se muestra en el
siguiente fragmento de código:

GestureLibrary myGestures = GestureLibraries.FromRawResources(this, Resource.Raw.gestures);


if (!myGestures.Load())
{
// The library didn't load, so close the activity.
Finish();
}

Usar gestos personalizados


Para reconocer gestos personalizados en una actividad, debe tener un objeto Android. gesto. GestureOverlay
agregado a su diseño. En el fragmento de código siguiente se muestra cómo agregar un GestureOverlayView a
una actividad mediante programación:

GestureOverlayView gestureOverlayView = new GestureOverlayView(this);


gestureOverlayView.AddOnGesturePerformedListener(this);
SetContentView(gestureOverlayView);

El siguiente fragmento XML muestra cómo agregar un GestureOverlayView mediante declaración:

<android.gesture.GestureOverlayView
android:id="@+id/gestures"
android:layout_width="match_parent "
android:layout_height="match_parent" />

GestureOverlayView Tiene varios eventos que se producirán durante el proceso de dibujo de un gesto. El evento
más interesante es GesturePerformed . Este evento se desencadena cuando el usuario ha terminado de dibujar su
gesto.
Cuando se genera este evento, la actividad pide GestureLibrary a que pruebe y haga coincidir el gesto que el
usuario con uno de los gestos creados por la herramienta de gestos. GestureLibrary devolverá una lista de objetos
de predicción.
Cada objeto de predicción contiene una puntuación y el nombre de uno de los gestos GestureLibrary en. Cuanto
mayor sea la puntuación, mayor será la probabilidad de que el gesto mencionado en la predicción coincida con el
gesto dibujado por el usuario. Por lo general, las puntuaciones inferiores a 1,0 se consideran malas coincidencias.
En el código siguiente se muestra un ejemplo de coincidencia de un gesto:
private void GestureOverlayViewOnGesturePerformed(object sender, GestureOverlayView.GesturePerformedEventArgs
gesturePerformedEventArgs)
{
// In this example _gestureLibrary was instantiated in OnCreate
IEnumerable<Prediction> predictions = from p in
_gestureLibrary.Recognize(gesturePerformedEventArgs.Gesture)
orderby p.Score descending
where p.Score > 1.0
select p;
Prediction prediction = predictions.FirstOrDefault();

if (prediction == null)
{
Log.Debug(GetType().FullName, "Nothing matched the user's gesture.");
return;
}

Toast.MakeText(this, prediction.Name, ToastLength.Short).Show();


}

Una vez hecho esto, debe tener conocimientos sobre cómo usar los gestos táctiles y en una aplicación de Xamarin.
Android. Vamos a pasar a un tutorial y ver todos los conceptos de una aplicación de ejemplo en funcionamiento.

Vínculos relacionados
Inicio táctil de Android (ejemplo)
Android Touch final (ejemplo)
Tutorial: uso de Touch en Android
16/08/2019 • 15 minutes to read • Edit Online

Vamos a ver cómo usar los conceptos de la sección anterior en una aplicación en funcionamiento. Crearemos una
aplicación con cuatro actividades. La primera actividad será un menú o un panel de tareas que iniciará las otras
actividades para mostrar las distintas API. En la captura de pantalla siguiente se muestra la actividad principal:

La primera actividad, ejemplo táctil, mostrará cómo usar controladores de eventos para tocar las vistas. En la
actividad del reconocedor de gestos se Android.View.Views muestra cómo subclases y control de eventos, así
como cómo controlar los gestos de pinch. La tercera y última actividad, el gesto personalizado, mostrará cómo
usar gestos personalizados. Para que los elementos sean más fáciles de seguir y absorber, vamos a desglosar este
tutorial en secciones, donde cada sección se centra en una de las actividades.

Actividad de ejemplo táctil


Abra el proyecto TouchWalkthrough_iniciar. La MainActivity está configurada para – que se
implemente el comportamiento táctil en la actividad. Si ejecuta la aplicación y hace clic en el ejemplo
Touch, debe iniciarse la siguiente actividad:
Ahora que hemos confirmado que la actividad se inicia, abra el archivo TouchActivity.CS y agregue un
controlador para el Touch evento del: ImageView

_touchMeImageView.Touch += TouchMeImageViewOnTouch;

A continuación, agregue el método siguiente a TouchActivity.CS:

private void TouchMeImageViewOnTouch(object sender, View.TouchEventArgs touchEventArgs)


{
string message;
switch (touchEventArgs.Event.Action & MotionEventActions.Mask)
{
case MotionEventActions.Down:
case MotionEventActions.Move:
message = "Touch Begins";
break;

case MotionEventActions.Up:
message = "Touch Ends";
break;

default:
message = string.Empty;
break;
}

_touchInfoTextView.Text = message;
}

Observe que en el código anterior se trata la Move acción Down y como la misma. Esto se debe a que, aunque el
usuario no levante el ImageView dedo, puede desplazarse o la presión ejercida por el usuario puede cambiar. Estos
tipos de cambios generarán una Move acción.
Cada vez que el usuario toca ImageView el, Touch se generará el evento y el controlador mostrará el mensaje el
toque comienza en la pantalla, tal como se muestra en la siguiente captura de pantalla:

Siempre que el usuario toque el ImageView , se mostrará la entrada táctil en el. TextView Cuando el usuario ya
no toca el ImageView , se mostrarán los extremos del mensaje en el TextView , tal y como se muestra en la
siguiente captura de pantalla:
Actividad de reconocedor de gestos
Ahora permite implementar la actividad del reconocedor de gestos. Esta actividad mostrará cómo arrastrar una
vista alrededor de la pantalla y mostrar una manera de implementar el acercamiento a zoom.
Agregue una nueva actividad a la aplicación denominada GestureRecognizer . Edite el código de esta
actividad para que sea similar al código siguiente:

public class GestureRecognizerActivity : Activity


{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
View v = new GestureRecognizerView(this);
SetContentView(v);
}
}

Agregue una nueva vista de Android al proyecto y asígnele el nombre GestureRecognizerView . Agregue las
siguientes variables a esta clase:
private static readonly int InvalidPointerId = -1;

private readonly Drawable _icon;


private readonly ScaleGestureDetector _scaleDetector;

private int _activePointerId = InvalidPointerId;


private float _lastTouchX;
private float _lastTouchY;
private float _posX;
private float _posY;
private float _scaleFactor = 1.0f;

Agregue el siguiente constructor a GestureRecognizerView . Este constructor agregará ImageView a nuestra


actividad. En este punto el código todavía no se compilará – es necesario crear la clase MyScaleListener que
le ayudará a cambiar el tamaño de la ImageView cuando el usuario pinche:

public GestureRecognizerView(Context context): base(context, null, 0)


{
_icon = context.Resources.GetDrawable(Resource.Drawable.Icon);
_icon.SetBounds(0, 0, _icon.IntrinsicWidth, _icon.IntrinsicHeight);
_scaleDetector = new ScaleGestureDetector(context, new MyScaleListener(this));
}

Para dibujar la imagen en nuestra actividad, es necesario invalidar el OnDraw método de la clase de vista, tal
y como se muestra en el siguiente fragmento de código. Este código moverá ImageView a la posición
especificada por _posX y _posY también cambiará el tamaño de la imagen según el factor de escala:

protected override void OnDraw(Canvas canvas)


{
base.OnDraw(canvas);
canvas.Save();
canvas.Translate(_posX, _posY);
canvas.Scale(_scaleFactor, _scaleFactor);
_icon.Draw(canvas);
canvas.Restore();
}

A continuación deberá actualizar la variable de instancia _scaleFactor como el usuario pinche el


ImageView . Agregaremos una clase denominada MyScaleListener . Esta clase realizará escuchas para los
eventos de escala que se generará Android cuando el usuario pinche el ImageView . Agregue la siguiente
clase interna a GestureRecognizerView . Esta clase es un ScaleGesture.SimpleOnScaleGestureListener . Esta
clase es una clase útil que los agentes de escucha pueden subclases cuando está interesado en un
subconjunto de gestos:
private class MyScaleListener : ScaleGestureDetector.SimpleOnScaleGestureListener
{
private readonly GestureRecognizerView _view;

public MyScaleListener(GestureRecognizerView view)


{
_view = view;
}

public override bool OnScale(ScaleGestureDetector detector)


{
_view._scaleFactor *= detector.ScaleFactor;

// put a limit on how small or big the image can get.


if (_view._scaleFactor > 5.0f)
{
_view._scaleFactor = 5.0f;
}
if (_view._scaleFactor < 0.1f)
{
_view._scaleFactor = 0.1f;
}

_view.Invalidate();
return true;
}
}

El método siguiente que se debe invalidar GestureRecognizerView en OnTouchEvent es. En el código


siguiente se muestra la implementación completa de este método. Aquí hay una gran cantidad de código,
por lo que Tómese un minuto y mire lo que está ocurriendo aquí. Lo primero que hace este método es
escalar el icono si – es necesario para controlarlo _scaleDetector.OnTouchEvent mediante una llamada a. A
continuación, se intenta averiguar qué acción llamó a este método:
Si el usuario toca la pantalla con, registramos las posiciones X e y y el identificador del primer
puntero que toca la pantalla.
Si el usuario ha mudado su toque en la pantalla, se averigua hasta qué punto el usuario ha pasado el
puntero.
Si el usuario ha quitado el dedo de la pantalla, se dejará de realizar el seguimiento de los gestos.
public override bool OnTouchEvent(MotionEvent ev)
{
_scaleDetector.OnTouchEvent(ev);

MotionEventActions action = ev.Action & MotionEventActions.Mask;


int pointerIndex;

switch (action)
{
case MotionEventActions.Down:
_lastTouchX = ev.GetX();
_lastTouchY = ev.GetY();
_activePointerId = ev.GetPointerId(0);
break;

case MotionEventActions.Move:
pointerIndex = ev.FindPointerIndex(_activePointerId);
float x = ev.GetX(pointerIndex);
float y = ev.GetY(pointerIndex);
if (!_scaleDetector.IsInProgress)
{
// Only move the ScaleGestureDetector isn't already processing a gesture.
float deltaX = x - _lastTouchX;
float deltaY = y - _lastTouchY;
_posX += deltaX;
_posY += deltaY;
Invalidate();
}

_lastTouchX = x;
_lastTouchY = y;
break;

case MotionEventActions.Up:
case MotionEventActions.Cancel:
// We no longer need to keep track of the active pointer.
_activePointerId = InvalidPointerId;
break;

case MotionEventActions.PointerUp:
// check to make sure that the pointer that went up is for the gesture we're tracking.
pointerIndex = (int) (ev.Action & MotionEventActions.PointerIndexMask) >> (int)
MotionEventActions.PointerIndexShift;
int pointerId = ev.GetPointerId(pointerIndex);
if (pointerId == _activePointerId)
{
// This was our active pointer going up. Choose a new
// action pointer and adjust accordingly
int newPointerIndex = pointerIndex == 0 ? 1 : 0;
_lastTouchX = ev.GetX(newPointerIndex);
_lastTouchY = ev.GetY(newPointerIndex);
_activePointerId = ev.GetPointerId(newPointerIndex);
}
break;

}
return true;
}

Ejecute ahora la aplicación e inicie la actividad del reconocedor de gestos. Cuando se inicia, la pantalla debe
tener un aspecto similar al de la siguiente captura de pantalla:
Ahora, toque el icono y arrástrelo alrededor de la pantalla. Pruebe el gesto de alejar para zoom. En algún
momento la pantalla puede tener un aspecto similar al de la siguiente captura de pantalla:

Llegados a este punto, debe tener una Pat en la parte trasera: acaba de implementar el acercamiento a zoom en
una aplicación Android. Realice un salto rápido y le permite pasar a la tercera y última actividad de este tutorial –
mediante gestos personalizados.
Actividad de gestos personalizados
La última pantalla de este tutorial usará gestos personalizados.
Para los fines de este tutorial, la biblioteca de gestos ya se ha creado con la herramienta de gestos y se ha
agregado al proyecto en los recursos de archivo /raw/movimientos. Con este poco de mantenimiento fuera del
camino, le permite realizar la actividad final en el tutorial.
Agregue un archivo de diseño denominado_diseño_de gestos personalizados. axml al proyecto con el
siguiente contenido. El proyecto ya tiene todas las imágenes en la carpeta de recursos :

<?xml version="1.0" encoding="utf-8"?>


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<ImageView
android:src="@drawable/check_me"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="3"
android:id="@+id/imageView1"
android:layout_gravity="center_vertical" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>

A continuación, CustomGestureRecognizerActivity.cs agregue una nueva actividad al proyecto y asígnele el


nombre. Agregue dos variables de instancia a la clase, tal y como se muestra en las dos líneas de código
siguientes:

private GestureLibrary _gestureLibrary;


private ImageView _imageView;

Edite OnCreate el método de esta actividad para que sea similar al código siguiente. Dedique un minuto a
explicar lo que sucede en este código. Lo primero que hacemos es crear una GestureOverlayView instancia
de y establecerla como la vista raíz de la actividad. También se asigna un controlador de eventos al
GesturePerformed evento de GestureOverlayView . A continuación, se infla el archivo de diseño creado
anteriormente y se agrega como una vista secundaria de GestureOverlayView . El paso final consiste en
inicializar la _gestureLibrary variable y cargar el archivo de gestos de los recursos de la aplicación. Si el
archivo de gestos no se puede cargar por alguna razón, no se pueden realizar muchas de estas actividades,
por lo que se cierra:
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);

GestureOverlayView gestureOverlayView = new GestureOverlayView(this);


SetContentView(gestureOverlayView);
gestureOverlayView.GesturePerformed += GestureOverlayViewOnGesturePerformed;

View view = LayoutInflater.Inflate(Resource.Layout.custom_gesture_layout, null);


_imageView = view.FindViewById<ImageView>(Resource.Id.imageView1);
gestureOverlayView.AddView(view);

_gestureLibrary = GestureLibraries.FromRawResource(this, Resource.Raw.gestures);


if (!_gestureLibrary.Load())
{
Log.Wtf(GetType().FullName, "There was a problem loading the gesture library.");
Finish();
}
}

Lo último que debemos hacer es implementar el método GestureOverlayViewOnGesturePerformed como se


muestra en el siguiente fragmento de código. GestureOverlayView Cuando detecta un gesto, vuelve a llamar
a este método. Lo primero que se intenta para obtener IList<Prediction> los objetos que coinciden con el
gesto es llamar _gestureLibrary.Recognize() a. Usamos un bit de LINQ para obtener el Prediction que
tenga la puntuación más alta para el gesto.
Si no hay ningún movimiento coincidente con una puntuación lo suficientemente alta, el controlador de
eventos se cierra sin hacer nada. En caso contrario, se comprueba el nombre de la predicción y se cambia la
imagen que se muestra en función del nombre del gesto:

private void GestureOverlayViewOnGesturePerformed(object sender,


GestureOverlayView.GesturePerformedEventArgs gesturePerformedEventArgs)
{
IEnumerable<Prediction> predictions = from p in
_gestureLibrary.Recognize(gesturePerformedEventArgs.Gesture)
orderby p.Score descending
where p.Score > 1.0
select p;
Prediction prediction = predictions.FirstOrDefault();

if (prediction == null)
{
Log.Debug(GetType().FullName, "Nothing seemed to match the user's gesture, so don't do
anything.");
return;
}

Log.Debug(GetType().FullName, "Using the prediction named {0} with a score of {1}.",


prediction.Name, prediction.Score);

if (prediction.Name.StartsWith("checkmark"))
{
_imageView.SetImageResource(Resource.Drawable.checked_me);
}
else if (prediction.Name.StartsWith("erase", StringComparison.OrdinalIgnoreCase))
{
// Match one of our "erase" gestures
_imageView.SetImageResource(Resource.Drawable.check_me);
}
}

Ejecute la aplicación e inicie la actividad del reconocedor de gestos personalizado. Debe ser similar a la
siguiente captura de pantalla:

Ahora dibuje una marca de verificación en la pantalla y el mapa de bits que se muestra debería tener un
aspecto similar al que se muestra en las siguientes capturas de pantalla:
Por último, dibuje un garabato en la pantalla. La casilla debe volver a cambiar a su imagen original, tal como
se muestra en estas capturas de pantallas:
Ahora conoce cómo integrar Touch y gestos en una aplicación Android con Xamarin. Android.

Vínculos relacionados
Inicio táctil de Android (ejemplo)
Android Touch final (ejemplo)
Seguimiento de dedo multitáctil
31/07/2019 • 10 minutes to read • Edit Online

En este tema se muestra cómo realizar un seguimiento de los eventos táctiles de varios dedos
Hay ocasiones en las que una aplicación multitáctil necesita realizar un seguimiento de los dedos individuales
mientras se mueven simultáneamente en la pantalla. Una aplicación típica es un programa de pintado de dedos.
Quiere que el usuario pueda dibujar con un solo dedo, pero también para dibujar varios dedos a la vez. A medida
que el programa procesa varios eventos táctiles, debe distinguir qué eventos corresponden a cada dedo. Android
proporciona un código de identificador para este propósito, pero obtener y controlar ese código puede ser un poco
complicado.
Para todos los eventos asociados a un dedo determinado, el código de identificador sigue siendo el mismo. El
código de identificador se asigna cuando un dedo toca primero la pantalla y deja de ser válido después de que el
dedo se levante de la pantalla. Estos códigos de identificador suelen ser enteros muy pequeños y Android los
vuelve a usar para eventos de toque posteriores.
Casi siempre, un programa que realiza un seguimiento de los dedos individuales mantiene un diccionario para el
seguimiento táctil. La clave del diccionario es el código de ID. que identifica un dedo determinado. El valor del
diccionario depende de la aplicación. En el programa de pintura , cada trazo de dedo (de toque a lanzamiento) se
asocia a un objeto que contiene toda la información necesaria para representar la línea dibujada con ese dedo. El
programa define una clase FingerPaintPolyline pequeña para este propósito:

class FingerPaintPolyline
{
public FingerPaintPolyline()
{
Path = new Path();
}

public Color Color { set; get; }

public float StrokeWidth { set; get; }

public Path Path { private set; get; }


}

Cada Polyline tiene un color, un ancho de trazo y un objeto de Path gráficos Android para acumular y representar
varios puntos de la línea mientras se dibujan.
El resto del código que se muestra a continuación se encuentra View en un FingerPaintCanvasView derivado
denominado. Esa clase mantiene un diccionario de objetos de tipo FingerPaintPolyline en el momento en el que
se dibujan activamente con uno o varios dedos:

Dictionary<int, FingerPaintPolyline> inProgressPolylines = new Dictionary<int, FingerPaintPolyline>();

Este diccionario permite a la vista obtener rápidamente la FingerPaintPolyline información asociada a un dedo
determinado.
La FingerPaintCanvasView clase también mantiene un List objeto para las polilíneas que se han completado:
List<FingerPaintPolyline> completedPolylines = new List<FingerPaintPolyline>();

Los objetos de esta List se encuentran en el mismo orden en que se dibujaron.


FingerPaintCanvasView invalida dos métodos definidos por View : OnDraw y OnTouchEvent . En su OnDraw
invalidación, la vista dibuja las polilíneas completadas y, a continuación, dibuja las polilíneas en curso.
La invalidación del OnTouchEvent método comienza obteniendo un pointerIndex valor de la ActionIndex
propiedad. Este ActionIndex valor distingue entre varios dedos, pero no es coherente en varios eventos. Por ese
motivo, se usa pointerIndex para obtener el valor del puntero id del GetPointerId método. Este identificador es
coherente en varios eventos:

public override bool OnTouchEvent(MotionEvent args)


{
// Get the pointer index
int pointerIndex = args.ActionIndex;

// Get the id to identify a finger over the course of its progress


int id = args.GetPointerId(pointerIndex);

// Use ActionMasked here rather than Action to reduce the number of possibilities
switch (args.ActionMasked)
{
// ...
}

// Invalidate to update the view


Invalidate();

// Request continued touch input


return true;
}

Observe que la invalidación utiliza ActionMasked la propiedad en switch la instrucción en lugar Action de la
propiedad. El motivo es el siguiente:
Cuando se trabaja con multi- Action Touch, la propiedad tiene un valor de MotionEventsAction.Down para que el
primer dedo toque la pantalla y, a continuación, los valores Pointer3Down de Pointer2Down y como segundo y
tercero tocan también la pantalla. A medida que los dedos cuarto y quinto hacen contacto Action , la propiedad
tiene valores numéricos que no se corresponden con MotionEventsAction los miembros de la enumeración. Debe
examinar los valores de las marcas de bits en los valores para interpretar lo que significan.
Del mismo modo, cuando los dedos dejen el contacto con la Action pantalla, la propiedad Pointer2Up tiene
Pointer3Up los valores y para los dedos segundo y Up tercero, y para el primer dedo.

La ActionMaskedpropiedad toma un número de valores menor porque está diseñado para usarse junto con la
ActionIndex propiedad para diferenciar entre varios dedos. Cuando los dedos tocan la pantalla, la propiedad solo
MotionEventActions.Down puede ser igual para el PointerDown primer dedo y para los dedos posteriores. Cuando
los dedos salen de la pantalla ActionMasked , tiene valores Pointer1Up de para los dedos posteriores Up y para el
primer dedo.
Cuando se ActionMasked usa ActionIndex , distingue entre los dedos siguientes para tocar y salir de la pantalla,
pero normalmente no es necesario usar ese valor excepto como argumento MotionEvent para otros métodos del
objeto. En el caso de la funcionalidad multitáctil, se GetPointerId llama a uno de los más importantes de estos
métodos en el código anterior. Este método devuelve un valor que puede usar para que una clave de diccionario
asocie eventos determinados a los dedos.
La OnTouchEvent invalidación en el programa pintura procesa MotionEventActions.Down los PointerDown eventos y
de forma idéntica creando un FingerPaintPolyline nuevo objeto y agregándolo al diccionario:

public override bool OnTouchEvent(MotionEvent args)


{
// Get the pointer index
int pointerIndex = args.ActionIndex;

// Get the id to identify a finger over the course of its progress


int id = args.GetPointerId(pointerIndex);

// Use ActionMasked here rather than Action to reduce the number of possibilities
switch (args.ActionMasked)
{
case MotionEventActions.Down:
case MotionEventActions.PointerDown:

// Create a Polyline, set the initial point, and store it


FingerPaintPolyline polyline = new FingerPaintPolyline
{
Color = StrokeColor,
StrokeWidth = StrokeWidth
};

polyline.Path.MoveTo(args.GetX(pointerIndex),
args.GetY(pointerIndex));

inProgressPolylines.Add(id, polyline);
break;
// ...
}
// ...
}

Observe que pointerIndex también se usa para obtener la posición del dedo dentro de la vista. Toda la
información táctil está asociada con el pointerIndex valor. Identifica de forma única los dedos en varios mensajes,
por lo que se usa para crear la entrada del diccionario. id
Del mismo modo OnTouchEvent , la invalidación MotionEventActions.Up también Pointer1Up controla y de forma
idéntica mediante la transferencia de la completedPolylines Polyline completada a la colección para que OnDraw se
puedan dibujar durante la invalidación. El código también quita la id entrada del diccionario:
public override bool OnTouchEvent(MotionEvent args)
{
// ...
switch (args.ActionMasked)
{
// ...
case MotionEventActions.Up:
case MotionEventActions.Pointer1Up:

inProgressPolylines[id].Path.LineTo(args.GetX(pointerIndex),
args.GetY(pointerIndex));

// Transfer the in-progress polyline to a completed polyline


completedPolylines.Add(inProgressPolylines[id]);
inProgressPolylines.Remove(id);
break;

case MotionEventActions.Cancel:
inProgressPolylines.Remove(id);
break;
}
// ...
}

Ahora para la parte complicada.


Entre los eventos Down y up, normalmente hay muchos MotionEventActions.Move eventos. Estas se agrupan en
una sola llamada a OnTouchEvent , y deben administrarse de manera diferente a Down los Up eventos y. Se
pointerIndex debe omitir el valor ActionIndex obtenido anteriormente de la propiedad. En su lugar, el método
debe obtener pointerIndex varios valores mediante un bucle entre 0 y PointerCount la propiedad y, a
continuación id , obtener una para pointerIndex cada uno de esos valores:

public override bool OnTouchEvent(MotionEvent args)


{
// ...
switch (args.ActionMasked)
{
// ...
case MotionEventActions.Move:

// Multiple Move events are bundled, so handle them differently


for (pointerIndex = 0; pointerIndex < args.PointerCount; pointerIndex++)
{
id = args.GetPointerId(pointerIndex);

inProgressPolylines[id].Path.LineTo(args.GetX(pointerIndex),
args.GetY(pointerIndex));
}
break;
// ...
}
// ...
}

Este tipo de procesamiento permite que el programa de pintura realice un seguimiento de los dedos individuales y
dibuje los resultados en la pantalla:
Ahora ha visto cómo puede realizar el seguimiento de los dedos individuales en la pantalla y distinguirlos.

Vínculos relacionados
Guía de Xamarin iOS equivalente
Pintura (ejemplo)
Selector de implementación de la pila HttpClient y
SSL/TLS para Android
16/08/2019 • 9 minutes to read • Edit Online

Los selectores de la pila HttpClient y de la implementación de SSL/TLS determinan la implementación de


HttpClient y SSL/TLS que usarán las aplicaciones de Xamarin. Android.
Los proyectos deben hacer referencia al ensamblado System .net. http .

WARNING
Abril de 2018 : debido a los mayores requisitos de seguridad, incluido el cumplimiento de PCI, los principales proveedores
en la nube y los servidores Web se espera que dejen de admitir versiones de TLS anteriores a 1,2. Los proyectos de Xamarin
creados en versiones anteriores de Visual Studio usan de forma predeterminada versiones anteriores de TLS.
Para asegurarse de que las aplicaciones continúan funcionando con estos servidores y servicios, debe actualizar los
proyectos de Xamarin Android HttpClient con la configuración de y Native TLS 1.2 que se muestra a
continuación, y volver a compilar y volver a implementar las aplicaciones para los usuarios.

Visual Studio
Visual Studio para Mac
La configuración de HttpClient. Android está en Opciones de proyecto > opciones de Androidy, a
continuación, haga clic en el botón Opciones avanzadas .
Esta es la configuración recomendada para la compatibilidad con TLS 1,2:

Opciones de configuración alternativas


AndroidClientHandler
AndroidClientHandler es el nuevo controlador que delega en código nativo de Java/OS en lugar de implementar
todo en código administrado. Esta es la opción recomendada.
Profesionales ti
Use la API nativa para mejorar el rendimiento y el tamaño de los archivos ejecutables más pequeños.
Compatibilidad con los estándares más recientes, por ejemplo, TLS 1.2.
Iconos
Requiere Android 4,1 o posterior.
Algunas opciones y características de HttpClient no están disponibles.
Administrado (HttpClientHandler)
El controlador administrado es el controlador HttpClient totalmente administrado que se ha enviado con versiones
anteriores de Xamarin. Android.
Profesionales ti
Es la versión más compatible (características) con MS .NET y versiones anteriores de Xamarin.
Iconos
No está totalmente integrado con el sistema operativo (por ejemplo, limitado a TLS 1,0).
Normalmente es mucho más lento (por ejemplo, cifrado) que la API nativa.
Requiere más código administrado, lo que crea aplicaciones de mayor tamaño.
Elegir un controlador
La elección entre AndroidClientHandler y HttpClientHandler depende de las necesidades de la aplicación.
AndroidClientHandler se recomienda para la compatibilidad de seguridad más actualizada, por ejemplo,.

Requiere compatibilidad con TLS 1.2 y.


Su aplicación tiene como destino Android 4,1 (API 16) o posterior.
Necesita compatibilidad con TLS 1.2 y para HttpClient .
No necesita compatibilidad con TLS 1.2 y para WebClient .
HttpClientHandleres una buena opción si necesita compatibilidad con TLS 1.2 + pero debe admitir versiones de
Android anteriores a Android 4,1. También es una buena opción si necesita compatibilidad con TLS 1.2 y para
WebClient .

A partir de Xamarin. Android 8,3 HttpClientHandler , el valor predeterminado es aburrido btls SSL () como
proveedor de TLS subyacente. El proveedor de SSL de perforación de aburrido ofrece las siguientes ventajas:
Admite TLS 1.2 +.
Es compatible con todas las versiones de Android.
Proporciona compatibilidad con TLS 1.2 HttpClient y para y. WebClient

La desventaja de utilizar SSL aburrido como el proveedor de TLS de subordinado es que puede aumentar el
tamaño del APK resultante (agrega aproximadamente 1 MB de tamaño de APK adicional por ABI compatible).
A partir de Xamarin. Android 8,3, el proveedor de TLS predeterminado es aburrido btls SSL (). Si no desea utilizar
SSL aburrido, puede revertir a la implementación de SSL administrada histórica estableciendo la
$(AndroidTlsProvider) propiedad en legacy (para obtener más información sobre cómo establecer las
propiedades de compilación, vea proceso de compilación).
Usar mediante programación AndroidClientHandler
Xamarin.Android.Net.AndroidClientHandler Es una HttpMessageHandler implementación específica de Xamarin.
Android. Las instancias de esta clase usarán la java.net.URLConnection implementación nativa para todas las
conexiones http. En teoría, esto proporcionará un aumento en el rendimiento HTTP y tamaños de APK menores.
Este fragmento de código es un ejemplo de cómo explícitamente para una única instancia de HttpClient la clase:

// Android 4.1 or higher, Xamarin.Android 6.1 or higher


HttpClient client = new HttpClient(new Xamarin.Android.Net.AndroidClientHandler ());

NOTE
El dispositivo Android subyacente debe admitir TLS 1,2 (es decir, Android 4,1 y versiones posteriores). Tenga en cuenta que el
soporte técnico oficial de TLS 1,2 es Android 5.0 +. Sin embargo, algunos dispositivos admiten TLS 1,2 en Android 4.1 +.

Opción de compilación de implementación de SSL/TLS


Esta opción de proyecto controla qué biblioteca TLS subyacente usarán todas las solicitudes Web, HttpClient y.
WebRequest De forma predeterminada, se selecciona TLS 1,2:

Visual Studio
Visual Studio para Mac

Por ejemplo:

var client = new HttpClient();

Si la implementación de HttpClient se estableció en administrado y la implementación de TLS se estableció en


TLS 1.2 + nativo, client el objeto usaría automáticamente los HttpClientHandler 1,2 administrados y TLS
(proporcionados por la biblioteca de BoringSSL ) para su Solicitudes HTTP.
Sin embargo, si la implementación de HttpClient está AndroidHttpClient establecida en, HttpClient todos los
objetos usarán la clase java.net.URLConnection Java subyacente y no se verán afectados por el valor de
implementación de TLS/SSL . WebRequest los objetos usarían la biblioteca BoringSSL.

Otras formas de controlar la configuración de SSL/TLS


Hay tres maneras de que una aplicación de Xamarin. Android pueda controlar la configuración de TLS:
1. Seleccione la implementación de HttpClient y la biblioteca TLS predeterminada en las opciones del proyecto.
2. Mediante programación Xamarin.Android.Net.AndroidClientHandler con.
3. Declare las variables de entorno (opcional).
De las tres opciones, el enfoque recomendado es usar las opciones de proyecto de Xamarin. Android para declarar
el HttpMessageHandler valor predeterminado y el TLS para toda la aplicación. A continuación, si es necesario, cree
instancias Xamarin.Android.Net.AndroidClientHandler de los objetos mediante programación. Estas opciones se han
descrito anteriormente.
La tercera opción – mediante variables – de entorno se explica a continuación.
Declarar variables de entorno
Hay dos variables de entorno relacionadas con el uso de TLS en Xamarin. Android:
XA_HTTP_CLIENT_HANDLER_TYPE Esta variable de entorno declara el valor HttpMessageHandler predeterminado
que la aplicación usará. – Por ejemplo:

XA_HTTP_CLIENT_HANDLER_TYPE=Xamarin.Android.Net.AndroidClientHandler

XA_TLS_PROVIDEREsta variable de entorno declarará qué biblioteca TLS se usará btls , legacy o, o default
(que es lo mismo que omitir esta variable): –

XA_TLS_PROVIDER=btls

Esta variable de entorno se establece agregando un archivo de entorno al proyecto. Un archivo de entorno es un
archivo de texto sin formato de UNIX con una acción de compilación de AndroidEnvironment:
Visual Studio
Visual Studio para Mac

Consulte la guía del entorno de Xamarin. Android para obtener más detalles sobre las variables de entorno y
Xamarin. Android.

Vínculos relacionados
Seguridad de la capa de transporte (TLS )
Escribir aplicaciones con capacidad de respuesta
27/07/2019 • 3 minutes to read • Edit Online

Una de las claves para mantener una GUI receptiva es realizar tareas de ejecución prolongada en un subproceso
en segundo plano para que la GUI no se bloquee. Supongamos que queremos calcular un valor para mostrar al
usuario, pero ese valor tarda 5 segundos en calcularse:

public class ThreadDemo : Activity


{
TextView textview;

protected override void OnCreate (Bundle bundle)


{
base.OnCreate (bundle);

// Create a new TextView and set it as our view


textview = new TextView (this);
textview.Text = "Working..";

SetContentView (textview);

SlowMethod ();
}

private void SlowMethod ()


{
Thread.Sleep (5000);
textview.Text = "Method Complete";
}
}

Esto funcionará, pero la aplicación se "bloqueará" durante 5 segundos mientras se calcula el valor. Durante este
tiempo, la aplicación no responderá a ninguna interacción del usuario. Para solucionar este tema, queremos
realizar los cálculos en un subproceso en segundo plano:

public class ThreadDemo : Activity


{
TextView textview;

protected override void OnCreate (Bundle bundle)


{
base.OnCreate (bundle);

// Create a new TextView and set it as our view


textview = new TextView (this);
textview.Text = "Working..";

SetContentView (textview);

ThreadPool.QueueUserWorkItem (o => SlowMethod ());


}

private void SlowMethod ()


{
Thread.Sleep (5000);
textview.Text = "Method Complete";
}
}
Ahora se calcula el valor en un subproceso en segundo plano para que la interfaz de usuario siga respondiendo
durante el cálculo. Sin embargo, cuando se realiza el cálculo, nuestra aplicación se bloquea, lo que deja en el
registro:

E/mono (11207): EXCEPTION handling: Android.Util.AndroidRuntimeException: Exception of type


'Android.Util.AndroidRuntimeException' was thrown.
E/mono (11207):
E/mono (11207): Unhandled Exception: Android.Util.AndroidRuntimeException: Exception of type
'Android.Util.AndroidRuntimeException' was thrown.
E/mono (11207): at Android.Runtime.JNIEnv.CallVoidMethod (IntPtr jobject, IntPtr jmethod,
Android.Runtime.JValue[] parms)
E/mono (11207): at Android.Widget.TextView.set_Text (IEnumerable`1 value)
E/mono (11207): at MonoDroidDebugging.Activity1.SlowMethod ()

Esto se debe a que debe actualizar la GUI desde el subproceso de la GUI. Nuestro código actualiza la GUI desde el
subproceso ThreadPool, lo que hace que la aplicación se bloquee. Necesitamos calcular nuestro valor en el
subproceso en segundo plano, pero luego realizar nuestra actualización en el subproceso de la GUI, que se
controla con Activity. RunOnUIThread:

public class ThreadDemo : Activity


{
TextView textview;

protected override void OnCreate (Bundle bundle)


{
base.OnCreate (bundle);

// Create a new TextView and set it as our view


textview = new TextView (this);
textview.Text = "Working..";

SetContentView (textview);

ThreadPool.QueueUserWorkItem (o => SlowMethod ());


}

private void SlowMethod ()


{
Thread.Sleep (5000);
RunOnUiThread (() => textview.Text = "Method Complete");
}
}

Este código funciona según lo esperado. Esta GUI sigue respondiendo y se actualiza correctamente una vez que se
com el cálculo.
Tenga en cuenta que esta técnica no se utiliza solo para calcular un valor caro. Se puede usar para cualquier tarea
de ejecución prolongada que se pueda realizar en segundo plano, como una llamada de servicio web o la descarga
de datos de Internet.
Interfaz de usuario
11/07/2019 • 3 minutes to read • Edit Online

Las siguientes secciones explican las diversas herramientas y bloques de creación que se utilizan para crear
interfaces de usuario en aplicaciones de Xamarin.Android.

Android Designer
Esta sección explica cómo usar el Diseñador de Android para diseñar controles visualmente y editar las
propiedades. También se explica cómo usar el diseñador para trabajar con interfaces de usuario y recursos entre
varias configuraciones, como temas, idiomas y configuraciones de dispositivos, así como cómo diseñar vistas
alternativas, como horizontal y vertical.

Tema de materiales
Tema de materiales es el estilo de la interfaz de usuario que determina la apariencia de las vistas y actividades en
Android. Tema de materiales está integrado en Android, por lo que se usa la interfaz de usuario del sistema, así
como las aplicaciones. Esta guía presenta los principios de diseño de Material y explica cómo crear un tema de una
aplicación con los temas de Material integrados o un tema personalizado.

Perfil de usuario
Esta guía explica cómo obtener acceso al perfil personal para el propietario de un dispositivo, incluidos los datos de
contacto, como del propietario del dispositivo nombre y número de teléfono.

Pantalla de presentación
Una aplicación Android tarda algún tiempo en iniciarse, especialmente cuando la aplicación se inició por primera
vez en un dispositivo. Una pantalla de presentación puede mostrar el inicio hasta el progreso al usuario. Esta guía
explica cómo crear una pantalla de presentación de la aplicación.

Diseños
Los diseños se usan para definir la estructura visual de una interfaz de usuario. Los diseños, como ListView y
RecyclerView son los bloques de creación más fundamentales de las aplicaciones de Android. Normalmente, usará
un diseño de un Adapter para que actúe como un puente desde el diseño a los datos subyacentes que se usan
para rellenar los elementos de datos en el diseño. En esta sección se explica cómo usar diseños, como
LinearLayout , RelativeLayout , TableLayout , RecyclerView , y GridView .

Controles
Controles de Android (también denominada widgets) son los elementos de interfaz de usuario que se utiliza para
compilar una interfaz de usuario. Esta sección explica cómo utilizar controles como botones, barras de
herramientas, los selectores de fecha y hora, calendarios, iconos de carga, conmutadores, los menús emergentes,
localizadores de vista y vistas web.
Xamarin. Android Designer
16/08/2019 • 3 minutes to read • Edit Online

En este artículo se describen las características de Xamarin. Android Designer. Se explican los conceptos básicos
del diseñador, que muestran cómo usar el diseñador para diseñar widgets visualmente y editar propiedades.
También se muestra cómo usar el diseñador para trabajar con interfaces y recursos de usuario en distintas
configuraciones, como temas, lenguajes y configuraciones de dispositivos, así como la forma de diseñar vistas
alternativas como horizontal y vertical.

Información general
Xamarin. Android admite un estilo declarativo del diseño de la interfaz de usuario basado en archivos XML, así
como la creación de la interfaz de usuario mediante programación en el código. Al usar el enfoque declarativo, los
archivos XML se pueden editar manualmente o modificar visualmente mediante el uso de Xamarin. Android
Designer. El uso de un diseñador permite obtener comentarios inmediatos durante la creación de la interfaz de
usuario, agiliza el desarrollo y hace que el proceso de creación de la interfaz de usuario sea menos laborioso.
En este artículo se analizan las numerosas características de Xamarin. Android Designer. Explica lo siguiente:
1. Aspectos básicos del uso del diseñador.
2. Las distintas partes que componen el diseñador.
3. Cómo cargar un diseño de Android en el diseñador.
4. Cómo agregar widgets.
5. Cómo editar propiedades.
6. Cómo trabajar con varios recursos y configuraciones de dispositivos.
7. Cómo modificar una interfaz de usuario para vistas alternativas como horizontal y vertical.
8. Cómo controlar los conflictos que pueden surgir al trabajar con vistas alternativas.
9. Cómo usar las herramientas de diseño de materiales para compilar aplicaciones compatibles con el diseño de
materiales.

Secciones
Uso de Android Designer
Conceptos básicos de Designer
Calificadores de recursos y opciones de visualización
Vistas de diseños alternativos
Características de Material Design

Resumen
En este artículo se describe el conjunto de características de Xamarin. Android Designer. Se ha mostrado cómo
empezar a trabajar con el diseñador y se han explicado las distintas partes. Se ha descrito cómo cargar un diseño y
cómo agregar y modificar widgets mediante la superficie del diseñador y la vista de código fuente . También
se explica cómo trabajar con varios recursos y configuraciones de dispositivos. Por último, examinó cómo usar el
diseñador para desarrollar interfaces de usuario que se crean específicamente para vistas alternativas, como
horizontal y vertical, y cómo resolver los conflictos que pueden surgir entre esas vistas.
Vínculos relacionados
Tutorial del diseñador
Recursos de Android
Usar Xamarin. Android Designer
16/08/2019 • 28 minutes to read • Edit Online

Este artículo es un tutorial de Xamarin. Android Designer. Muestra cómo crear una interfaz de usuario para una
aplicación de explorador de color pequeña; Esta interfaz de usuario se crea completamente en el diseñador.

Información general
Las interfaces de usuario de Android se pueden crear mediante declaración usando archivos XML o mediante
programación escribiendo código. Xamarin. Android Designer permite a los desarrolladores crear y modificar
visualmente diseños declarativos, sin necesidad de modificar manualmente los archivos XML. El diseñador
también proporciona comentarios en tiempo real que permiten al desarrollador evaluar los cambios de la interfaz
de usuario sin tener que volver a implementar la aplicación en un dispositivo o en un emulador. Estas
características del diseñador pueden acelerar enormemente el desarrollo de la interfaz de usuario de Android. En
este artículo se muestra cómo usar Xamarin. Android Designer para crear visualmente una interfaz de usuario.

TIP
Las versiones más recientes de Visual Studio admiten la apertura de archivos .xml dentro de Android Designer.
Android Designer admite tanto archivos .axml como .xml.

Tutorial
El objetivo de este tutorial es usar el Android Designer para crear una interfaz de usuario para una aplicación de
explorador de color de ejemplo. La aplicación color Browser presenta una lista de colores, sus nombres y sus
valores RGB. Aprenderá a agregar widgets al superficie de diseño , así como a diseñar estos widgets
visualmente. Después, aprenderá a modificar widgets de forma interactiva en el superficie de diseño o mediante
el panel de propiedades del diseñador. Por último, verá cómo se ve el diseño cuando la aplicación se ejecuta en
un dispositivo o emulador.
Visual Studio
Visual Studio para Mac
Crear un nuevo proyecto
El primer paso es crear un nuevo proyecto de Xamarin. Android. Inicie Visual Studio, haga clic en nuevo
proyecto... y elija la plantilla # Visual C > Android > Android App (Xamarin) . Asigne a la nueva aplicación el
nombre DesignerWalkthrough y haga clic en Aceptar.
En el cuadro de diálogo nueva aplicación de Android , elija aplicación vacía y haga clic en Aceptar:

Agregar un diseño
El siguiente paso consiste en crear un LinearLayout que contendrá los elementos de la interfaz de usuario. Haga
clic con el botón derecho en recursos/diseño en el Explorador de soluciones y seleccione Agregar > nuevo
elemento. ... En el cuadro de diálogo Agregar nuevo elemento , seleccione diseño de Android. Asigne al
archivo el nombre list_item y haga clic en Agregar:
El nuevo diseño de list_item se muestra en el diseñador. Observe que se muestran – dos paneles. el superficie de
diseño para list_item está visible en el panel izquierdo, mientras que su origen XML se muestra en el panel
derecho. Puede intercambiar las posiciones de los paneles de superficie de diseño y de origen haciendo clic en
el icono intercambiar paneles que se encuentra entre los dos paneles:

En el menú Ver , haga clic en otras ventanas > esquema del documento para abrir el esquema del
documento. El esquema del documento muestra que el diseño contiene actualmente un solo widget
LinearLayout :
El siguiente paso consiste en crear la interfaz de usuario para la aplicación de explorador de LinearLayout color
dentro de este.
Crear la interfaz de usuario de elemento de lista
Si el panel cuadro de herramientas no está visible, haga clic en la pestaña cuadro de herramientas de la
izquierda. En el cuadro de herramientas, desplácese hacia abajo hasta la sección imágenes & medios y
desplácese hacia ImageView abajo hasta encontrar un:

Como alternativa, puede escribir ImageView en la barra de búsqueda para buscar ImageView :
Arrástrelo hasta el superficie de diseño (se usará para mostrar una muestra de color en la aplicación del
explorador de color): ImageView ImageView

A continuación, arrastre LinearLayout (Vertical) un widget desde el cuadro de herramientas al diseñador.


Observe que un contorno azul indica los límites del agregado LinearLayout . El esquema del documento
muestra que es un elemento secundario LinearLayout de, que imageView1 (ImageView) se encuentra en:

Al seleccionar ImageView en el diseñador, el contorno azul se desplaza para rodear ImageView el. Además, la
selección se mueve a imageView1 (ImageView) en el esquema del documento:

A continuación, arrastre Text (Large) un widget desde el cuadro de herramientas hasta el LinearLayout recién
agregado. Observe que el diseñador usa resaltados verdes para indicar dónde se insertará el nuevo widget:

Después, agregue un Text (Small) widget debajo del Text (Large) widget:

En este punto, la superficie del diseñador debe ser similar a la captura de pantalla siguiente:
Si los dos textView widgets no están dentro linearLayout1 , puede arrastrarlos a linearLayout1 en el esquema
del documento y colocarlos de modo que aparezcan como se muestra en la captura de pantalla anterior
linearLayout1 (con sangría debajo).

Organizar la interfaz de usuario


El siguiente paso consiste en modificar la interfaz de usuario para ImageView Mostrar la a la izquierda, con
TextView los dos widgets apilados ImageView a la derecha de.

1. Seleccione el control ImageView .


2. En el ventana Propiedades, escriba ancho en el cuadro de búsqueda y busque el ancho del diseño.
3. Cambie la configuración de ancho de wrap_content diseño a:

Otra manera de cambiar la Width configuración es hacer clic en el triángulo del lado derecho del widget para
alternar el valor de ancho a: wrap_content

Al hacer clic en el triángulo Width de nuevo match_parent , se devuelve el valor a. A continuación, vaya al panel
esquema del documento y seleccione la LinearLayout raíz:
Con la raíz LinearLayout seleccionada, vuelva al panel de propiedades , escriba orientación en el cuadro de
búsqueda y busque la configuración de orientación . Cambie la orientación horizontal a:

En este punto, la superficie del diseñador debe ser similar a la captura de pantalla siguiente. Observe que los
TextView widgets se han colocado a la derecha ImageView de:
Modificar el espaciado
El siguiente paso consiste en modificar la configuración del relleno y los márgenes en la interfaz de usuario para
proporcionar más espacio entre los widgets. ImageView Seleccione en la superficie de diseño. En el panel
propiedades , escriba min en el cuadro de búsqueda. Escriba 70dp para altura mínima y 50dp para ancho
mínimo:

En el panel propiedades , escriba padding en el cuadro de búsqueda y 10dp escriba para relleno. Estos
minHeight valores y la padding configuración agregan relleno alrededor de todos los lados de
yloalarganverticalmente. ImageView minWidth Observe que el esquema XML cambia a medida que se escriben
estos valores:
La configuración de los márgenes inferior, izquierdo, derecho y superior se puede establecer de forma
independiente mediante la especificación de valores en los campos de relleno hacia abajo, relleno izquierdo,
relleno derechoy relleno superior , respectivamente. Por ejemplo, establezca el campo relleno izquierdo en
5dp y los campos parte inferior, relleno derechoy relleno superior para 10dp :

A continuación, ajuste la posición del LinearLayout widget que contiene los dos TextView widgets. En el
esquema del documento, linearLayout1 seleccione. En la ventana propiedades , escriba margin en el cuadro
de búsqueda. Establezca el margen inferior del diseño, el margen de diseño a la izquierday el margen de
diseño arriba en 5dp . Establezca margen de diseño a 0dp la derecha en:
Quitar la imagen predeterminada
Dado que ImageView se usa para mostrar los colores (en lugar de las imágenes), el siguiente paso es quitar el
origen de imagen predeterminado agregado por la plantilla.
1. Seleccione en la superficie del diseñador. ImageView

2. En propiedades, escriba src en el cuadro de búsqueda.


3. Haga clic en el cuadrado pequeño situado a la derecha del valor de la propiedad src y seleccione
restablecer:
Esto quita android:src="@android:drawable/ic_menu_gallery" del XML de origen para eso ImageView .
Agregar un contenedor de ListView
Ahora que se ha definido el diseño list_item , el paso siguiente consiste en agregar ListView un al diseño
principal. Contendrá una lista de list_item. ListView
En el Explorador de soluciones, Abra Resources/layout/activity_main. axml. En el cuadro de herramientas,
ListView busque el widget y arrástrelo hasta el superficie de diseño. ListView En el diseñador estará en blanco
excepto las líneas azules que conforman el borde cuando está seleccionado. Puede ver el esquema del
documento para comprobar que ListView se ha agregado correctamente:

De forma predeterminada, ListView se Id proporciona el valor @+id/listView1 . Mientras listView1 aún está
seleccionado en el esquema del documento, abra el panel de propiedades , haga clic en organizar pory
seleccione categoría. Abra Main, busque la propiedad ID y cambie su valor a @+id/myListView :
En este momento, la interfaz de usuario está lista para usarse.
Ejecutar la aplicación
Abra MainActivity.CS y reemplace su código por lo siguiente:

using Android.App;
using Android.Widget;
using Android.Views;
using Android.OS;
using Android.Support.V7.App;
using System.Collections.Generic;

namespace DesignerWalkthrough
{
[Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)]
public class MainActivity : AppCompatActivity
{
List<ColorItem> colorItems = new List<ColorItem>();
ListView listView;

protected override void OnCreate(Bundle savedInstanceState)


{
base.OnCreate(savedInstanceState);

// Set our view from the "main" layout resource


SetContentView(Resource.Layout.activity_main);
listView = FindViewById<ListView>(Resource.Id.myListView);

colorItems.Add(new ColorItem()
{
Color = Android.Graphics.Color.DarkRed,
ColorName = "Dark Red",
Code = "8B0000"
});
colorItems.Add(new ColorItem()
{
Color = Android.Graphics.Color.SlateBlue,
ColorName = "Slate Blue",
Code = "6A5ACD"
});
colorItems.Add(new ColorItem()
{
Color = Android.Graphics.Color.ForestGreen,
ColorName = "Forest Green",
Code = "228B22"
});

listView.Adapter = new ColorAdapter(this, colorItems);


}
}

public class ColorAdapter : BaseAdapter<ColorItem>


{
List<ColorItem> items;
Activity context;
public ColorAdapter(Activity context, List<ColorItem> items)
: base()
{
this.context = context;
this.items = items;
}
public override long GetItemId(int position)
{
return position;
}
public override ColorItem this[int position]
{
get { return items[position]; }
}
public override int Count
{
get { return items.Count; }
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
var item = items[position];

View view = convertView;


if (view == null) // no view to re-use, create new
view = context.LayoutInflater.Inflate(Resource.Layout.list_item, null);
view.FindViewById<TextView>(Resource.Id.textView1).Text = item.ColorName;
view.FindViewById<TextView>(Resource.Id.textView2).Text = item.Code;
view.FindViewById<ImageView>(Resource.Id.imageView1).SetBackgroundColor(item.Color);

return view;
}
}

public class ColorItem


{
public string ColorName { get; set; }
public string Code { get; set; }
public Android.Graphics.Color Color { get; set; }
}
}

Este código usa un adaptador ListView personalizado para cargar información de color y para mostrar estos
datos en la interfaz de usuario que se acaba de crear. Para que este ejemplo sea breve, la información de color está
codificada de forma rígida en una lista, pero el adaptador se podría modificar para extraer la información de color
de un origen de datos o para calcularla sobre la marcha. Para obtener más información ListView acerca de los
adaptadores, vea ListView.
Compile y ejecute la aplicación. La captura de pantalla siguiente es un ejemplo de cómo aparece la aplicación
cuando se ejecuta en un dispositivo:
Resumen
En este artículo se explica el proceso de uso de Xamarin. Android Designer en Visual Studio para crear una
interfaz de usuario para una aplicación básica. Se ha mostrado cómo crear la interfaz para un único elemento de
una lista, y se ha mostrado cómo agregar widgets y colocarlos visualmente. También se explica cómo asignar
recursos y, después, establecer diversas propiedades en esos widgets.
Aspectos básicos de Xamarin. Android Designer
16/08/2019 • 48 minutes to read • Edit Online

En este tema se presentan las características de Xamarin. Android Designer, se explica cómo iniciar el diseñador, se
describe el Superficie de diseño y se detalla cómo usar el panel Propiedades para editar las propiedades del
widget.
Visual Studio
Visual Studio para Mac

Iniciar el diseñador
El diseñador se inicia automáticamente cuando se crea un diseño o se puede iniciar haciendo doble clic en un
archivo de diseño existente. Por ejemplo, si hace doble clic en activity_main. axml en la carpeta recursos >
diseño , se cargará el diseñador tal y como se verá en esta captura de pantalla:

Del mismo modo, puede Agregar un nuevo diseño haciendo clic con el botón secundario en la carpeta diseño del
Explorador de soluciones y seleccionando Agregar > nuevo elemento... > Diseño de Android:
Esto crea un nuevo archivo de diseño . axml y lo carga en el diseñador.

TIP
Las versiones más recientes de Visual Studio admiten la apertura de archivos .xml dentro de Android Designer.
Android Designer admite tanto archivos .axml como .xml.

Características del diseñador


El diseñador se compone de varias secciones que admiten sus diversas características, como se muestra en la
siguiente captura de pantalla:
Al editar un diseño en el diseñador, se usan las siguientes características para crear y dar forma a un diseño:
Superficie de diseño – Facilita la construcción visual de la interfaz de usuario al proporcionar una
representación editable de cómo aparecerá el diseño en el dispositivo. El superficie de diseño se muestra
en el Panel de diseño (con la barra de herramientas del diseñador colocada encima).
Panel origen Proporciona una vista del origen XML subyacente que corresponde al diseño presentado en
el superficie de diseño. –
Barra de herramientas del diseñador – Muestra una lista de selectores: Configuración de dispositivo,
versión, tema, diseño y barra de acciones. La barra de herramientas del diseñador también incluye
iconos para iniciar el editor de temas y habilitar la cuadrícula de diseño del material.
Cuadro de herramientas Proporciona una lista de widgets y diseños que puede arrastrar y colocar en el
superficie de diseño. –
Ventana Propiedades – Muestra las propiedades del widget seleccionado para su visualización y edición.
Esquema del documento – Muestra el árbol de widgets que componen el diseño. Puede hacer clic en un
elemento del árbol para que se seleccione en el superficie de diseño. Además, al hacer clic en un elemento
del árbol, se cargan las propiedades del elemento en la ventana propiedades .

Superficie de diseño
El diseñador permite arrastrar y colocar widgets desde el cuadro de herramientas hasta el superficie de diseño.
Al interactuar con widgets en el diseñador (agregando nuevos widgets o cambiando la posición de los existentes),
se muestran las líneas verticales y horizontales para marcar los puntos de inserción disponibles. En el ejemplo
siguiente, se está Button arrastrando un nuevo widget hasta el superficie de diseño:

Además, se pueden copiar widgets: puede usar copiar y pegar para copiar un widget, o puede arrastrar y colocar
un widget existente mientras presiona la tecla Ctrl .
Barra de herramientas del diseñador
La barra de herramientas del diseñador (situada sobre el superficie de diseño) presenta los selectores de
configuración y los menús de herramientas:
La barra de herramientas del diseñador proporciona acceso a las siguientes características:
Selector de diseño alternativo – Permite seleccionar entre diferentes versiones de diseño.
Selector de dispositivos – Define un conjunto de calificadores (como el tamaño de la pantalla, la
resolución y la disponibilidad del teclado) asociados a un dispositivo determinado. También puede Agregar
y eliminar nuevos dispositivos.
Selector de versión de Android – Versión de Android de destino del diseño. El diseñador representará el
diseño según la versión de Android seleccionada.
Selector de tema – Selecciona el tema de la interfaz de usuario para el diseño.
Selector de configuración Selecciona la configuración del dispositivo, como vertical u horizontal. –
Opciones de calificador de recursos Abre un cuadro de diálogo que muestra los menús desplegables para
seleccionar el idioma, el modo de la interfaz de usuario, el modo nocturno y las opciones de pantalla
redondeada. –
Configuración de barra de acciones – Configura los valores de barra de acciones para el diseño.
Editor de temas Abre el Editor de temas, lo que permite personalizar los elementos del tema seleccionado.

Cuadrícula de diseño de materiales Habilita o deshabilita la cuadrícula de diseño del material. – El
elemento de menú desplegable adyacente a la cuadrícula de diseño del material abre un cuadro de diálogo
que le permite personalizar la cuadrícula.
Cada una de estas características se explica con más detalle en estos temas:
Opciones de visualización y calificadores de recursos proporciona información detallada sobre el selector
de dispositivos, el selector de versiones de Android, el selector de temas, el selector de
configuracióny los requisitos de recursos Opcionesy barra de acciones configuración.
En las vistas de diseño alternativas se explica cómo usar el selector de diseño alternativo.
Las características de diseño de material de Xamarin. Android Designer proporcionan información general
detallada sobre el Editor de temas y la cuadrícula de diseño de materiales.
Comandos del menú contextual
Un menú contextual está disponible tanto en el superficie de diseño como en el esquema del documento. Este
menú muestra los comandos que están disponibles para el widget seleccionado y su contenedor, lo que facilita la
realización de operaciones en contenedores (que no siempre son fáciles de seleccionar en el superficie de
diseño). A continuación se muestra un ejemplo de un menú contextual:
En este ejemplo, al hacer clic con TextView el botón secundario en, se abre un menú contextual que proporciona
varias opciones:
LinearLayout abre un submenú para editar el LinearLayout elemento primario del TextView control. –
Operaciones de eliminación, copiay corte – TextView que se aplican al clic con el botón secundario.
Controles de zoom
El superficie de diseño admite la ampliación a través de varios controles, como se muestra a continuación:

Estos controles facilitan la visualización de ciertas áreas de la interfaz de usuario en el diseñador:


Resaltar contenedores Resalta los contenedores en la superficie de diseño de forma que sean más fáciles
de encontrar al acercar y alejar. –
Tamaño normal – Representa el píxel de diseño del píxel para que pueda ver cómo se verá el diseño en la
resolución del dispositivo seleccionado.
Ajustar a la ventana – Establece el nivel de zoom para que todo el diseño esté visible en el superficie de
diseño.
Acercar – Acerca de forma incremental con cada clic, ampliando el diseño.
Alejar – Aleja de forma incremental con cada clic, haciendo que el diseño aparezca más pequeño en el
superficie de diseño.
Tenga en cuenta que la configuración de zoom elegida no afecta a la interfaz de usuario de la aplicación en tiempo
de ejecución.

Cambiar entre los paneles de diseño y de origen


En la franja central situada entre los paneles diseño y origen , hay varios botones que se usan para modificar el
modo en que se muestran los paneles de diseño y de origen :

Estos botones hacen lo siguiente:


Diseño de Este botón de nivel superior, diseño, selecciona el panel de diseño. – Al hacer clic en este botón,
se habilitan los paneles cuadro de herramientas y propiedades y no se muestra la barra de herramientas
del Editor de texto . Cuando se hace clic en el botón contraer (vea más abajo), el panel de diseño se
presenta solo sin el panel de origen .
Intercambiar paneles Este botón (que se asemeja a dos flechas opuestas) intercambia los paneles de
diseño y de origen para que el panel de origen se encuentra a la izquierda y el panel de diseño está a la
derecha. – Al hacer clic en él, se vuelven a intercambiar los paneles con sus ubicaciones originales.
Origen de Este botón (que se asemeja a dos corchetes angulares opuestos) selecciona el panel origen. – Al
hacer clic en este botón, los paneles cuadro de herramientas y propiedades se deshabilitan y la barra de
herramientas del Editor de texto se hace visible en la parte superior de Visual Studio. Cuando se haga clic
en el botón contraer (vea más abajo), al hacer clic en el botón origen se muestra el panel origen en lugar
del panel diseño .
División vertical Este botón (que es similar a una barra vertical) muestra los paneles de diseño y de
origen en paralelo. – Esta es la disposición predeterminada.
División horizontal Este botón (que es similar a una barra horizontal) muestra el panel de diseño sobre el
panel de origen. – Se puede hacer clic en los paneles de intercambio para colocar el panel de origen
encima del panel de diseño .
Contraer panel Este botón (que se parece a dos corchetes angulares) "contrae" la presentación de dos
paneles del diseño y del origen en una sola vista de uno de estos paneles. – Este botón se convierte en el
botón de Panel de expansión (similar a dos corchetes angulares que apuntan a la izquierda), en el que se
puede hacer clic para devolver la vista al modo de presentación de doble panel (diseño y origen).
Cuando se hace clic en el Panel de contraer, solo se muestra el panel de diseño . Sin embargo, puede hacer clic en
el botón origen para ver en su lugar solo el panel origen . Vuelva a hacer clic en el botón diseño para volver al
panel de diseño .

Panel origen
En el panel origen se muestra el origen XML que subyace al diseño mostrado en el superficie de diseño. Dado
que las dos vistas están disponibles al mismo tiempo, es posible crear un diseño de la interfaz de usuario si va
entre una representación visual del diseño y el origen XML subyacente para el diseño:

Los cambios realizados en el origen XML se representan inmediatamente en el superficie de diseño; los cambios
realizados en el superficie de diseño hacen que el origen XML mostrado en el panel de origen se actualice en
consecuencia. Al realizar cambios en XML en el panel origen , las características de autocompletar e IntelliSense
están disponibles para acelerar el desarrollo de la interfaz de usuario basada en XML, tal como se explica a
continuación.
Para una mayor facilidad de navegación al trabajar con archivos XML largos, el panel de origen es compatible con
la barra de desplazamiento de Visual Studio (como se mostró a la derecha en la captura de pantalla anterior). Para
obtener más información sobre la barra de desplazamiento, vea Cómo realizar un seguimiento del Código
personalizando la barra de desplazamiento.
Autocompletar
Cuando empiece a escribir el nombre de un atributo para un widget, puede presionar CTRL + barra
espaciadora para ver una lista de posibles finalizaciones. Por ejemplo, después de android:lay escribir en el
ejemplo siguiente (seguido de escribir CTRL + barra espaciadora), se presenta la siguiente lista:
Presione entrar para aceptar la primera finalización de la lista o utilice las teclas de dirección para desplazarse a la
finalización deseada y presione entrar. Como alternativa, puede usar el mouse para desplazarse y hacer clic en la
finalización deseada.
IntelliSense
Después de escribir un nuevo atributo para un widget y de empezar a asignarle un valor, IntelliSense aparece
después de escribir un carácter desencadenador y proporciona una lista de valores válidos que se usarán para ese
atributo. Por ejemplo, después de escribir la primera comilla doble para android:layout_width en el ejemplo
siguiente, aparece un selector de finalización automática que proporciona la lista de opciones válidas para este
ancho:

En la parte inferior de este menú emergente hay dos botones (como se indica en rojo en la captura de pantalla
anterior). Al hacer clic en el botón recursos del proyecto de la izquierda, la lista se restringe a los recursos que
forman parte del proyecto de la aplicación, mientras que al hacer clic en el botón recursos del marco de la
derecha se restringe la lista para mostrar los recursos disponibles en el marco. Estos botones se activan o
desactivan: puede hacer clic en ellos de nuevo para deshabilitar la acción de filtrado que proporciona cada una.

Panel Propiedades
El diseñador admite la edición de las propiedades del widget a través del panel de propiedades :
Las propiedades enumeradas en el panel propiedades cambian en función del widget seleccionado en el
superficie de diseño.
Valores predeterminados
Las propiedades de la mayoría de los widgets estarán en blanco en la ventana propiedades porque sus valores se
heredan del tema Android seleccionado. La ventana propiedades solo mostrará los valores que se establecen
explícitamente para el widget seleccionado; no se mostrarán los valores que se heredan del tema.
Referencia a recursos
Algunas propiedades pueden hacer referencia a los recursos que se definen en archivos que no sean el archivo
layout . axml . Los casos más comunes de este tipo son string y drawable los recursos. Sin embargo, las
referencias también se pueden usar para otros recursos, Boolean como valores y dimensiones. Cuando una
propiedad admite referencias de recursos, se muestra un icono de exploración (un cuadrado) junto a la entrada de
texto de la propiedad. Al hacer clic en este botón, se abre un selector de recursos.
Por ejemplo, en la siguiente captura de pantalla se muestran las opciones disponibles al hacer clic en el cuadrado
oscurecido a la derecha Text del campo de texto de un widget en la ventana propiedades :
Cuando se hace clic en el recurso , se muestra el cuadro de diálogo seleccionar recurso :
En esta lista, puede seleccionar un recurso de texto para usarlo en el widget en lugar de codificar de forma rígida el
texto en el panel de propiedades . En el ejemplo siguiente se muestra el selector de recursos Src para la
propiedad ImageView de un:

Al hacer clic en el cuadrado en blanco situado Src a la derecha de la propiedad, se abre el cuadro de diálogo
seleccionar recurso con una lista de recursos que van desde los colores (como se mostró anteriormente) a
drawables.
Referencias de propiedades booleanas
Las propiedades booleanas se seleccionan normalmente como marcas de verificación junto a una propiedad en el
ventana Propiedades. Puede designar un true valor o false activando o desactivando esta casilla, o bien puede
seleccionar una referencia de propiedad haciendo clic en el cuadrado rellenado a la derecha de la propiedad. En el
ejemplo siguiente, el texto se cambia a todas las mayúsculas al hacer clic en la referencia de propiedad booleana
All capss de texto asociada al seleccionado TextView :

Editar propiedades en línea


El Android Designer admite la edición directa de ciertas propiedades en el superficie de diseño (por lo que no
tiene que buscar estas propiedades en la lista de propiedades). Entre las propiedades que se pueden editar
directamente se incluyen texto, margen y tamaño.
Text
Las propiedades de texto de algunos widgets (como Button y TextView ) se pueden editar directamente en el
superficie de diseño. Al hacer doble clic en un widget, se pone en modo de edición, como se muestra a
continuación:
Puede escribir un nuevo valor de texto o escribir una nueva cadena de recursos. En el ejemplo siguiente, el
@string/hello recurso se reemplaza por el CLICK THIS BUTTON texto:

Este cambio se almacena en la propiedad del text widget; no modifica el valor asignado @string/hello al
recurso. Al escribir una clave en una nueva cadena de texto, puede presionar MAYÚS + entrar para vincular
automáticamente el texto especificado a un nuevo recurso.
Margen
Al seleccionar un widget, el diseñador muestra los identificadores que le permiten cambiar el tamaño o margen del
widget de forma interactiva. Al hacer clic en el widget mientras está seleccionado, se alterna entre el modo de
edición de márgenes y el modo de edición de tamaño.
Al hacer clic en un widget por primera vez, se muestran los controladores de margen. Si mueve el mouse a uno de
los identificadores, el diseñador muestra la propiedad que cambiará el identificador (como se muestra a
continuación layout_marginLeft para la propiedad):

Si ya se ha establecido un margen, se muestran líneas de puntos, lo que indica el espacio que ocupa el margen:
Tamaño
Como se mencionó anteriormente, puede cambiar al modo de edición de tamaño haciendo clic en un widget
mientras ya está seleccionado. Haga clic en el controlador triangular para establecer el tamaño de la wrap_content
dimensión indicada en:

Al hacer clic en el controlador ajustar contenido , se reduce el widget en esa dimensión para que no sea más
grande de lo necesario para incluir el contenido delimitado. En este ejemplo, el texto del botón se reduce
horizontalmente tal y como se muestra en la siguiente captura de pantalla.
Cuando el valor de tamaño se establece para ajustar el contenido, el diseñador muestra un controlador
triangular que apunta a la dirección opuesta para match_parent cambiar el tamaño a:
Al hacer clic en el identificador principal de coincidencia , se restaura el tamaño de esa dimensión para que sea
el mismo que el del widget primario.
Además, puede arrastrar el controlador de tamaño circular (como se muestra en las capturas de pantallas
anteriores) para cambiar el tamaño del dp widget a un valor arbitrario. Cuando lo haga, se mostrarán los
identificadores ajustar contenido y coincidir con la dimensión:

No todos los contenedores permiten editar Size el de un widget. Por ejemplo, observe que en la captura de
pantalla siguiente LinearLayout con el seleccionado, los controladores de tamaño no aparecen:
Esquema del documento
El esquema del documento muestra la jerarquía del widget del diseño. En el ejemplo siguiente, se selecciona
LinearLayout el widget contenedor:

El contorno del widget seleccionado (en este caso, a LinearLayout ) también se resalta en el superficie de diseño.
El widget seleccionado en el esquema del documento permanece sincronizado con su homólogo en el superficie
de diseño. Esto resulta útil para seleccionar grupos de vistas, que no siempre son fáciles de seleccionar en el
superficie de diseño.
El esquema del documento admite copiar y pegar, o puede usar arrastrar y colocar. Arrastrar y colocar se admite
desde el esquema del documento hasta el superficie de diseño , así como desde el superficie de diseño al
esquema del documento. Además, al hacer clic con el botón secundario en un elemento del esquema del
documento , se muestra el menú contextual de ese elemento (el mismo menú contextual que aparece al hacer clic
con el botón secundario en ese mismo widget en el superficie de diseño).
Opciones de visualización y calificadores de recursos
16/08/2019 • 16 minutes to read • Edit Online

En este tema se explica cómo definir los recursos que se usarán solo cuando se encuentren coincidencias con
algunos valores de calificador. Un ejemplo sencillo es un recurso de cadena calificado con el idioma. Un recurso
de cadena se puede definir como valor predeterminado, con otros recursos alternativos definidos que se usarán
para otros idiomas. Todos los tipos de recursos se pueden calificar, incluido el propio diseño.
Visual Studio
Visual Studio para Mac

Opciones de calificador de recursos


Se puede tener acceso a las opciones del calificador de recursos haciendo clic en el icono de puntos suspensivos
a la derecha del botón modo horizontal :

Este cuadro de diálogo presenta menús desplegables para los siguientes calificadores de recursos:
Idioma de – Muestra los recursos de idioma disponibles y ofrece una opción para agregar nuevos
recursos de idioma o región.
Modo de interfaz de usuario Muestra los modos de visualización (por ejemplo, el Dock de
automóviles y el acoplamiento de escritorio), así como las direcciones de diseño. –
Cada uno de estos menús desplegables abre nuevos cuadros de diálogo en los que puede seleccionar y
configurar calificadores de recursos (como se explica a continuación).
Idioma
En el menú desplegable idioma se muestran solo los idiomas que tienen definidos los recursos (o todos los
idiomas, que es el valor predeterminado). Sin embargo, también hay una opción Agregar idioma o región...
que le permite agregar un nuevo idioma a la lista:
Al hacer clic en Agregar idioma o región... , se abre el cuadro de diálogo Seleccionar idioma para mostrar las
listas desplegables de idiomas y regiones disponibles:

En este ejemplo, hemos elegido fr (Francés) como idioma y ser (Bélgica) para el dialecto regional de francés.
Tenga en cuenta que el campo región es opcional porque se pueden especificar muchos idiomas sin tener en
cuenta las regiones específicas. Cuando se vuelve a abrir el menú desplegable de idioma , se muestra el recurso
de idioma o región recién agregado:
Tenga en cuenta que si agrega un nuevo lenguaje pero no crea nuevos recursos, el idioma agregado ya no se
mostrará la próxima vez que abra el proyecto.
Modo de interfaz de usuario
Al hacer clic en el menú desplegable modo de interfaz de usuario , se muestra una lista de los modos, como
normal, coche Dock, mesa acoplada, televisión, dispositivoy inspección:

Debajo de esta lista están los modos nocturnos no nocturno y nocturno, seguidos de las direcciones de diseño
de izquierda a derecha y de derecha a izquierda (para obtener información sobre las opciones de izquierda a
derecha y de derecha a izquierda , vea LayoutDirection). Los últimos elementos del cuadro de diálogo
Opciones de calificador de recursos son las pantallas redondas (para su uso con el desgaste de Android) o no
las pantallas redondas. Para obtener información acerca de las pantallas redondas y no redondas, vea diseños.
Para obtener más información sobre los modos de interfaz de usuario de Android, vea UiModeManager.

Configuración de Barra de acciones


El icono de configuración de la barra de acciones está disponible a la izquierda del icono de pincel (editor de
temas):
Este icono abre un cuadro de diálogo elemento flotante que proporciona una manera de seleccionar uno de los
tres modos de Barra de acciones:
Estándar de – Consta de un logotipo, un icono y un texto de título con un subtítulo opcional.
Lista de – Modo de navegación de lista. En lugar de texto de título estático, este modo presenta un menú
de lista para la navegación dentro de la actividad (es decir, se puede presentar al usuario como una lista
desplegable).
Pestañas – Modo de navegación por tabulación. En lugar del texto del título estático, este modo presenta
una serie de pestañas para la navegación dentro de la actividad.

Temas
En el menú desplegable de tema se muestran todos los temas definidos en el proyecto. Al seleccionar más
temas , se abre un cuadro de diálogo con una lista de todos los temas disponibles en el Android SDK instalado,
como se muestra a continuación:

Cuando se selecciona un tema, el Superficie de diseño se actualiza para mostrar el efecto del nuevo tema. Tenga
en cuenta que este cambio se hace permanente solo si se hace clic en el botón Aceptar del cuadro de diálogo
tema . Una vez que se ha seleccionado un tema, se incluirá en el menú desplegable del tema , como se muestra a
continuación:
El ![tema claro ya está disponible] El (resource-qualifiers-images/vs/16-light-theme.png "tema claro ya está
disponible")

Versión de Android
El selector de versión de Android establece la versión de Android que se usa para representar el diseño en el
diseñador. El selector muestra todas las versiones que son compatibles con la versión de .NET Framework de
destino del proyecto:

La versión de .NET Framework de destino se puede establecer en la configuración del proyecto en propiedades
> aplicación > compilar con la versión de Android. Para obtener más información acerca de la versión de
.NET Framework de destino, consulte Descripción de los niveles de API de Android.
El conjunto de widgets disponibles en el cuadro de herramientas viene determinado por la versión de .NET
Framework de destino del proyecto. Esto también se aplica a las propiedades disponibles en la ventana
Propiedades. La lista de widgets disponible no está determinada por el valor seleccionado en el selector de
versión de la barra de herramientas. Por ejemplo, si establece la versión de destino del proyecto en Android 4,4,
todavía puede seleccionar Android 6,0 en el selector de versión de la barra de herramientas para ver el aspecto
del proyecto en Android 6,0, pero no podrá agregar widgets que sean específicos de Android 6,0 – . seguirá
estando limitado a los widgets que están disponibles en Android 4,4.
Para obtener más información sobre los tipos de recursos, vea recursos de Android.
Vistas de diseños alternativos
11/07/2019 • 22 minutes to read • Edit Online

Este tema explica cómo pueden los diseños de versión mediante el uso de calificadores de recursos. Por ejemplo,
cree una versión de un diseño que solo se usa cuando el dispositivo está en modo horizontal y una versión de
diseño que es solo para el modo vertical.
Visual Studio
Visual Studio para Mac

Crear diseños alternativos


Al hacer clic en el vista alternativa de diseño icono (a la izquierda del dispositivo), se abre un panel de vista
previa para obtener una lista de los diseños alternativos disponibles en el proyecto. Si no hay ningún diseños
alternativos, el predeterminado se presenta la vista:

Al hacer clic en el signo más verde junto a nueva versión, crear variación de diseño abre el cuadro de diálogo
para que pueda seleccionar los calificadores de recursos de esta variación de diseño:
En el ejemplo siguiente, el calificador de recursos de orientación de pantalla está establecido en horizontaly el
tamaño de la pantalla cambia a grande. Esto crea una nueva versión de diseño denominada grandes land:

Tenga en cuenta que el panel de vista previa de la izquierda muestra los efectos de las selecciones del calificador
de recursos. Al hacer clic en agregar crea el diseño alternativo y se activa el diseñador para que el diseño. El vista
de diseño alternativa panel de vista previa indica qué diseño se carga en el diseñador mediante un pequeño
puntero derecho como se indica en la captura de pantalla siguiente:

Edición de diseños alternativos


Al crear diseños alternativos, suele ser deseable para realizar un único cambio que se aplica a todas las versiones
bifurcadas de un diseño. Por ejemplo, es posible que desee cambiar el texto del botón amarillo en todos los
diseños. Si tiene un gran número de diseños y deba propagar un único cambio a todas las versiones,
mantenimiento puede volverse rápidamente complicado y propensas a errores.
Para simplificar el mantenimiento de varias versiones de diseño, el diseñador proporciona una editar varios
modo que propaga los cambios a través de uno o varios diseños. Cuando hay más de un diseño, el editar varios
icono se muestra:
Al hacer clic en el editar varios icono, aparecen líneas que indican que los diseños están vinculados (como se
muestra a continuación); es decir, al realizar un cambio en un diseño, dicho cambio se propaga a los diseños
vinculados. Puede desvincular todos los diseños, haga clic en el icono con un círculo indicado en la siguiente
captura de pantalla:

Si tiene más de dos diseños, selectivamente puede alternar el botón Editar a la izquierda de cada vista previa del
diseño para determinar qué diseños están vinculados entre sí. Por ejemplo, si desea realizar un único cambio que
se propaga a la primera y última de tres diseños, desea desvincular el diseño central como se muestra aquí:
En este ejemplo, realiza un cambio en el predeterminado o largo diseño se propagará al diseño del, pero no a la
grandes land diseño.
Ejemplo de edición múltiple
En general, al realizar un cambio en un diseño, ese mismo cambio se propaga a todos los demás diseños
vinculados. Por ejemplo, al agregar un nuevo TextView widget a la predeterminado diseño y cambiar su texto
de string a Portrait hará que el mismo cambio para diseños vinculados. Este es su aspecto la predeterminado
diseño:

El TextView también se agrega a la grandes land la vista Diseño porque está vinculado a la predeterminado
diseño:
Pero ¿qué ocurre si desea realizar un cambio local en un solo diseño (es decir, no desea que los cambios se
propaguen a cualquiera de los otros diseños)? Para ello, debe desvincular el diseño que desee cambiar antes de
modificarlo, tal como se explica a continuación.
Realización de cambios locales
Supongamos que queremos ambos diseños tener agregado TextView , pero también queremos cambiar la
cadena de texto en el grandes land diseño Landscape lugar Portrait . Si se realiza este cambio a grandes land
mientras ambos diseños están vinculados, el cambio se propagará a la predeterminado diseño. Por lo tanto, en
primer lugar, debemos desvincular los dos diseños antes de realizar el cambio. Cuando se modifica el texto en
grandes land a Landscape , el Diseñador de marca este cambio con un marco rojo para indicar que el cambio es
local para el grandes land diseño y es no volver a propagarse a la predeterminado diseño:
Al hacer clic en el predeterminado diseño para verlo, el TextView todavía se establece la cadena de texto en
Portrait .

Control de conflictos
Si decide cambiar el color del texto en el predeterminado diseño a verde, aparecerá un icono de advertencia en
el diseño vinculado. Al hacer que el diseño, abre el diseño para mostrar el conflicto. Se resalta el widget que
provocó el conflicto con un marco rojo y se muestra el mensaje siguiente: Los cambios recientes han generado
conflictos en este diseño alternativo.

Un cuadro conflicto se muestra a la derecha del widget para explicar el conflicto:


El cuadro de conflicto muestra la lista de propiedades que han cambiado y enumera sus valores. Al hacer clic en
omitir conflicto solo se aplica el cambio de propiedad a este widget. Al hacer clic en aplicar se aplica el cambio
de propiedad para este widget, así como para el widget homólogo en vinculado predeterminado diseño. Si se
aplican a todos los cambios de propiedad, se descarta automáticamente el conflicto.
Ver conflictos de grupo
Los cambios de propiedades no son la única fuente de conflictos. Al insertar o extraer widgets, se pueden detectar
conflictos. Por ejemplo, cuando el grandes land se desvincula el diseño de la predeterminado diseño y el
TextView en el grandes land diseño de arrastrar y colocar encima de la Button , el Diseñador de marca del
widget movido para indicar el conflicto:
Sin embargo, no hay ningún marcador en el Button . Aunque la posición de la Button ha cambiado, el Button
no muestra cambios aplicados a los que son específicos de la grandes land configuración.
Si un CheckBox se agrega a la predeterminado diseño, se genera otro conflicto y se muestra un icono de
advertencia sobre la grandes land diseño:

Al hacer clic en el grandes land diseño revela el conflicto. Se mostrará el mensaje siguiente: Los cambios
recientes han generado conflictos en este diseño alternativo:
Además, en el cuadro de conflicto se muestra el mensaje siguiente:

Agregar el CheckBox provoca un conflicto porque los grandes land diseño tiene cambios en el LinearLayout que
lo contiene. Sin embargo, en este caso el cuadro de conflictos muestra el widget que se acaba de insertar en el
predeterminado diseño (el CheckBox ).
Si hace clic en omitir conflicto, el diseñador resuelve el conflicto, lo que permite el widget que aparece en el
cuadro de conflictos para poder arrastrar y colocar en el diseño que falta el widget (en este caso, el grandes land
diseño):
Tal como se muestra en el ejemplo anterior con el Button , el CheckBox no tiene un marcador de cambio de color
rojo, porque sólo la LinearLayout tiene cambios que se aplicaron en el grandes land diseño.
Persistencia de conflicto
Los conflictos se almacenan en el archivo de diseño como comentarios XML, como se muestra aquí:

<!-- Widget Inserted Conflict | id:__root__ | @+id/checkBox1 -->

Por lo tanto, cuando se cierra y se vuelve a abrir un proyecto, todos los conflictos igualmente estar allí – incluso a
los que se han omitido.
Características de diseño de material de Xamarin.
Android Designer
16/08/2019 • 25 minutes to read • Edit Online

En este tema se describen las características del diseñador que facilitan a los desarrolladores la creación de
diseños conformes al diseño. En esta sección se presenta y explica cómo usar la cuadrícula material, la paleta de
colores material, la escala tipográfica y el editor de temas.

Evolve 2016: Todo el mundo puede crear aplicaciones atractivas con el diseño de materiales

Información general
Xamarin. Android Designer incluye características que facilitan la creación de diseños compatibles con el diseño
de materiales. Si no está familiarizado con el diseño de material, consulte la Introducción al diseño de materiales.
Visual Studio
Visual Studio para Mac
En esta guía, echaremos un vistazo a las siguientes características del diseñador:
Cuadrícula de materiales – Superposición en el superficie de diseño que muestra una cuadrícula,
espaciado y líneas para ayudarle a colocar widgets de diseño de acuerdo con las directrices de diseño de
materiales.
Editor de temas – Editor de recursos de color pequeño que permite establecer información de color para
un subconjunto de un tema. Por ejemplo, puede obtener una vista previa de los colores de colorPrimary
material colorPrimaryDark , como colorAccent , y.
Veremos cada una de estas características y proporcionamos ejemplos de cómo usarlas.

Cuadrícula de diseño de materiales


El menú cuadrícula de diseño de material está disponible en la barra de herramientas de la parte superior del
diseñador:
Al hacer clic en el icono de la cuadrícula de diseño de material, el diseñador muestra una superposición en el
Superficie de diseño que incluye los elementos siguientes:
Líneas (líneas naranja)
Espaciado (áreas verdes)
Una cuadrícula (líneas azules)
Estos elementos pueden verse en la captura de pantalla anterior. Cada uno de estos elementos superpuesto es
configurable. Al hacer clic en los puntos suspensivos junto al menú cuadrícula de diseño de materiales, se abre un
cuadro de diálogo elemento flotante que le permite deshabilitar o habilitar la cuadrícula, configurar la ubicación
de líneas y establecer espaciados. Tenga en cuenta que todos los valores dp se expresan en (píxeles
independientes de la densidad):

Para agregar un nuevo KEYLINE, escriba un nuevo valor de desplazamiento en el cuadro desplazamiento ,
seleccione una ubicación (izquierda, superior, derechao inferior) y haga clic en el icono + para agregar el
nuevo KEYLINE. Del mismo modo, para agregar un nuevo espaciado, escriba el tamaño y el desplazamiento (en
DP ) en los cuadros tamaño y desplazamiento , respectivamente. Seleccione una ubicación (izquierda,
superior, derechao inferior) y haga clic en el icono + para agregar el nuevo espaciado.
Al cambiar estos valores de configuración, se guardan en el archivo XML de diseño y se reutilizan cuando se
vuelve a abrir el diseño.

Editor de temas
El Editor de temas permite personalizar la información de color para un subconjunto de atributos de tema. Para
abrir el Editor de temas, haga clic en el icono de pincel en la barra de herramientas:
Aunque el Editor de temas es accesible desde la barra de herramientas para todos los niveles de API y versiones
de Android de destino, solo hay disponible un subconjunto de las funcionalidades que se describen a
continuación si el nivel de API de destino es anterior a la API 21 (Android 5,0 Lollipop).
En el panel izquierdo del editor de temas se muestra la lista de colores que componen el tema seleccionado
actualmente (en este ejemplo, usamos el Default Theme ):

Al seleccionar un color de la izquierda, el panel de la derecha proporciona las siguientes pestañas para ayudarle a
editar el color:
Heredar – Muestra un diagrama de herencia de estilo para el color seleccionado y muestra el color y el
código de color resueltos asignados a ese color de tema.
Selector de colores – Permite cambiar el color seleccionado a cualquier valor arbitrario.
Paleta de materiales – Permite cambiar el color seleccionado a un valor que se ajuste al diseño del
material.
Recursos de – Permite cambiar el color seleccionado a uno de los otros recursos de color existentes en el
tema.
Echemos un vistazo a cada una de estas pestañas en detalle.
Heredar (pestaña)
Como se muestra en el ejemplo siguiente, la pestaña heredar muestra la herencia de estilo para el color de fondo
del tema predeterminado:
En este ejemplo, el tema predeterminado hereda de un estilo que utiliza @color/background_material_light pero
lo reemplaza por color/material_grey_50 , que tiene un valor de código de color de #fffafafa . Para obtener más
información sobre la herencia de estilos, vea estilos y temas.
Selector de colores
En la captura de pantalla siguiente se muestra el selector de colores:

En este ejemplo, el color de fondo se puede cambiar a cualquier valor a través de varios medios:
Hacer clic en un color directamente.
Especificar valores de matiz, saturación y luminosidad.
Escribir valores RGB (rojo, verde y azul) en formato decimal.
Establecer el valor alfa (opacidad) del color seleccionado.
Escribir directamente el código de color hexadecimal.
El color que elija en el selector de colores no está restringido a las directrices de diseño de materiales ni al
conjunto de recursos de color disponibles.
Recursos
La pestaña recursos ofrece una lista de recursos de color que ya están presentes en el tema:
El uso de la pestaña recursos restringe las opciones a esta lista de colores. Tenga en cuenta que si elige un
recurso de color que ya está asignado a otra parte del tema, dos elementos adyacentes de la interfaz de usuario
pueden "ejecutarse juntos" (porque tienen el mismo color) y resultan difíciles de distinguir para el usuario.
Paleta de materiales
La pestaña paleta de materiales abre la paleta de colores de diseño de materiales. Al elegir un valor de color
de esta paleta se restringe su elección de color para que sea coherente con las directrices de diseño de materiales:

En la parte superior de la paleta de colores se muestran los colores del diseño del material principal, mientras que
la parte inferior de la paleta muestra un intervalo de tonos para el color primario seleccionado. Por ejemplo, al
seleccionar Indigo, se muestra una colección de los tonos de Indigo en la parte inferior del cuadro de diálogo. Al
seleccionar un matiz, el color de la propiedad cambia al matiz seleccionado. En el ejemplo siguiente, el
Background Tint del botón cambia a Indigo 500:
Background Tint está establecido en el código de color para Indigo 500 ( #ff3f51b5 ) y el diseñador actualiza el
color de fondo para reflejar este cambio:

Para obtener más información acerca de la paleta de colores de diseño de materiales, consulte la Guía de paleta
de coloresde diseño de materiales.
Crear un nuevo tema
En el ejemplo siguiente, usaremos la paleta de materiales para crear un nuevo tema personalizado. En primer
lugar, cambiaremos el color de fondo a azul 900:
Cuando se cambia un recurso de color, aparece un mensaje con el mensaje, el tema actual tiene cambios sin
guardar:

El color de fondo del diseñador ha cambiado a la nueva selección de color, pero este cambio aún no se ha
guardado. En este momento, puede realizar una de las siguientes acciones:
Haga clic en descartar cambios para descartar la opción de nuevo color (o opciones) y revertir el tema a
su estado original.
Presione Ctrl + S para guardar los cambios en el tema actual.
En el ejemplo siguiente, se presionó Ctrl + S para que los cambios se guardaran en AppTheme:

Resumen
En este tema se describen las características de diseño de materiales disponibles en Xamarin. Android Designer.
Se explicó cómo habilitar y configurar la cuadrícula de diseño de material y se explicó cómo usar el editor de
temas para crear nuevos temas personalizados que se ajusten a las directrices de diseño de materiales. Para
obtener más información sobre la compatibilidad de Xamarin. Android con el diseño de material, consulte el tema
material.

Vínculos relacionados
Tema de materiales
Introducción al diseño de materiales
Tema de materiales
16/08/2019 • 18 minutes to read • Edit Online

El tema material es un estilo de interfaz de usuario que determina la apariencia y el funcionamiento de las vistas
y actividades a partir de Android 5,0 (Lollipop). El tema material está integrado en Android 5,0, por lo que la
interfaz de usuario del sistema y las aplicaciones lo usan. El tema material no es un "tema" en el sentido de una
opción de apariencia para todo el sistema que un usuario puede elegir de forma dinámica en un menú de
configuración. En su lugar, el tema material puede considerarse como un conjunto de estilos base integrados
relacionados que puede usar para personalizar la apariencia de la aplicación.
Android proporciona tres tipos de tema de material:
Theme.Material – Versión oscura del tema material; este es el tipo predeterminado en Android 5,0.
Theme.Material.Light – Versión ligera del tema material.
Theme.Material.Light.DarkActionBar – Versión ligera del tema material, pero con una barra de acciones
oscura.
Aquí se muestran ejemplos de estos tipos de tema de material:

Puede derivar del tema material para crear su propio tema, invalidando algunos o todos los atributos de color.
Por ejemplo, puede crear un tema que se derive de Theme.Material.Light , pero invalida el color de la barra de la
aplicación para que coincida con el color de la marca. También puede aplicar un estilo a vistas individuales; por
ejemplo, puede crear un estilo para CardView que tenga más esquinas redondeadas y use un color de fondo
más oscuro.
Puede usar un solo tema para una aplicación completa o puede usar distintos temas para diferentes pantallas
(actividades) en una aplicación. En las capturas de pantallas anteriores, por ejemplo, una sola aplicación usa un
tema diferente para cada actividad con el fin de mostrar las combinaciones de colores integradas. Los botones
de radio cambian la aplicación a diferentes actividades y, como resultado, muestran temas diferentes.
Dado que el tema material solo se admite en Android 5,0 y versiones posteriores, no se puede usar (o un tema
personalizado derivado del tema material) para que la aplicación se ejecute en versiones anteriores de Android.
Sin embargo, puede configurar la aplicación para que use el tema material en dispositivos Android 5,0 y revertir
correctamente a un tema anterior cuando se ejecute en versiones anteriores de Android (consulte la sección de
compatibilidad de este artículo para obtener más información).

Requisitos
Lo siguiente es necesario para usar las nuevas características de tema de material de Android 5,0 en aplicaciones
basadas en Xamarin:
Xamarin. Android – Xamarin. Android 4,20 o posterior debe estar instalado y configurado con Visual
Studio o Visual Studio para Mac.
Android SDK – Android 5,0 (API 21) o posterior debe instalarse a través del administrador de Android
SDK.
Java JDK 1,8 – JDK 1,7 puede usarse si se trata de destino de nivel de API 23 y versiones anteriores. JDK
1,8 está disponible en Oracle.
Para obtener información sobre cómo configurar un proyecto de aplicación de Android 5,0, consulte
configuración de un proyecto de android 5,0.

Usar los temas integrados


La forma más sencilla de usar el tema material es configurar la aplicación para que use un tema integrado sin
personalización. Si no desea configurar explícitamente un tema, la aplicación tendrá como Theme.Material valor
predeterminado (el tema oscuro). Si la aplicación tiene solo una actividad, puede configurar un tema en el nivel
de actividad. Si la aplicación tiene varias actividades, puede configurar un tema en el nivel de aplicación para que
use el mismo tema en todas las actividades, o puede asignar distintos temas a actividades diferentes. En las
siguientes secciones se explica cómo configurar temas en el nivel de la aplicación y en el nivel de actividad.
Crear una aplicación
Para configurar una aplicación completa para que use un tipo de tema material, android:theme establezca el
atributo del nodo de aplicación en archivo AndroidManifest. XML en uno de los siguientes:
@android:style/Theme.Material – Tema oscuro.
@android:style/Theme.Material.Light – Tema claro.
@android:style/Theme.Material.Light.DarkActionBar – Tema claro con barra de acciones oscuras.

En el ejemplo siguiente se configura la aplicación MyApp para usar el tema claro:

<application android:label="MyApp"
android:theme="@android:style/Theme.Material.Light">
</application>

Como alternativa, puede establecer el atributo de Theme aplicación en AssemblyInfo.CS (o Properties.CS ).


Por ejemplo:

[assembly: Application(Theme="@android:style/Theme.Material.Light")]

Cuando el tema de la aplicación se @android:style/Theme.Material.Light establece en, todas las actividades de


MyApp se Theme.Material.Light mostrarán con.
Una actividad
Para aplicar un tema a una actividad, Theme agregue una configuración [Activity] al atributo por encima de la
declaración Theme de actividad y asígnela al tipo de tema material que desee usar. En el ejemplo siguiente se
temas de Theme.Material.Light una actividad con:
[Activity(Theme = "@android:style/Theme.Material.Light",
Label = "MyApp", MainLauncher = true, Icon = "@drawable/icon")]

Otras actividades de esta aplicación usarán la combinación Theme.Material de colores oscuro predeterminada
(o, si está configurado, la configuración de tema de la aplicación).

Uso de temas personalizados


Puede mejorar su marca mediante la creación de un tema personalizado que permite aplicar estilos a
la’aplicación con los colores de su marca. Para crear un tema personalizado, se define un nuevo estilo que se
deriva de un tipo de tema material integrado y se reemplazan los atributos de color que se desean cambiar. Por
ejemplo, puede definir un tema personalizado que deriva de Theme.Material.Light.DarkActionBar y cambia el
color de fondo de la pantalla a beige en lugar de a blanco.
El tema material expone los siguientes atributos de diseño para la personalización:
colorPrimary – Color de la barra de la aplicación.
colorPrimaryDarkEl color de la barra de estado y las barras de la aplicación contextual; normalmente es
una versión oscura de colorPrimary . –
colorAccent – Color de los controles de interfaz de usuario, como las casillas, los botones de radio y los
cuadros de texto de edición.
windowBackground – Color del fondo de la pantalla.
textColorPrimary – Color del texto de la interfaz de usuario en la barra de la aplicación.
statusBarColor – Color de la barra de estado.
navigationBarColor – Color de la barra de navegación.

Estas áreas de pantalla se etiquetan en el diagrama siguiente:

De forma predeterminada statusBarColor , se establece en el valor colorPrimaryDark de. Puede establecer


statusBarColor en un color sólido, o bien puede establecerlo @android:color/transparent en para que la barra
de estado sea transparente. La barra de navegación también se puede hacer transparente navigationBarColor
estableciendo en. @android:color/transparent
Creación de un tema de aplicación personalizado
Puede crear un tema de aplicación personalizado mediante la creación y modificación de archivos en la carpeta
recursos del proyecto de la aplicación. Para aplicar estilo a la aplicación con un tema personalizado, siga estos
pasos:
Cree un archivo colors. XML en recursos/valores — . este archivo se usa para definir los colores del tema
personalizado. Por ejemplo, puede pegar el código siguiente en el archivo colors. XML para ayudarle a
comenzar:

<?xml version="1.0" encoding="UTF-8" ?>


<resources>
<color name="my_blue">#3498DB</color>
<color name="my_green">#77D065</color>
<color name="my_purple">#B455B6</color>
<color name="my_gray">#738182</color>
</resources>

Modifique este archivo de ejemplo para definir los nombres y códigos de color para los recursos de color
que utilizará en el tema personalizado.
Cree una carpeta Resources /Values-V21 . En esta carpeta, cree un archivo styles. XML :

Tenga en cuenta que Resources /Values-V21 es específico de Android 5,0 – las versiones anteriores de
Android no leerán los archivos de esta carpeta.
Agregue un resources nodo a styles. XML y defina style un nodo con el nombre del tema
personalizado. Por ejemplo, este es un archivo styles. XML que define MyCustomTheme (derivado del
estilo de Theme.Material.Light tema integrado):

<?xml version="1.0" encoding="UTF-8" ?>


<resources>
<!-- Inherit from the light Material Theme -->
<style name="MyCustomTheme" parent="android:Theme.Material.Light">
<!-- Customizations go here -->
</style>
</resources>

En este momento, una aplicación que usa MyCustomTheme mostrará el tema de Theme.Material.Light
existencias sin personalizaciones:
Agregue personalizaciones de color a styles. XML definiendo los colores de los atributos de diseño que
desee cambiar. Por ejemplo, para cambiar el color de la barra my_blue de la aplicación a y cambiar el
color my_purple de los controles de interfaz de usuario a, agregue invalidaciones de color a styles. XML
que hagan referencia a recursos configurados en Colors . XML:

<?xml version="1.0" encoding="UTF-8" ?>


<resources>
<!-- Inherit from the light Material Theme -->
<style name="MyCustomTheme" parent="android:Theme.Material.Light">
<!-- Override the app bar color -->
<item name="android:colorPrimary">@color/my_blue</item>
<!-- Override the color of UI controls -->
<item name="android:colorAccent">@color/my_purple</item>
</style>
</resources>

Una vez realizados estos cambios, una aplicación que use MyCustomTheme mostrará un color de barra de
aplicación my_blue en los controles de my_purple interfaz de usuario y Theme.Material.Light en, pero usará la
combinación de colores en cualquier otro lugar:

En este ejemplo, MyCustomTheme toma los colores de Theme.Material.Light para el color de fondo, la barra de
estado y los colores de texto, pero cambia el color de la my_blue barra de la aplicación a y establece el color
my_purple del botón de radio en.

Crear un estilo de vista personalizado


Android 5,0 también permite aplicar estilo a una vista individual. Después de crear los colores. XML y styles.
XML (como se describe en la sección anterior), puede Agregar un estilo de vista a styles. XML. Para aplicar
estilo a una vista individual, siga estos pasos:
Edite Resources /Values-V21/Styles. XML y agregue un style nodo con el nombre del estilo de vista
personalizado. Establezca los atributos de color personalizado para la vista en style este nodo. Por ejemplo,
para crear un estilo CardView personalizado que tenga más esquinas redondeadas y use my_blue como
color de fondo de la tarjeta, style agregue un nodo a styles. XML (dentro del resources nodo) y configure
el color de fondo y radio de redondeo:

<!-- Theme an individual view: -->


<style name="CardView.MyBlue">

<!-- Change the background color to Xamarin blue: -->


<item name="cardBackgroundColor">@color/my_blue</item>

<!-- Make the corners very round: -->


<item name="cardCornerRadius">18dp</item>
</style>

En el diseño, establezca el style atributo de esa vista para que coincida con el nombre de estilo
personalizado que eligió en el paso anterior. Por ejemplo:

<android.support.v7.widget.CardView
style="@style/CardView.MyBlue"
android:layout_width="200dp"
android:layout_height="100dp"
android:layout_gravity="center_horizontal">

En la captura de pantalla siguiente se proporciona un CardView ejemplo del valor predeterminado (que se
muestra a la CardView izquierda) en comparación con el estilo con CardView.MyBlue el tema personalizado (que
se muestra a la derecha):

En este ejemplo, se muestra CardView el personalizado con el color my_blue de fondo y un radio de esquina
18dp.

Compatibilidad
Para aplicar estilo a la aplicación de forma que use el tema material en Android 5,0, pero se revierte
automáticamente a un estilo compatible con las versiones anteriores de Android, siga estos pasos:
Defina un tema personalizado en Resources/Values-V21/Styles. XML que se derive de un estilo material
Theme. Por ejemplo:

<resources>
<style name="MyCustomTheme" parent="android:Theme.Material.Light">
<!-- Your customizations go here -->
</style>
</resources>

Defina un tema personalizado en Resources/Values/Styles. XML que se derive de un tema anterior, pero
que use el mismo nombre de tema que el anterior. Por ejemplo:

<resources>
<style name="MyCustomTheme" parent="android:Theme.Holo.Light">
<!-- Your customizations go here -->
</style>
</resources>

En archivo AndroidManifest. XML, configure la aplicación con el nombre del tema personalizado. Por
ejemplo:

<application android:label="MyApp"
android:theme="@style/MyCustomTheme">
</application>

Como alternativa, puede aplicar un estilo a una actividad específica mediante el tema personalizado:

[Activity(Label = "MyActivity", Theme = "@style/MyCustomTheme")]

Si el tema usa colores definidos en un archivo colors. XML , asegúrese de colocar este archivo en
recursos/valores (en lugar de en recursos/valores-V21) para que ambas versiones del tema personalizado
puedan tener acceso a las definiciones de color.
Cuando la aplicación se ejecuta en un dispositivo Android 5,0, usará la definición de tema especificada en
Resources/Values-V21/Styles. XML. Cuando esta aplicación se ejecuta en dispositivos Android más antiguos,
se revierte automáticamente a la definición de tema especificada en Resources /Values/Styles. XML.
Para obtener más información sobre la compatibilidad de temas con versiones anteriores de Android, consulte
recursos alternativos.

Resumen
En este artículo se presentó el nuevo estilo de interfaz de usuario de tema de material incluido en Android 5,0
(Lollipop). Se han descrito los tres tipos de tema de material integrados que se pueden usar para aplicar estilo a
la aplicación, se ha explicado cómo crear un tema personalizado para la personalización de marca de la
aplicación y se ha proporcionado un ejemplo de cómo aplicar un tema a una vista individual. Por último, en este
artículo se explica cómo usar el tema material en la aplicación manteniendo la compatibilidad con versiones
anteriores de Android.

Vínculos relacionados
ThemeSwitcher (ejemplo)
Introducción al círculo
CardView
Recursos alternativos
Círculo de Android
Desarrollador de gráficos circulares de Android
Diseño de materiales
Principios del diseño de materiales
Mantener la compatibilidad
Perfil de usuario
31/07/2019 • 3 minutes to read • Edit Online

Android ha admitido la enumeración de contactos con el proveedor de ContactsContract desde el nivel de API 5.
Por ejemplo, la enumeración de contactos es tan sencilla como usar la clase ContactContracts. contacts tal como se
muestra en el ejemplo de código siguiente:

// Get the URI for the user's contacts:


var uri = ContactsContract.Contacts.ContentUri;

// Setup the "projection" (columns we want) for only the ID and display name:
string[] projection = {
ContactsContract.Contacts.InterfaceConsts.Id,
ContactsContract.Contacts.InterfaceConsts.DisplayName };

// Use a CursorLoader to retrieve the user's contacts data:


CursorLoader loader = new CursorLoader(this, uri, projection, null, null, null);
ICursor cursor = (ICursor)loader.LoadInBackground();

// Print the contact data to the console if reading back succeeds:


if (cursor != null)
{
if (cursor.MoveToFirst())
{
do
{
Console.WriteLine("Contact ID: {0}, Contact Name: {1}",
cursor.GetString(cursor.GetColumnIndex(projection[0])),
cursor.GetString(cursor.GetColumnIndex(projection[1])));
} while (cursor.MoveToNext());
}
}

A partir de Android 4 (nivel de API 14), la clase ContactsContact. Profile está disponible ContactsContract a través
del proveedor. El ContactsContact.Profile proporciona acceso al perfil personal para el propietario de un
dispositivo, que incluye los datos de contacto, como el nombre y el número de teléfono del propietario del
dispositivo.

Permisos necesarios
Para leer y escribir datos de contacto, las aplicaciones deben READ_CONTACTS solicitar WRITE_CONTACTS los permisos
y, respectivamente. Además, para leer y editar el perfil de usuario, las aplicaciones deben READ_PROFILE solicitar
WRITE_PROFILE los permisos y.

Actualizar datos de perfil


Una vez que se han establecido estos permisos, una aplicación puede usar las técnicas normales de Android para
interactuar con los datos del perfil de usuario. Por ejemplo, para actualizar el nombre para mostrar del perfil, llame
a ContentResolver devuelvan. Update con un Uri recuperado a través de la propiedad ContactsContract. Profile.
ContentRawContactsUri , como se muestra a continuación:
var values = new ContentValues ();
values.Put (ContactsContract.Contacts.InterfaceConsts.DisplayName, "John Doe");

// Update the user profile with the name "John Doe":


ContentResolver.Update (ContactsContract.Profile.ContentRawContactsUri, values, null, null);

Leyendo datos de perfil


La emisión de una consulta a ContactsContact. Profile. ContentUri vuelve a leer los datos del perfil. Por ejemplo, el
código siguiente leerá el nombre para mostrar del perfil de usuario:

// Read the profile


var uri = ContactsContract.Profile.ContentUri;

// Setup the "projection" (column we want) for only the display name:
string[] projection = {
ContactsContract.Contacts.InterfaceConsts.DisplayName };

// Use a CursorLoader to retrieve the data:


CursorLoader loader = new CursorLoader(this, uri, projection, null, null, null);
ICursor cursor = (ICursor)loader.LoadInBackground();
if (cursor != null)
{
if (cursor.MoveToFirst ())
{
Console.WriteLine(cursor.GetString (cursor.GetColumnIndex (projection [0])));
}
}

Desplazarse hasta el perfil de usuario


Por último, para desplazarse hasta el perfil de usuario, cree ActionView un intento con
ContactsContract.Profile.ContentUri una acción y, a StartActivity continuación, páselo al método de la siguiente
manera:

var intent = new Intent (Intent.ActionView,


ContactsContract.Profile.ContentUri);
StartActivity (intent);

Al ejecutar el código anterior, el perfil de usuario se muestra como se muestra en la siguiente captura de pantalla:
Trabajar con el perfil de usuario es similar a interactuar con otros datos en Android y ofrece un nivel adicional de
personalización del dispositivo.

Vínculos relacionados
ContactsProviderDemo (ejemplo)
Presentación del bocadillo de helado
Plataforma Android 4,0
Pantalla de presentación
16/08/2019 • 13 minutes to read • Edit Online

Una aplicación Android tarda algún tiempo en iniciarse, sobre todo cuando la aplicación se inicia por primera vez
en un dispositivo. Una pantalla de presentación puede mostrar el progreso de inicio al usuario o para indicar la
personalización de marca.

Información general
Una aplicación Android tarda algún tiempo en iniciarse, especialmente durante la primera vez que la aplicación se
ejecuta en un dispositivo (en ocasiones, esto se conoce como Inicio en frío). La pantalla de presentación puede
mostrar el progreso de inicio del usuario, o puede mostrar información de personalización de marca para
identificar y promover la aplicación.
En esta guía se describe una técnica para implementar una pantalla de presentación en una aplicación de Android.
Se tratan los pasos siguientes:
1. Crear un recurso dibujable para la pantalla de presentación.
2. Definir un nuevo tema que mostrará el recurso que se va a dibujar.
3. Agregar una nueva actividad a la aplicación que se usará como la pantalla de presentación definida por el
tema creado en el paso anterior.
Requisitos
En esta guía se da por supuesto que la aplicación tiene como destino el nivel de API de Android 15 (Android 4.0.3)
o superior. La aplicación también debe tener los paquetes de NuGet Xamarin. Android. support. V4 y Xamarin.
Android. support. V7. AppCompat agregados al proyecto.
Todo el código y XML de esta guía se pueden encontrar en el proyecto de ejemplo SplashScreen de esta guía.

Implementar una pantalla de presentación


La forma más rápida de presentar y mostrar la pantalla de presentación es crear un tema personalizado y aplicarlo
a una actividad que muestre la pantalla de presentación. Cuando se representa la actividad, carga el tema y aplica
el recurso que se dibuja (al que hace referencia el tema) al fondo de la actividad. Este enfoque evita la necesidad de
crear un archivo de diseño.
La pantalla de presentación se implementa como una actividad que muestra la marca dibujable, realiza las
inicializaciones y inicia cualquier tarea. Una vez que la aplicación se ha arrancado, la actividad de la pantalla de
presentación inicia la actividad principal y se quita de la pila de retroceso de la aplicación.
Crear un dibujable para la pantalla de presentación
La pantalla de presentación mostrará un XML que se podrá dibujar en el fondo de la actividad de la pantalla de
presentación. Es necesario usar una imagen de mapa de imágenes (como PNG o JPG ) para que se muestre la
imagen.
En esta guía, se usa una lista de capas para centrar la imagen de la pantalla de presentación en la aplicación. El
siguiente fragmento de código es un ejemplo drawable de un recurso layer-list que utiliza un:

<?xml version="1.0" encoding="utf-8"?>


<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<color android:color="@color/splash_background"/>
</item>
<item>
<bitmap
android:src="@drawable/splash"
android:tileMode="disabled"
android:gravity="center"/>
</item>
</layer-list>

Esto layer-listcentrará la imagen de bienvenida Splash. png en el fondo especificado por


@color/splash_background el recurso. Coloque este archivo XML en la carpeta Resources /drawable (por ejemplo,
Resources/ drawable/splash_screen. XML ).
Después de crear la pantalla de presentación dibujable, el paso siguiente consiste en crear un tema para la pantalla
de presentación.
Implementar un tema
Para crear un tema personalizado para la actividad de la pantalla de presentación, edite (o agregue) el archivo
Values/Styles. XML y cree un nuevo style elemento para la pantalla de presentación. A continuación se muestra
un archivo Values/Style. XML de style ejemplo con un denominado mis . Splash:

<resources>
<style name="MyTheme.Base" parent="Theme.AppCompat.Light">
</style>

<style name="MyTheme" parent="MyTheme.Base">


</style>

<style name="MyTheme.Splash" parent ="Theme.AppCompat.Light.NoActionBar">


<item name="android:windowBackground">@drawable/splash_screen</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowFullscreen">true</item>
</style>
</resources>

. Splash es muy Spartan – declara el fondo de la ventana, quita explícitamente la barra de título de la ventana y
declara que está en pantalla completa. Si desea crear una pantalla de presentación que eMule la interfaz de usuario
de la aplicación antes de que la actividad infla el primer diseño, puede usar windowContentOverlay en
windowBackground lugar de en la definición de estilo. En este caso, también debe modificar splash_screen. XML
drawable para que muestre una emulación de la interfaz de usuario.
Crear una actividad de presentación
Ahora necesitamos una nueva actividad para que Android inicie con la imagen de bienvenida y realice las tareas de
inicio. El código siguiente es un ejemplo de una implementación completa de la pantalla de presentación:
[Activity(Theme = "@style/MyTheme.Splash", MainLauncher = true, NoHistory = true)]
public class SplashActivity : AppCompatActivity
{
static readonly string TAG = "X:" + typeof(SplashActivity).Name;

public override void OnCreate(Bundle savedInstanceState, PersistableBundle persistentState)


{
base.OnCreate(savedInstanceState, persistentState);
Log.Debug(TAG, "SplashActivity.OnCreate");
}

// Launches the startup task


protected override void OnResume()
{
base.OnResume();
Task startupWork = new Task(() => { SimulateStartup(); });
startupWork.Start();
}

// Simulates background work that happens behind the splash screen


async void SimulateStartup ()
{
Log.Debug(TAG, "Performing some startup work that takes a bit of time.");
await Task.Delay (8000); // Simulate a bit of startup work.
Log.Debug(TAG, "Startup work is finished - starting MainActivity.");
StartActivity(new Intent(Application.Context, typeof (MainActivity)));
}
}

SplashActivity usa explícitamente el tema que se creó en la sección anterior, invalidando el tema predeterminado
de la aplicación. No es necesario cargar un diseño en OnCreate , ya que el tema declara una función dibujable
como fondo.
Es importante establecer el NoHistory=true atributo para que la actividad se quite de la pila de retroceso. Para
evitar que el botón atrás cancele el proceso de inicio, también puede invalidar OnBackPressed y hacer que no haga
nada:

public override void OnBackPressed() { }

El trabajo de inicio se realiza de OnResume forma asincrónica en. Esto es necesario para que el trabajo de inicio no
se ralentice o retrase la apariencia de la pantalla de inicio. Una vez completado el trabajo, SplashActivity se
iniciará MainActivity y el usuario puede empezar a interactuar con la aplicación.
Este nuevo SplashActivity se establece como la actividad del iniciador para la aplicación estableciendo
MainLauncher el atributo true en. Dado SplashActivity que ahora es la actividad del iniciador, MainActivity.cs
debe editar y quitar MainLauncher el atributo MainActivity de:

[Activity(Label = "@string/ApplicationName")]
public class MainActivity : AppCompatActivity
{
// Code omitted for brevity
}

Modo horizontal
La pantalla de presentación implementada en los pasos anteriores se mostrará correctamente en el modo vertical
y horizontal. Sin embargo, en algunos casos es necesario tener pantallas de presentación independientes para los
modos vertical y horizontal (por ejemplo, si la imagen de la pantalla de presentación está en pantalla completa).
Para agregar una pantalla de presentación para el modo horizontal, siga estos pasos:
1. En la carpeta Resources /drawable , agregue la versión horizontal de la imagen de la pantalla de
presentación que desee usar. En este ejemplo, splash_logo_land. png es la versión horizontal del logotipo
que se usó en los ejemplos anteriores (utiliza letras en blanco en lugar de azul).
2. En la carpeta Resources /drawable , cree una versión horizontal layer-list de la dibujable que se definió
anteriormente (por ejemplo, splash_screen_land. XML ). En este archivo, establezca la ruta de acceso del
mapa de bits en la versión horizontal de la imagen de la pantalla de presentación. En el ejemplo siguiente,
splash_screen_land. XML usa splash_logo_land. png:

<?xml version="1.0" encoding="utf-8"?>


<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<color android:color="@color/splash_background"/>
</item>
<item>
<bitmap
android:src="@drawable/splash_logo_land"
android:tileMode="disabled"
android:gravity="center"/>
</item>
</layer-list>

3. Cree la carpeta Resources /Values-Land si aún no existe.


4. Agregue los archivos colors. XML y style. XML a valores-terrenos (se pueden copiar y modificar desde
los archivos valores/colores. XML y valores/estilo. XML existentes).
5. Modifique Values-Land/Style. XML para que use la versión horizontal de drawable para
windowBackground . En este ejemplo, se usa splash_screen_land. XML :

<resources>
<style name="MyTheme.Base" parent="Theme.AppCompat.Light">
</style>
<style name="MyTheme" parent="MyTheme.Base">
</style>
<style name="MyTheme.Splash" parent ="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowBackground">@drawable/splash_screen_land</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowFullscreen">true</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowActionBar">true</item>
</style>
</resources>

6. Modifique Values-Land/colors. XML para configurar los colores que quiere usar para la versión horizontal
de la pantalla de presentación. En este ejemplo, el color de fondo de la pantalla de presentación cambia a
azul para el modo horizontal:

<?xml version="1.0" encoding="utf-8"?>


<resources>
<color name="primary">#2196F3</color>
<color name="primaryDark">#1976D2</color>
<color name="accent">#FFC107</color>
<color name="window_background">#F5F5F5</color>
<color name="splash_background">#3498DB</color>
</resources>

7. Vuelva a compilar y ejecutar la aplicación. Gire el dispositivo al modo horizontal mientras se sigue
mostrando la pantalla de presentación. La pantalla de presentación cambia a la versión horizontal:

Tenga en cuenta que el uso de una pantalla de presentación en modo horizontal no siempre proporciona una
experiencia sin problemas. De forma predeterminada, Android inicia la aplicación en modo vertical y la cambia al
modo horizontal, incluso si el dispositivo ya está en modo horizontal. Como resultado, si la aplicación se inicia
mientras el dispositivo está en modo horizontal, el dispositivo presenta brevemente la pantalla de presentación
vertical y, a continuación, anima el giro desde el vertical hasta la pantalla de presentación horizontal.
Desafortunadamente, esta transición inicial vertical a horizontal tiene lugar incluso cuando
ScreenOrientation = Android.Content.PM.ScreenOrientation.Landscape se especifica en las marcas de la actividad de
presentación. La mejor manera de solucionar esta limitación es crear una única imagen de pantalla de presentación
que se represente correctamente en los modos vertical y horizontal.

Resumen
En esta guía se describe una manera de implementar una pantalla de presentación en una aplicación de Xamarin.
Android; es decir, aplicar un tema personalizado a la actividad de inicio.

Vínculos relacionados
SplashScreen (ejemplo)
lista de capas que se dibujan
Patrones de diseño de material: pantallas de inicio
Diseños de Xamarin. Android
16/08/2019 • 3 minutes to read • Edit Online

Los diseños se usan para organizar los elementos que componen la interfaz de usuario de una pantalla (como una
actividad). En las secciones siguientes se explica cómo usar los diseños de uso más frecuente en las aplicaciones de
Xamarin. Android.
LinearLayout es un grupo de vistas que muestra los elementos de vista secundarios en una dirección lineal,
ya sea vertical u horizontalmente.

RelativeLayout es el grupo de vistas que muestra los elementos de vista secundarios en una posición
relativa. La posición de una vista se puede especificar en relación con los elementos del mismo nivel.

TableLayout es un grupo de vistas que muestra los elementos de vista secundarios en filas y columnas.
RecyclerView es un elemento de la interfaz de usuario que muestra una colección de elementos en una lista
o una cuadrícula, lo que permite al usuario desplazarse por la colección.

ListView es un grupo de vistas que crea una lista de elementos desplazables. Los elementos de la lista se
insertan automáticamente en la lista mediante un adaptador de lista. ListView Es un componente
importante de la interfaz de usuario de las aplicaciones de Android porque se usa en todas partes desde
listas cortas de opciones de menú hasta largas listas de contactos o favoritos de Internet. Proporciona una
manera sencilla de presentar una lista de desplazamiento de filas a las que se puede dar formato con un
estilo integrado o personalizarse en gran medida. Una instancia de ListView requiere un adaptador para
insertarlo con los datos contenidos en las vistas de fila.
GridView es un elemento de la interfaz de usuario que muestra los elementos en una cuadrícula
bidimensional que se puede desplazar.

GridLayout es un grupo de vistas que admite la colocación de vistas en una cuadrícula 2D, similar a una
tabla HTML.
Los diseños con pestañas son un conocido patrón de interfaz de usuario en aplicaciones móviles debido a
su simplicidad y facilidad de uso. Proporcionan una manera coherente y sencilla de desplazarse entre varias
pantallas en una aplicación.
LinearLayout de Xamarin. Android
16/08/2019 • 3 minutes to read • Edit Online

LinearLayoutes un ViewGroup que muestra secundario View elementos en una dirección lineal, ya sea vertical u
horizontalmente.
Tenga cuidado con el uso excesivo de LinearLayout . Si comienza a anidar varios LinearLayout , puede que desee
considerar la posibilidad de usar un RelativeLayout en lugar.
Inicie un nuevo proyecto denominado HelloLinearLayout.
Abra Resources/layout/main. axml e inserte lo siguiente:

<?xml version="1.0" encoding="utf-8"?>


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation= "vertical"
android:layout_width= "match_parent"
android:layout_height= "match_parent" >

<LinearLayout
android:orientation= "horizontal"
android:layout_width= "match_parent"
android:layout_height= "match_parent"
android:layout_weight= "1" >
<TextView
android:text= "red"
android:gravity= "center_horizontal"
android:background= "#aa0000"
android:layout_width= "wrap_content"
android:layout_height= "match_parent"
android:layout_weight= "1" />
<TextView
android:text= "green"
android:gravity= "center_horizontal"
android:background= "#00aa00"
android:layout_width= "wrap_content"
android:layout_height= "match_parent"
android:layout_weight= "1" />
<TextView
android:text= "blue"
android:gravity= "center_horizontal"
android:background= "#0000aa"
android:layout_width= "wrap_content"
android:layout_height= "match_parent"
android:layout_weight= "1" />
<TextView
android:text= "yellow"
android:gravity= "center_horizontal"
android:background= "#aaaa00"
android:layout_width= "wrap_content"
android:layout_height= "match_parent"
android:layout_weight= "1" />
</LinearLayout>

<LinearLayout
android:orientation= "vertical"
android:layout_width= "match_parent"
android:layout_height= "match_parent"
android:layout_weight= "1" >
<TextView
android:text= "row one"
android:textSize= "15pt"
android:textSize= "15pt"
android:layout_width= "match_parent"
android:layout_height= "wrap_content"
android:layout_weight= "1" />
<TextView
android:text= "row two"
android:textSize= "15pt"
android:layout_width= "match_parent"
android:layout_height= "wrap_content"
android:layout_weight= "1" />
<TextView
android:text= "row three"
android:textSize= "15pt"
android:layout_width= "match_parent"
android:layout_height= "wrap_content"
android:layout_weight= "1" />
<TextView
android:text= "row four"
android:textSize= "15pt"
android:layout_width= "match_parent"
android:layout_height= "wrap_content"
android:layout_weight= "1" />
</LinearLayout>

</LinearLayout>

Inspeccione atentamente este XML. Hay una raíz LinearLayout que define su orientación para que sea – vertical
todos View los elementos secundarios (de los que tiene dos) se apilarán verticalmente. El primer elemento
secundario es otro. LinearLayout que usa una orientación horizontal y el segundo elemento secundario es un
LinearLayout que usa una orientación vertical. Cada una de estas LinearLayout s anidadas contiene varios
TextView elementos, que están orientados entre sí de la manera definida por su elemento LinearLayout primario.

Ahora Abra HelloLinearLayout.CS y asegúrese de que carga el diseño Resources /layout/main. axml en el
OnCreate() forma

protected override void OnCreate (Bundle savedInstanceState)


{
base.OnCreate (savedInstanceState);
SetContentView (Resource.Layout.Main);
}

El SetContentView(int) método) carga el archivo de diseño para Activity el, especificado por el identificador –
Resources.Layout.Main de recurso hace referencia al archivo de diseño Resources /layout/main. axml .
Ejecute la aplicación. Debería ver lo siguiente:

Observe cómo los atributos XML definen el comportamiento de cada vista. Pruebe a experimentar con valores
diferentes para android:layout_weight para ver cómo se distribuye el espacio real de la pantalla en función del
peso de cada elemento. Vea el documento sobre objetos de diseño comunes para obtener más información sobre
cómo LinearLayout controla el android:layout_weight atributo.

Referencias
LinearLayout
TextView

Algunas partes de esta página son modificaciones basadas en el trabajo creado y compartido por el proyecto de
código abierto de Android y que se usan según los términos descritos en la licencia de atribución de Creative
Commons 2,5.
RelativeLayout de Xamarin. Android
16/08/2019 • 3 minutes to read • Edit Online

RelativeLayout es un ViewGroup que muestra secundario View elementos en posiciones relativas. La posición de
se View puede especificar en relación con los elementos del mismo nivel (por ejemplo, a la izquierda o por debajo
de un elemento determinado) o en posiciones relativas al RelativeLayout área (como alineada en la parte inferior
izquierda del centro).
Una RelativeLayout es una utilidad muy eficaz para diseñar una interfaz de usuario, ya que puede eliminar
ViewGroup anidadas. Si se encuentra con varios LinearLayout los grupos, es posible que pueda reemplazarlos por
un único RelativeLayout .
Inicie un nuevo proyecto denominado HelloRelativeLayout.
Abra el archivo Resources /layout/main. axml e inserte lo siguiente:

<?xml version="1.0" encoding="utf-8"?>


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Type here:"/>
<EditText
android:id="@+id/entry"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:drawable/editbox_background"
android:layout_below="@id/label"/>
<Button
android:id="@+id/ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/entry"
android:layout_alignParentRight="true"
android:layout_marginLeft="10dip"
android:text="OK" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="@id/ok"
android:layout_alignTop="@id/ok"
android:text="Cancel" />
</RelativeLayout>

Observe cada uno de android:layout_* los atributos, layout_below como, layout_alignParentRight y


layout_toLeftOf . Al usar RelativeLayout , puede utilizar estos atributos para describir cómo desea colocar cada
uno View de ellos. Cada uno de estos atributos define un tipo diferente de posición relativa. Algunos atributos
usan el identificador de recurso de un View elemento del mismo nivel para definir su propia posición relativa. Por
ejemplo, la última Button se define para que se encuentre a la izquierda y alineada con la parte superior de la
View identificada por el identificador ok (que es el anterior Button ).

Todos los atributos de diseño disponibles se definen en RelativeLayout.LayoutParams .


Asegúrese de cargar este diseño en el OnCreate() forma
protected override void OnCreate (Bundle savedInstanceState)
{
base.OnCreate (savedInstanceState);
SetContentView (Resource.Layout.Main);
}

El SetContentView(int) método carga el archivo de diseño para Activity el, especificado por el identificador —
Resource.Layout.Main de recurso hace referencia al archivo de diseño Resources /layout/main. axml .
Ejecute la aplicación. Debería ver el siguiente diseño:

Recursos
RelativeLayout
RelativeLayout.LayoutParams
TextView
EditText
Button

Algunas partes de esta página son modificaciones basadas en el trabajo creado y compartido por el proyecto de
código abierto de Android y que se usan según los términos descritos en la licencia de atribución de Creative
Commons 2,5.
TableLayout de Xamarin. Android
16/08/2019 • 2 minutes to read • Edit Online

TableLayout es un ViewGroup que muestra secundario View elementos de filas y columnas.


Inicie un nuevo proyecto denominado HelloTableLayout.
Abra el archivo Resources /layout/main. axml e inserte lo siguiente:

<?xml version="1.0" encoding="utf-8"?>


<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:stretchColumns="1">

<TableRow>
<TextView
android:layout_column="1"
android:text="Open..."
android:padding="3dip"/>
<TextView
android:text="Ctrl-O"
android:gravity="right"
android:padding="3dip"/>
</TableRow>

<TableRow>
<TextView
android:layout_column="1"
android:text="Save..."
android:padding="3dip"/>
<TextView
android:text="Ctrl-S"
android:gravity="right"
android:padding="3dip"/>
</TableRow>

<TableRow>
<TextView
android:layout_column="1"
android:text="Save As..."
android:padding="3dip"/>
<TextView
android:text="Ctrl-Shift-S"
android:gravity="right"
android:padding="3dip"/>
</TableRow>

<View
android:layout_height="2dip"
android:background="#FF909090"/>

<TableRow>
<TextView
android:text="X"
android:padding="3dip"/>
<TextView
android:text="Import..."
android:padding="3dip"/>
</TableRow>

<TableRow>
<TextView
android:text="X"
android:padding="3dip"/>
<TextView
android:text="Export..."
android:padding="3dip"/>
<TextView
android:text="Ctrl-E"
android:gravity="right"
android:padding="3dip"/>
</TableRow>

<View
android:layout_height="2dip"
android:background="#FF909090"/>

<TableRow>
<TextView
android:layout_column="1"
android:text="Quit"
android:padding="3dip"/>
</TableRow>
</TableLayout>

Observe cómo es similar a la estructura de una tabla HTML. El TableLayout el elemento es como el <table>
elemento HTML; TableRow es como un <tr> elemento; pero para las celdas, puede usar cualquier tipo de View
elemento. En este ejemplo, un TextView se utiliza para cada celda. Entre algunas de las filas, también hay un básico
View , que se usa para dibujar una línea horizontal.

Asegúrese de que la actividad HelloTableLayout carga este diseño en el OnCreate() forma

protected override void OnCreate (Bundle savedInstanceState)


{
base.OnCreate (savedInstanceState);
SetContentView (Resource.Layout.Main);
}

El SetContentView(int) método) carga el archivo de diseño para Activity el, especificado por el identificador —
Resource.Layout.Main de recurso hace referencia al archivo de diseño Resources /layout/main. axml .
Ejecute la aplicación. Debería ver lo siguiente:

Referencias
TableLayout
TableRow
TextView

Algunas partes de esta página son modificaciones basadas en el trabajo creado y compartido por el proyecto de
código abierto de Android y que se usan según los términos descritos en la licencia de atribución de Creative
Commons 2,5.
RecyclerView
16/08/2019 • 8 minutes to read • Edit Online

RecyclerView es un grupo de vistas para mostrar colecciones; está diseñado para ser un reemplazo más flexible
de grupos de vistas más antiguos, como ListView y GridView. En esta guía se explica cómo usar y personalizar
RecyclerView en aplicaciones de Xamarin. Android.

RecyclerView
Muchas aplicaciones necesitan Mostrar colecciones del mismo tipo (por ejemplo, mensajes, contactos, imágenes
o canciones); a menudo, esta colección es demasiado grande para caber en la pantalla, por lo que la colección se
presenta en una ventana pequeña que se puede desplazar sin problemas a través de todos los elementos de la
colección. RecyclerView es un widget de Android que muestra una colección de elementos en una lista o una
cuadrícula, lo que permite al usuario desplazarse por la colección. A continuación se muestra una captura de
pantalla de una aplicación RecyclerView de ejemplo que usa para mostrar el contenido de la bandeja de entrada
de correo electrónico en una lista de desplazamiento vertical:

RecyclerView ofrece dos características atractivas:


Tiene una arquitectura flexible que le permite modificar su comportamiento mediante la conexión de sus
componentes preferidos.
Es eficaz con las colecciones grandes porque reutiliza las vistas de elementos y requiere el uso de los
titulares de la vista para almacenar en caché las referencias de la vista.
En esta guía se explica cómo RecyclerView usar en las aplicaciones de Xamarin. Android; se explica cómo
RecyclerView agregar el paquete al proyecto de Xamarin. Android y se describe RecyclerView cómo funciona en
una aplicación típica. Se proporcionan ejemplos de código reales para mostrar cómo integrar RecyclerView en la
aplicación, cómo implementar un clic en la vista de elementos y cómo actualizar RecyclerView cuando cambian
los datos subyacentes. En esta guía se da por supuesto que está familiarizado con el desarrollo de Xamarin.
Android.
Requisitos
Aunque RecyclerView a menudo se asocia con el círculo de Android 5,0, se ofrece como una – biblioteca
RecyclerView de soporte técnico que funciona con aplicaciones que tienen como destino el nivel de API 7
(Android 2,1) y versiones posteriores. Se requiere lo siguiente para usar RecyclerView en aplicaciones basadas
en Xamarin:
Xamarin. Android – Xamarin. Android 4,20 o posterior debe estar instalado y configurado con Visual
Studio o Visual Studio para Mac.
El proyecto de la aplicación debe incluir el paquete Xamarin. Android. support. V7. RecyclerView .
Para obtener más información sobre la instalación de paquetes NuGet, consulte Tutorial: Incluir un NuGet
en el proyecto.
Información general
RecyclerView se puede considerar como sustituto de los ListView widgets y GridView en Android. Al igual que
sus predecesores, RecyclerView se ha diseñado para mostrar un conjunto de datos grande en una ventana
pequeña, pero RecyclerView ofrece más opciones de diseño y está mejor optimizada para mostrar colecciones
de gran tamaño. Si está familiarizado con ListView , hay varias diferencias importantes entre ListView y
RecyclerView :

RecyclerView es ligeramente más complejo de usar: tiene que escribir más código para su uso
RecyclerView en comparación ListView con.

RecyclerView no proporciona un adaptador predefinido; debe implementar el código de adaptador que


tiene acceso al origen de datos. Sin embargo, Android incluye varios adaptadores predefinidos que
funcionan ListView con GridView y.
RecyclerView no ofrece un evento de clic de elemento cuando un usuario pulsa un elemento; en su lugar,
los eventos de clic de elemento se controlan mediante las clases auxiliares. Por el contrario ListView ,
ofrece un evento de clic de elemento.
RecyclerView mejora el rendimiento mediante el reciclaje de vistas y la aplicación del patrón de
portaherramienta de la vista, lo que elimina las búsquedas de recursos de diseño innecesarios. El uso del
patrón View -portaherramienta es opcional en ListView .
RecyclerView se basa en un diseño modular que facilita la personalización. Por ejemplo, puede conectar
una directiva de diseño diferente sin cambios significativos en el código de la aplicación. Por el contrario
ListView , es relativamente monolítica en la estructura.

RecyclerViewincluye animaciones integradas para agregar y quitar elementos. ListView las animaciones
requieren algún esfuerzo adicional en la parte del desarrollador de la aplicación.
Secciones
Componentes y funcionalidad de RecyclerView
En este tema se explica Adapter cómo LayoutManager , y ViewHolder funcionan conjuntamente como clases
auxiliares para admitir RecyclerView . Proporciona información general de alto nivel de cada una de estas clases
auxiliares y explica cómo usarlas en la aplicación.
Ejemplo de RecyclerView básico
Este tema se basa en la información proporcionada en las partes y la funcionalidad de RecyclerView
proporcionando ejemplos de código reales RecyclerView de cómo se implementan los distintos elementos para
compilar una aplicación de exploración de fotografías en el mundo real.
Extender el ejemplo de RecyclerView
En este tema se agrega código adicional a la aplicación de ejemplo que se presenta en un ejemplo de
RecyclerView básico para mostrar cómo controlar los RecyclerView eventos de clic de elemento y actualizar
cuando cambia el origen de datos subyacente.
Resumen
En esta guía se ha RecyclerView introducido el widget Android; se ha explicado cómo agregar la RecyclerView
biblioteca de compatibilidad a los RecyclerView proyectos de Xamarin. Android, cómo recicla las vistas, cómo
aplica el modelo de portaherramienta de la vista para mejorar la eficacia y cómo las distintas clases auxiliares que
componen RecyclerView la colaboración para mostrar colecciones. Se ha proporcionado código de ejemplo para
RecyclerView mostrar cómo se integra en una aplicación, se ha explicado cómo personalizar RecyclerView la
Directiva de diseño mediante la conexión a diferentes administradores de diseño y se ha descrito cómo controlar
eventos de clic de elemento y notificar RecyclerView de cambios en el origen de datos.
Para obtener más información RecyclerView sobre, vea la referencia de la clase RecyclerView.

Vínculos relacionados
RecyclerViewer (ejemplo)
Introducción al círculo
RecyclerView
Componentes y funcionalidad de RecyclerView
16/08/2019 • 18 minutes to read • Edit Online

RecyclerView controla algunas tareas internamente (como el desplazamiento y el reciclaje de vistas), pero es
esencialmente un administrador que coordina las clases auxiliares para mostrar una colección. RecyclerView
delega las tareas a las siguientes clases auxiliares:
Adapter Infla los diseños de elementos (crea instancias del contenido de un archivo de diseño) y enlaza los
datos a las vistas que se muestran en RecyclerView un. – El adaptador también informa de los eventos de
clic de elemento.
LayoutManager Mide y coloca las vistas de elementos RecyclerView dentro de un y administra la Directiva
para el reciclaje de vistas. –
ViewHolder – Busca y almacena las referencias de la vista. El titular de la vista también ayuda a detectar los
clics de elementos y vistas.
ItemDecoration – Permite que una aplicación agregue desplazamientos de dibujo y diseño especiales a
vistas específicas para dibujar divisores entre elementos, resaltados y límites de agrupación visual.
ItemAnimator – Define las animaciones que tienen lugar durante las acciones del elemento o cuando se
realizan cambios en el adaptador.
La relación entre las RecyclerView clases LayoutManager ,y Adapter se representa en el diagrama siguiente:

Como se muestra en esta ilustración, LayoutManager el se puede considerar como intermediario Adapter entre y
RecyclerView . Realiza llamadas Adapter en RecyclerView métodos en nombre del. LayoutManager Por ejemplo,
LayoutManager llama a un Adapter método cuando es el momento de crear una nueva vista para una posición de
elemento RecyclerView determinada en. El Adapter aumenta el diseño de ese elemento y crea una ViewHolder
instancia de (no se muestra) para almacenar en caché las referencias a las vistas en esa posición. LayoutManager
Cuando Adapter llama a para enlazar un elemento determinado al conjunto de datos, busca los datos de ese
elemento, los recupera del conjunto de datos y los copia en la vista de elemento asociada. Adapter
Cuando se RecyclerView usa en la aplicación, se requiere la creación de tipos derivados de las siguientes clases:
RecyclerView.Adapter Proporciona un enlace del conjunto de datos de la aplicación (que es específico de la
aplicación) a las vistas de elementos que se muestran en el RecyclerView . – El adaptador sabe cómo
asociar cada posición de vista-elemento de RecyclerView la a una ubicación específica en el origen de
datos. Además, el adaptador controla el diseño del contenido dentro de cada vista de elemento individual y
crea el titular de la vista para cada vista. El adaptador también informa de los eventos de clic de elemento
detectados por la vista de elementos.
RecyclerView.ViewHolder – Almacena en caché las referencias a las vistas en el archivo de diseño del
elemento para que las búsquedas de recursos no se repitan innecesariamente. El titular de la vista también
organiza los eventos de clic de elemento que se reenviarán al adaptador cuando un usuario puntee en la
vista de elemento asociada del titular de la vista.
RecyclerView.LayoutManager Coloca los elementos RecyclerView dentro de. – Puede usar uno de varios
administradores de diseño predefinidos o puede implementar su propio administrador de diseño
personalizado. RecyclerView delega la Directiva de diseño al administrador de diseño, por lo que puede
conectar otro administrador de diseño sin tener que realizar cambios significativos en la aplicación.
Además, opcionalmente, puede extender las clases siguientes para cambiar la apariencia de RecyclerView en la
aplicación:
RecyclerView.ItemDecoration
RecyclerView.ItemAnimator

Si no extiende ItemDecoration y ItemAnimator , RecyclerView utiliza implementaciones predeterminadas. En esta


guía no se explica cómo crear clases ItemDecoration y ItemAnimator personalizadas; para obtener más
información sobre estas clases, vea RecyclerView. ItemDecoration y RecyclerView. ItemAnimator.
Cómo funciona el reciclaje de vistas
RecyclerView no asigna una vista de elemento para cada elemento del origen de datos. En su lugar, asigna solo el
número de vistas de elemento que caben en la pantalla y reutiliza esos diseños de elemento a medida que el
usuario se desplaza. Cuando la vista se desplaza por primera vez fuera de la vista, pasa por el proceso de reciclaje
que se muestra en la ilustración siguiente:

1. Cuando una vista se desplaza fuera de la vista y ya no se muestra, se convierte en una vista de rechazo.
2. La vista de rechazo se coloca en un grupo y se convierte en una vista de reciclaje. Este grupo es una caché
de vistas que muestran el mismo tipo de datos.
3. Cuando se va a mostrar un nuevo elemento, se toma una vista del grupo de reciclaje para su reutilización.
Dado que esta vista debe volver a estar enlazada por el adaptador antes de mostrarse, se denomina vista
desfasada.
4. La vista desfasada se recicla: el adaptador busca los datos para el siguiente elemento que se va a mostrar y
copia estos datos en las vistas de este elemento. Las referencias de estas vistas se recuperan del titular de la
vista asociado a la vista reciclada.
5. La vista reciclada se agrega a la lista de elementos de RecyclerView que están a punto de ir en pantalla.
6. La vista reciclada pasa a la pantalla cuando el usuario desplaza el RecyclerView objeto hasta el siguiente
elemento de la lista. Mientras tanto, otra vista se desplaza fuera de la vista y se recicla según los pasos
anteriores.
Además de la reutilización de la RecyclerView vista de elementos, también usa otra optimización de eficacia: los
titulares de la vista. Un contenedor de vistas es una clase simple que almacena en caché las referencias de la vista.
Cada vez que el adaptador infla un archivo de diseño de elementos, también crea un contenedor de vistas
correspondiente. El titular de la FindViewById vista usa para obtener referencias a las vistas dentro del archivo de
diseño de elementos inflado. Estas referencias se usan para cargar datos nuevos en las vistas cada vez que se
recicla el diseño para Mostrar datos nuevos.
Administrador de diseño
El administrador de diseño es responsable de colocar los elementos RecyclerView en la pantalla; determina el tipo
de presentación (una lista o una cuadrícula), la orientación (si los elementos se muestran vertical u
horizontalmente) y qué elementos de dirección deben mostrarse. (en orden normal o en orden inverso). El
administrador de diseño también es responsable de calcular el tamaño y la posición de cada elemento en la
pantalla de RecycleView .
El administrador de diseño tiene un propósito adicional: determina la Directiva para Cuándo reciclar las vistas de
elementos que ya no son visibles para el usuario. Dado que el administrador de diseño es consciente de qué vistas
están visibles (y cuáles no), está en la mejor posición para decidir cuándo se puede reciclar una vista. Para reciclar
una vista, el administrador de diseño normalmente realiza llamadas al adaptador para reemplazar el contenido de
una vista reciclada con datos diferentes, como se describió anteriormente en Cómo funciona el reciclaje de vistas.
Puede extender RecyclerView.LayoutManager para crear su propio administrador de diseño o puede usar un
administrador de diseño predefinido. RecyclerView proporciona los siguientes administradores de diseño
predefinidos:
LinearLayoutManager – Organiza los elementos de una columna que se puede desplazar verticalmente o en
una fila que se puede desplazar horizontalmente.
GridLayoutManager – Muestra los elementos en una cuadrícula.
StaggeredGridLayoutManager – Muestra los elementos en una cuadrícula escalonada, donde algunos
elementos tienen distintos altos y anchos.
Para especificar el administrador de diseño, cree una instancia del administrador de diseño elegido y páselo
SetLayoutManager al método. Tenga en cuenta que debe especificar el administrador – RecyclerView de diseño no
selecciona un administrador de diseño predefinido de forma predeterminada.
Para obtener más información sobre el administrador de diseño, vea la referencia de la clase RecyclerView.
LayoutManager.
El titular de la vista
El titular de la vista es una clase que se define para almacenar en caché las referencias de la vista. El adaptador
utiliza estas referencias de vista para enlazar cada vista a su contenido. Cada elemento de RecyclerView tiene una
instancia asociada de contenedor de vistas que almacena en memoria caché las referencias de la vista para ese
elemento. Para crear un contenedor de vistas, siga estos pasos para definir una clase que contenga el conjunto
exacto de vistas por elemento:
1. Subclase RecyclerView.ViewHolder .
2. Implemente un constructor que busque y almacene las referencias de la vista.
3. Implemente las propiedades que el adaptador puede usar para tener acceso a estas referencias.
Un ejemplo detallado de una ViewHolder implementación se presenta en un ejemplo de RecyclerView básico.
Para obtener más información RecyclerView.ViewHolder sobre, vea la referencia de la clase RecyclerView.
ViewHolder.
El adaptador
La mayor parte del "trabajo pesado" del código RecyclerView de integración tiene lugar en el adaptador.
RecyclerView requiere que proporcione un adaptador derivado de RecyclerView.Adapter para tener acceso al
origen de datos y rellenar cada elemento con el contenido del origen de datos. Dado que el origen de datos es
específico de la aplicación, debe implementar la funcionalidad del adaptador que entienda cómo obtener acceso a
los datos. El adaptador extrae información del origen de datos y la carga en cada elemento de RecyclerView la
colección.
En el dibujo siguiente se muestra cómo el adaptador asigna el contenido de un origen de datos a través de los
titulares de la vista a RecyclerView vistas individuales dentro de cada elemento de fila del:

El adaptador carga cada RecyclerView fila con datos para un elemento de fila determinado. En el caso de la
posición de fila p, por ejemplo, el adaptador busca los datos asociados en la posición p en el origen de datos y
copia estos datos en el elemento de fila en la posición p de la RecyclerView colección. En el dibujo anterior, por
ejemplo, el adaptador usa el portaherramienta de la vista para buscar las referencias ImageView de TextView y en
esa posición, por lo que no tiene FindViewById que llamar repetidamente a para esas vistas cuando el usuario se
desplaza por la colección y vuelve a usar las vistas.
Al implementar un adaptador, debe invalidar los métodos siguientes RecyclerView.Adapter :
OnCreateViewHolder – Crea una instancia del archivo de diseño del elemento y del titular de la vista.
OnBindViewHolder – Carga los datos en la posición especificada en las vistas cuyas referencias se almacenan
en el titular de la vista especificado.
ItemCount – Devuelve el número de elementos del origen de datos.

El administrador de diseño llama a estos métodos mientras coloca los elementos dentro RecyclerView de.
Notificar los cambios de datos de RecyclerView
RecyclerView no actualiza automáticamente su presentación cuando cambia el contenido de su origen de datos; el
adaptador debe notificar RecyclerView cuando se produzca un cambio en el conjunto de datos. El conjunto de
datos puede cambiar de muchas maneras. por ejemplo, el contenido de un elemento puede cambiar o se puede
modificar la estructura global de los datos. RecyclerView.Adapter proporciona una serie de métodos a los que
puede llamar para RecyclerView que responda a los cambios de datos de la manera más eficaz:
NotifyItemChanged – Indica que el elemento en la posición especificada ha cambiado.
NotifyItemRangeChanged – Indica que han cambiado los elementos del intervalo especificado de posiciones.
NotifyItemInserted – Indica que el elemento de la posición especificada se ha insertado recientemente.
NotifyItemRangeInserted – Indica que los elementos del intervalo especificado de posiciones se han
insertado recientemente.
NotifyItemRemoved – Indica que se ha quitado el elemento de la posición especificada.
NotifyItemRangeRemoved – Indica que se han quitado los elementos del intervalo especificado de posiciones.
NotifyDataSetChanged – Indica que el conjunto de datos ha cambiado (fuerza una actualización completa).

Si sabe exactamente cómo ha cambiado el conjunto de datos, puede llamar a los métodos adecuados anteriores
para actualizar RecyclerView de la manera más eficaz. Si no sabe exactamente cómo ha cambiado el conjunto de
datos, puede llamar a NotifyDataSetChanged , que es mucho menos eficaz porque RecyclerView debe actualizar
todas las vistas que son visibles para el usuario. Para obtener más información acerca de estos métodos, vea
RecyclerView. Adapter.
En el siguiente tema, un ejemplo de RecyclerView básico, se implementa una aplicación de ejemplo para mostrar
ejemplos de código reales de los elementos y la funcionalidad descritos anteriormente.

Vínculos relacionados
RecyclerView
Ejemplo de RecyclerView básico
Extender el ejemplo de RecyclerView
RecyclerView
Ejemplo de RecyclerView básico
16/08/2019 • 19 minutes to read • Edit Online

Para entender cómo RecyclerView funciona en una aplicación típica, en este tema se explora la aplicación de
ejemplo RecyclerViewer , un ejemplo de código RecyclerView sencillo que usa para mostrar una gran colección
de fotografías:

RecyclerViewer usa CardView para implementar cada elemento de fotografía en RecyclerView el diseño.
Debido a RecyclerView las ventajas de rendimiento de, esta aplicación de ejemplo puede desplazarse
rápidamente a través de una gran colección de fotografías sin problemas y sin retrasos apreciables.
Un origen de datos de ejemplo
En esta aplicación de ejemplo, un origen de datos de "álbum fotográfico" ( PhotoAlbum representado por la
RecyclerView clase) proporciona el contenido del elemento. PhotoAlbum es una colección de fotos con títulos; al
crear una instancia de ella, obtiene una colección preparada de 32 fotos:

PhotoAlbum mPhotoAlbum = new PhotoAlbum ();

Cada instancia de la PhotoAlbum foto de expone propiedades que le permiten leer su identificador de recurso de
PhotoID imagen, y su cadena de Caption título,. La colección de fotografías se organiza de forma que un
indexador puede acceder a cada foto. Por ejemplo, las siguientes líneas de código tienen acceso al identificador
de recurso de imagen y al título de la décima foto de la colección:
int imageId = mPhotoAlbum[9].ImageId;
string caption = mPhotoAlbum[9].Caption;

PhotoAlbum también proporciona un RandomSwap método al que se puede llamar para intercambiar la primera
foto de la colección con una fotografía elegida aleatoriamente en otro lugar de la colección:

mPhotoAlbum.RandomSwap ();

Dado que los detalles de PhotoAlbum implementación de no son relevantes RecyclerView para comprender
PhotoAlbum , el código fuente no se presenta aquí. El código fuente a PhotoAlbum está disponible en
Photoalbum.CS en la aplicación de ejemplo RecyclerViewer .
Diseño e inicialización
El archivo de diseño, Main. axml, consta de un RecyclerView único dentro LinearLayout de un:

<?xml version="1.0" encoding="utf-8"?>


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:scrollbars="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>

Tenga en cuenta que debe usar el nombre completo Android. support. V7. widget. RecyclerView porque
RecyclerView está empaquetado en una biblioteca de soporte técnico. El OnCreate método de MainActivity
inicializa este diseño, crea una instancia del adaptador y prepara el origen de datos subyacente:

public class MainActivity : Activity


{
RecyclerView mRecyclerView;
RecyclerView.LayoutManager mLayoutManager;
PhotoAlbumAdapter mAdapter;
PhotoAlbum mPhotoAlbum;

protected override void OnCreate (Bundle bundle)


{
base.OnCreate (bundle);

// Prepare the data source:


mPhotoAlbum = new PhotoAlbum ();

// Instantiate the adapter and pass in its data source:


mAdapter = new PhotoAlbumAdapter (mPhotoAlbum);

// Set our view from the "main" layout resource:


SetContentView (Resource.Layout.Main);

// Get our RecyclerView layout:


mRecyclerView = FindViewById<RecyclerView> (Resource.Id.recyclerView);

// Plug the adapter into the RecyclerView:


mRecyclerView.SetAdapter (mAdapter);

Este código hace lo siguiente:


1. Crea una instancia PhotoAlbum del origen de datos.
2. Pasa el origen de datos del álbum de fotos al constructor del adaptador PhotoAlbumAdapter , (que se
define más adelante en esta guía). Tenga en cuenta que se recomienda pasar el origen de datos como un
parámetro al constructor del adaptador.
3. Obtiene el RecyclerView del diseño.
4. Conecta el adaptador a la RecyclerView instancia de llamando al RecyclerView SetAdapter método tal y
como se mostró anteriormente.
Administrador de diseño
Cada elemento de RecyclerView se compone de un CardView que contiene una imagen de fotografía y un título
de fotografía (los detalles se describen en la sección de titulares de la vista a continuación). El predefinido
LinearLayoutManager se usa para diseñar cada CardView en una disposición de desplazamiento vertical:

mLayoutManager = new LinearLayoutManager (this);


mRecyclerView.SetLayoutManager (mLayoutManager);

Este código reside en el método de OnCreate la actividad principal. El constructor para el administrador de
diseño requiere un contexto, por MainActivity lo que se this pasa utilizando como se ha mencionado
anteriormente.
En lugar de usar el predefinido LinearLayoutManager , puede conectar un administrador de diseño personalizado
que muestre dos CardView elementos en paralelo, implementando un efecto de animación de activación de
página para recorrer la colección de fotografías. Más adelante en esta guía, verá un ejemplo de cómo modificar
el diseño mediante el intercambio en un administrador de diseño diferente.
Ver titular
Se llama a la clase de titular de vista. Cada PhotoViewHolder instancia contiene referencias a los
PhotoViewHolder
ImageView elementos TextView y de un elemento de fila asociado, que se incluye en CardView un objeto como
diagrama aquí:

PhotoViewHolder deriva de RecyclerView.ViewHolder y contiene propiedades para almacenar las referencias


ImageView ay TextView que se muestran en el diseño anterior. PhotoViewHolder consta de dos propiedades y un
constructor:
public class PhotoViewHolder : RecyclerView.ViewHolder
{
public ImageView Image { get; private set; }
public TextView Caption { get; private set; }

public PhotoViewHolder (View itemView) : base (itemView)


{
// Locate and cache view references:
Image = itemView.FindViewById<ImageView> (Resource.Id.imageView);
Caption = itemView.FindViewById<TextView> (Resource.Id.textView);
}
}

En este ejemplo de código, PhotoViewHolder al constructor se le pasa una referencia a la vista del elemento
CardView primario ( PhotoViewHolder el) que contiene. Tenga en cuenta que siempre reenvía la vista del
elemento primario al constructor base. El PhotoViewHolder constructor llama FindViewById a en la vista de
elemento primario para buscar cada una de sus referencias ImageView de TextView vista secundaria, y
almacenar los Image resultados Caption en las propiedades y, respectivamente. Posteriormente, el adaptador
recupera las referencias de la vista de estas propiedades cuando CardView actualiza las vistas secundarias de este
con nuevos datos.
Para obtener más información RecyclerView.ViewHolder sobre, vea la referencia de la clase RecyclerView.
ViewHolder.
Adaptador
El adaptador carga cada RecyclerView fila con datos de una fotografía determinada. Para una fotografía
determinada en la posición de fila p, por ejemplo, el adaptador busca los datos asociados en la posición p en el
origen de datos y copia estos datos en el elemento de fila en RecyclerView la posición p de la colección. El
adaptador usa el titular de la vista para buscar las referencias ImageView de TextView y en esa posición, por lo
que no tiene FindViewById que llamar repetidamente a esas vistas cuando el usuario se desplaza por la colección
de fotografías y reutiliza las vistas.
En RecyclerViewer, una clase de adaptador se deriva RecyclerView.Adapter de para PhotoAlbumAdapter crear:

public class PhotoAlbumAdapter : RecyclerView.Adapter


{
public PhotoAlbum mPhotoAlbum;

public PhotoAlbumAdapter (PhotoAlbum photoAlbum)


{
mPhotoAlbum = photoAlbum;
}
...
}

El mPhotoAlbum miembro contiene el origen de datos (el álbum de fotos) que se pasa al constructor; el
constructor copia el álbum de fotos en esta variable miembro. Se implementan RecyclerView.Adapter los
siguientes métodos necesarios:
OnCreateViewHolder – Crea una instancia del archivo de diseño del elemento y del titular de la vista.
OnBindViewHolder – Carga los datos en la posición especificada en las vistas cuyas referencias se
almacenan en el titular de la vista especificado.
ItemCount – Devuelve el número de elementos del origen de datos.

El administrador de diseño llama a estos métodos mientras coloca los elementos dentro RecyclerView de. La
implementación de estos métodos se examina en las secciones siguientes.
OnCreateViewHolder
El administrador de diseño OnCreateViewHolder llama a RecyclerView cuando necesita un nuevo titular de la
vista para representar un elemento. OnCreateViewHolder aumenta la vista de elementos del archivo de diseño de
la vista y ajusta la vista en una nueva PhotoViewHolder instancia. El PhotoViewHolder constructor busca y
almacena las referencias a las vistas secundarias en el diseño tal y como se describió anteriormente en el titular
de la vista.
Cada elemento de fila se representa mediante CardView un que contiene ImageView una (para la foto) y
TextView un (para el título). Este diseño reside en el archivo PhotoCardView. axml:

<?xml version="1.0" encoding="utf-8"?>


<FrameLayout xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardElevation="4dp"
card_view:cardUseCompatPadding="true"
card_view:cardCornerRadius="5dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="8dp">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/imageView"
android:scaleType="centerCrop" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#333333"
android:text="Caption"
android:id="@+id/textView"
android:layout_gravity="center_horizontal"
android:layout_marginLeft="4dp" />
</LinearLayout>
</android.support.v7.widget.CardView>
</FrameLayout>

Este diseño representa un elemento de una sola fila RecyclerView en. El OnBindViewHolder método (que se
describe a continuación) copia los datos del origen ImageView de TextView datos en y de este diseño.
OnCreateViewHolder infla este diseño para una determinada ubicación de la foto en el RecyclerView y crea una
instancia de PhotoViewHolder una nueva instancia (que busca y almacena en caché las ImageView referencias
TextView a las vistas secundarias CardView y en el diseño asociado):
public override RecyclerView.ViewHolder
OnCreateViewHolder (ViewGroup parent, int viewType)
{
// Inflate the CardView for the photo:
View itemView = LayoutInflater.From (parent.Context).
Inflate (Resource.Layout.PhotoCardView, parent, false);

// Create a ViewHolder to hold view references inside the CardView:


PhotoViewHolder vh = new PhotoViewHolder (itemView);
return vh;
}

La instancia de marcador de vista vh resultante,, se devuelve al autor de la llamada (el administrador de diseño).
OnBindViewHolder
Cuando el administrador de diseño está listo para mostrar una vista determinada en RecyclerView el área visible
de la pantalla, llama al método OnBindViewHolder del adaptador para rellenar el elemento en la posición de la fila
especificada con el contenido del origen de datos. OnBindViewHolder Obtiene la información de la fotografía para
la posición de la fila especificada (el recurso de imagen de la fotografía y la cadena para el título de la fotografía)
y copia estos datos en las vistas asociadas. Las vistas se encuentran a través de referencias almacenadas en el
objeto de portaherramienta de la vista holder (que se pasa a través del parámetro):

public override void


OnBindViewHolder (RecyclerView.ViewHolder holder, int position)
{
PhotoViewHolder vh = holder as PhotoViewHolder;

// Load the photo image resource from the photo album:


vh.Image.SetImageResource (mPhotoAlbum[position].PhotoID);

// Load the photo caption from the photo album:


vh.Caption.Text = mPhotoAlbum[position].Caption;
}

El objeto de titular de la vista pasada debe convertirse primero en el tipo de contenedor de la vista derivada (en
PhotoViewHolder este caso,) antes de que se use. El adaptador carga el recurso de imagen en la vista a la que hace
referencia la Image propiedad del titular de la vista y copia el texto del título en la vista a la que Caption hace
referencia la propiedad del titular de la vista. Esto enlaza la vista asociada con sus datos.
Observe que OnBindViewHolder es el código que trata directamente la estructura de los datos. En este caso,
OnBindViewHolder entiende cómo asignar la posición RecyclerView del elemento a su elemento de datos
asociado en el origen de datos. En este caso, la asignación es sencilla, ya que la posición puede usarse como un
índice de matriz en el álbum de fotos. sin embargo, los orígenes de datos más complejos pueden requerir código
adicional para establecer este tipo de asignación.
ItemCount
El ItemCount método devuelve el número de elementos de la colección de datos. En la aplicación de visor de
fotos de ejemplo, el recuento de elementos es el número de fotos del álbum de fotos:

public override int ItemCount


{
get { return mPhotoAlbum.NumPhotos; }
}

Para obtener más información RecyclerView.Adapter sobre, vea la referencia de la clase RecyclerView. Adapter.
Reunir todo
La implementación RecyclerView resultante para la aplicación de foto de ejemplo MainActivity consta de
código que crea el origen de datos, el administrador de diseño y el adaptador. MainActivity crea la
mRecyclerView instancia, crea una instancia del origen de datos y el adaptador, y se conecta en el administrador
de diseño y el adaptador:

public class MainActivity : Activity


{
RecyclerView mRecyclerView;
RecyclerView.LayoutManager mLayoutManager;
PhotoAlbumAdapter mAdapter;
PhotoAlbum mPhotoAlbum;

protected override void OnCreate (Bundle bundle)


{
base.OnCreate (bundle);
mPhotoAlbum = new PhotoAlbum();
SetContentView (Resource.Layout.Main);
mRecyclerView = FindViewById<RecyclerView> (Resource.Id.recyclerView);

// Plug in the linear layout manager:


mLayoutManager = new LinearLayoutManager (this);
mRecyclerView.SetLayoutManager (mLayoutManager);

// Plug in my adapter:
mAdapter = new PhotoAlbumAdapter (mPhotoAlbum);
mRecyclerView.SetAdapter (mAdapter);
}
}

PhotoViewHolder busca y almacena en caché las referencias de la vista:

public class PhotoViewHolder : RecyclerView.ViewHolder


{
public ImageView Image { get; private set; }
public TextView Caption { get; private set; }

public PhotoViewHolder (View itemView) : base (itemView)


{
// Locate and cache view references:
Image = itemView.FindViewById<ImageView> (Resource.Id.imageView);
Caption = itemView.FindViewById<TextView> (Resource.Id.textView);
}
}

PhotoAlbumAdapter implementa las tres invalidaciones de método necesarias:


public class PhotoAlbumAdapter : RecyclerView.Adapter
{
public PhotoAlbum mPhotoAlbum;
public PhotoAlbumAdapter (PhotoAlbum photoAlbum)
{
mPhotoAlbum = photoAlbum;
}

public override RecyclerView.ViewHolder


OnCreateViewHolder (ViewGroup parent, int viewType)
{
View itemView = LayoutInflater.From (parent.Context).
Inflate (Resource.Layout.PhotoCardView, parent, false);
PhotoViewHolder vh = new PhotoViewHolder (itemView);
return vh;
}

public override void


OnBindViewHolder (RecyclerView.ViewHolder holder, int position)
{
PhotoViewHolder vh = holder as PhotoViewHolder;
vh.Image.SetImageResource (mPhotoAlbum[position].PhotoID);
vh.Caption.Text = mPhotoAlbum[position].Caption;
}

public override int ItemCount


{
get { return mPhotoAlbum.NumPhotos; }
}
}

Cuando este código se compila y se ejecuta, crea la aplicación básica de visualización fotográfica, tal como se
muestra en las siguientes capturas de pantalla:
Si no se dibujan sombras (como se ha mostrado en la captura de pantalla anterior), edite Properties/archivo
AndroidManifest. XML y agregue el <application> siguiente valor de atributo al elemento:

android:hardwareAccelerated="true"

Esta aplicación básica solo admite la exploración del álbum de fotos. No responde a los eventos táctiles de
elementos ni a los cambios en los datos subyacentes. Esta funcionalidad se agrega en la extensión del ejemplo
RecyclerView.
Cambiar el LayoutManager
Debido a RecyclerView la flexibilidad de, es fácil modificar la aplicación para que use un administrador de diseño
diferente. En el ejemplo siguiente, se modifica para mostrar el álbum de fotos con un diseño de cuadrícula que se
desplaza horizontalmente en lugar de con un diseño lineal vertical. Para ello, la creación de instancias del
administrador de diseño se modifica para GridLayoutManager usar el de la siguiente manera:

mLayoutManager = new GridLayoutManager(this, 2, GridLayoutManager.Horizontal, false);

Este cambio de código reemplaza el LinearLayoutManager vertical con GridLayoutManager un que presenta una
cuadrícula formada por dos filas que se desplazan en dirección horizontal. Al compilar y ejecutar la aplicación de
nuevo, verá que las fotografías se muestran en una cuadrícula y que el desplazamiento es horizontal en lugar de
vertical:
Al cambiar solo una línea de código, es posible modificar la aplicación de visualización de fotografías para que
use un diseño diferente con un comportamiento diferente. Tenga en cuenta que ni el código del adaptador ni el
XML de diseño tuvieron que modificarse para cambiar el estilo de diseño.
En el tema siguiente, extender el ejemplo de RecyclerView, esta aplicación de ejemplo básica se extiende para
controlar eventos de clic de RecyclerView elemento y actualizar cuando cambia el origen de datos subyacente.

Vínculos relacionados
RecyclerViewer (ejemplo)
RecyclerView
Componentes y funcionalidad de RecyclerView
Extender el ejemplo de RecyclerView
RecyclerView
Extender el ejemplo de RecyclerView
16/08/2019 • 11 minutes to read • Edit Online

En realidad, la aplicación básica descrita en un ejemplo de RecyclerView básico no hace mucho – sino que
simplemente se desplaza y muestra una lista fija de elementos de fotografía para facilitar la exploración. En las
aplicaciones reales, los usuarios esperan poder interactuar con la aplicación punteando en los elementos de la
pantalla. Además, el origen de datos subyacente puede cambiar (o ser modificado por la aplicación) y el
contenido de la pantalla debe permanecer coherente con estos cambios. En las secciones siguientes, aprenderá a
controlar eventos de clic de elemento y a actualizar RecyclerView cuando cambie el origen de datos subyacente.
Controlar eventos de clic de elemento
Cuando un usuario toca un elemento en el RecyclerView , se genera un evento de clic de elemento para notificar
a la aplicación de qué elemento se ha tocado. En su lugar, no genera RecyclerView – este evento, la vista del
elemento (que está incluida en el titular de la vista) detecta los toques y notifica que estos tocan como eventos de
clic.
Para ilustrar cómo controlar los eventos de clic de elemento, en los pasos siguientes se explica cómo se modifica
la aplicación básica de visualización de fotografías para informar de qué fotografía ha sido tocada por el usuario.
Cuando se produce un evento de clic de elemento en la aplicación de ejemplo, tiene lugar la siguiente secuencia:
1. La fotografía CardView detecta el evento de clic de elemento y lo notifica al adaptador.
2. El adaptador reenvía el evento (con información de posición del elemento) al controlador de clic de
elemento de la actividad.
3. El controlador de clic de elemento de la actividad responde al evento de clic del elemento.
En primer lugar, se agrega un ItemClick miembro del controlador de PhotoAlbumAdapter eventos denominado a
la definición de clase:

public event EventHandler<int> ItemClick;

A continuación, se agrega un método de controlador de eventos de MainActivity clic de elemento a. Este


controlador muestra brevemente una notificación del sistema que indica qué elemento de fotografía se ha
tocado:

void OnItemClick (object sender, int position)


{
int photoNum = position + 1;
Toast.MakeText(this, "This is photo number " + photoNum, ToastLength.Short).Show();
}

A continuación, se necesita una línea de código para registrar OnItemClick el controlador PhotoAlbumAdapter con.
Un buen lugar para hacerlo es inmediatamente después PhotoAlbumAdapter de que se cree:

mAdapter = new PhotoAlbumAdapter (mPhotoAlbum);


mAdapter.ItemClick += OnItemClick;

En este ejemplo básico, el registro del controlador tiene lugar en el método OnCreate de la actividad principal,
pero una aplicación de producción podría OnResume registrar el controlador en y OnPause anular su registro en –
consulte el ciclo de vida de la actividad para obtener más información informaciones.
PhotoAlbumAdapter llamará ahora OnItemClick a cuando reciba un evento de clic del elemento. El siguiente paso
consiste en crear un controlador en el adaptador que genera este ItemClick evento. El método siguiente,
OnClick , se agrega inmediatamente después del método del ItemCount adaptador:

void OnClick (int position)


{
if (ItemClick != null)
ItemClick (this, position);
}

Este OnClick método es el agente de escucha del adaptador para los eventos de clic de elemento de las vistas de
elementos. Antes de que se pueda registrar este agente de escucha con una vista de elemento (a través del titular
de la PhotoViewHolder vista de la vista de elemento), el constructor debe modificarse para aceptar OnClick este
método como argumento Click adicional y registrarse con el evento de vista de elemento. Este es el constructor
PhotoViewHolder modificado:

public PhotoViewHolder (View itemView, Action<int> listener)


: base (itemView)
{
Image = itemView.FindViewById<ImageView> (Resource.Id.imageView);
Caption = itemView.FindViewById<TextView> (Resource.Id.textView);

itemView.Click += (sender, e) => listener (base.LayoutPosition);


}

El itemView parámetro contiene una referencia CardView al que el usuario ha tocado. Tenga en cuenta que la
clase base del portaherramienta de la vista conoce la posición CardView del diseño del elemento () que
LayoutPosition representa (a través de la propiedad) y esta posición se OnClick pasa al método del adaptador
cuando tiene lugar un evento de clic del elemento. El método del OnCreateViewHolder adaptador se modifica para
pasar el método del OnClick adaptador al constructor del propietario de la vista:

PhotoViewHolder vh = new PhotoViewHolder (itemView, OnClick);

Ahora, al compilar y ejecutar la aplicación de visualización de fotografías de ejemplo, al pulsar una foto en la
pantalla se mostrará una notificación que indica qué fotografía se ha tocado:
En este ejemplo se muestra un solo enfoque para implementar controladores de RecyclerView eventos con. Otro
enfoque que podría usarse aquí es colocar los eventos en el titular de la vista y hacer que el adaptador se suscriba
a estos eventos. Si la aplicación de foto de ejemplo proporciona una funcionalidad de edición de fotografías, se
necesitarían ImageView eventos independientes TextView para y CardView en TextView cada una de ellas: los
EditView toques de iniciarían un cuadro de diálogo que permite al usuario editar el título y los toques ImageView
del iniciarán una herramienta de retoque fotográfico que permite al usuario recortar o girar la foto. En función de
las necesidades de la aplicación, debe diseñar el mejor método para controlar y responder a los eventos de toque.
Para demostrar cómo RecyclerView se puede actualizar cuando se cambia el conjunto de datos, se puede
modificar la aplicación de visualización de fotografías de ejemplo para elegir aleatoriamente una foto en el origen
de datos y cambiarla con la primera foto. En primer lugar, se agrega un botón de selección aleatoria al diseño
principal. axml de la aplicación de fotos de ejemplo:

<?xml version="1.0" encoding="utf-8"?>


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Button
android:id="@+id/randPickButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Random Pick" />
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:scrollbars="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>

A continuación, se agrega el código al final del OnCreate método de la actividad principal para buscar el
Random Pick botón en el diseño y adjuntar un controlador:
Button randomPickBtn = FindViewById<Button>(Resource.Id.randPickButton);

randomPickBtn.Click += delegate
{
if (mPhotoAlbum != null)
{
// Randomly swap a photo with the first photo:
int idx = mPhotoAlbum.RandomSwap();
}
};

Este controlador llama al método del álbum RandomSwap de fotos cuando se puntea el botón de selección
aleatoria . El RandomSwap método intercambia una fotografía aleatoriamente con la primera foto del origen de
datos y, a continuación, devuelve el índice de la fotografía de intercambio aleatorio. Al compilar y ejecutar la
aplicación de ejemplo con este código, al pulsar el botón de selección aleatoria no RecyclerView se produce un
cambio de pantalla, ya que no es consciente del cambio en el origen de datos.
Para mantener RecyclerView actualizados después de que se cambie el origen de datos, el controlador de clics de
selección aleatoria debe NotifyItemChanged modificarse para llamar al método del adaptador para cada
elemento de la colección que ha cambiado (en este caso, dos elementos han cambiado: la primera foto y la foto
intercambiada). Esto hace RecyclerView que actualice su pantalla para que sea coherente con el nuevo estado del
origen de datos:

Button randomPickBtn = FindViewById<Button>(Resource.Id.randPickButton);

randomPickBtn.Click += delegate
{
if (mPhotoAlbum != null)
{
int idx = mPhotoAlbum.RandomSwap();

// First photo has changed:


mAdapter.NotifyItemChanged(0);

// Swapped photo has changed:


mAdapter.NotifyItemChanged(idx);
}
};

Ahora, cuando se puntee en el botón de RecyclerView selección aleatoria , actualiza la pantalla para mostrar
que una foto más abajo en la colección se ha intercambiado con la primera foto de la colección:
Por supuesto, NotifyDataSetChanged se podría haber llamado a en lugar de realizar las dos llamadas
NotifyItemChanged a, pero hacerlo obligaría RecyclerView a actualizar toda la colección, aunque solo hubieran
cambiado dos elementos de la colección. Llamar NotifyItemChanged a es significativamente más eficaz que
NotifyDataSetChanged llamar a.

Vínculos relacionados
RecyclerViewer (ejemplo)
RecyclerView
Componentes y funcionalidad de RecyclerView
Ejemplo de RecyclerView básico
RecyclerView
ListView de Xamarin. Android
16/08/2019 • 11 minutes to read • Edit Online

ListView es un componente importante de la interfaz de usuario de las aplicaciones de Android; se usa en todas
partes desde listas cortas de opciones de menú hasta largas listas de contactos o favoritos de Internet.
Proporciona una manera sencilla de presentar una lista de desplazamiento de filas a las que se puede dar
formato con un estilo integrado o personalizarse en gran medida.

Información general
Las vistas de lista y los adaptadores se incluyen en los bloques de creación más fundamentales de las
aplicaciones de Android. La ListView clase proporciona una manera flexible de presentar los datos, tanto si se
trata de un menú corto como una lista de desplazamiento largo. Proporciona características de facilidad de uso,
como el desplazamiento rápido, los índices y una o varias selecciones para ayudarle a crear interfaces de
usuario fáciles de utilizar para las aplicaciones. Una instancia ListView necesita un adaptador para llenarlo con
los datos que contienen las vistas de la fila.
En esta guía se explica cómo ListView implementar y las Adapter distintas clases de Xamarin. Android.
También se muestra cómo personalizar la apariencia de un ListView y se describe la importancia del
reutilización de las filas para reducir el consumo de memoria. También se explica cómo afecta ListView y
Adapter utiliza el ciclo de vida de la actividad. Si está trabajando en ListView aplicaciones multiplataforma con
Xamarin. iOS, el control es estructuralmente similar a iOS UITableView (y UITableViewSource Android Adapter
es similar a).
En primer lugar, un tutorial breve ListView presenta el con un ejemplo de código básico. A continuación, se
proporcionan vínculos a temas más avanzados que le ayudarán a usar ListView en aplicaciones reales.

NOTE
El RecyclerView widget es una versión más avanzada y flexible de ListView . Dado RecyclerView que está diseñado
para ser el sucesor ListView de ( GridView y) ListView , se recomienda usar RecyclerView en lugar de para el
nuevo desarrollo de aplicaciones. Para obtener más información, vea RecyclerView.

Tutorial de ListView
ListView es un ViewGroup que crea una lista de elementos desplazables. Los elementos de la lista se insertan
automáticamente en la IListAdapter lista mediante.
En este tutorial, creará una lista desplazable de nombres de país que se leen de una matriz de cadenas. Cuando
se selecciona un elemento de lista, el mensaje del sistema muestra la posición del elemento en la lista.
Inicie un nuevo proyecto denominado HelloListView.
Cree un archivo XML con el nombre list_item. XML y guárdelo dentro de la carpeta recursos/diseño/ .
Inserte lo siguiente:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dp"
android:textSize="16sp">
</TextView>

Este archivo define el diseño de cada elemento que se colocará en ListView el.
Abra MainActivity.cs y modifique la clase para extender ListActivity (en lugar de Activity ):

public class MainActivity : ListActivity


{

Inserte el código siguiente para el OnCreate() método):

protected override void OnCreate (Bundle bundle)


{
base.OnCreate (bundle);

ListAdapter = new ArrayAdapter<string> (this, Resource.Layout.list_item, countries);

ListView.TextFilterEnabled = true;

ListView.ItemClick += delegate (object sender, AdapterView.ItemClickEventArgs args)


{
Toast.MakeText(Application, ((TextView)args.View).Text, ToastLength.Short).Show();
};
}

Tenga en cuenta que esto no carga un archivo de diseño para la actividad (lo que suele SetContentView(int)
hacer con)). En su lugar, al establecer ListAdapter la propiedad agrega automáticamente un ListView para
rellenar toda la pantalla ListActivity de. Este método toma un ArrayAdapter<T> , que administra la matriz de
elementos de lista que se colocará ListView en. El ArrayAdapter<T> el constructor toma la Context aplicación, la
descripción del diseño de cada elemento de la lista (creada en el paso anterior T[] ) y un o Java.Util.IList<T>
matriz de objetos que se van a insertar en el ListView (se define a continuación).
El TextFilterEnabled la propiedad activa el ListView filtrado de texto para, de modo que cuando el usuario
comience a escribir, la lista se filtre.
El ItemClick el evento se puede utilizar para suscribir Controladores para clics. Cuando un elemento de la
ListView se hace clic en, se llama al controlador y a un Toast se muestra el mensaje con el texto del elemento
en el que se hizo clic.
Puede usar los diseños de elementos de lista proporcionados por la plataforma en lugar de definir su propio
archivo ListAdapter de diseño para. Por ejemplo, pruebe a Android.Resource.Layout.SimpleListItem1 usar en
lugar Resource.Layout.list_item de.
Agregue la siguiente using instrucción:

using System;

A continuación, agregue la siguiente matriz de cadenas como un MainActivity miembro de:


static readonly string[] countries = new String[] {
"Afghanistan","Albania","Algeria","American Samoa","Andorra",
"Angola","Anguilla","Antarctica","Antigua and Barbuda","Argentina",
"Armenia","Aruba","Australia","Austria","Azerbaijan",
"Bahrain","Bangladesh","Barbados","Belarus","Belgium",
"Belize","Benin","Bermuda","Bhutan","Bolivia",
"Bosnia and Herzegovina","Botswana","Bouvet Island","Brazil","British Indian Ocean Territory",
"British Virgin Islands","Brunei","Bulgaria","Burkina Faso","Burundi",
"Cote d'Ivoire","Cambodia","Cameroon","Canada","Cape Verde",
"Cayman Islands","Central African Republic","Chad","Chile","China",
"Christmas Island","Cocos (Keeling) Islands","Colombia","Comoros","Congo",
"Cook Islands","Costa Rica","Croatia","Cuba","Cyprus","Czech Republic",
"Democratic Republic of the Congo","Denmark","Djibouti","Dominica","Dominican Republic",
"East Timor","Ecuador","Egypt","El Salvador","Equatorial Guinea","Eritrea",
"Estonia","Ethiopia","Faeroe Islands","Falkland Islands","Fiji","Finland",
"Former Yugoslav Republic of Macedonia","France","French Guiana","French Polynesia",
"French Southern Territories","Gabon","Georgia","Germany","Ghana","Gibraltar",
"Greece","Greenland","Grenada","Guadeloupe","Guam","Guatemala","Guinea","Guinea-Bissau",
"Guyana","Haiti","Heard Island and McDonald Islands","Honduras","Hong Kong","Hungary",
"Iceland","India","Indonesia","Iran","Iraq","Ireland","Israel","Italy","Jamaica",
"Japan","Jordan","Kazakhstan","Kenya","Kiribati","Kuwait","Kyrgyzstan","Laos",
"Latvia","Lebanon","Lesotho","Liberia","Libya","Liechtenstein","Lithuania","Luxembourg",
"Macau","Madagascar","Malawi","Malaysia","Maldives","Mali","Malta","Marshall Islands",
"Martinique","Mauritania","Mauritius","Mayotte","Mexico","Micronesia","Moldova",
"Monaco","Mongolia","Montserrat","Morocco","Mozambique","Myanmar","Namibia",
"Nauru","Nepal","Netherlands","Netherlands Antilles","New Caledonia","New Zealand",
"Nicaragua","Niger","Nigeria","Niue","Norfolk Island","North Korea","Northern Marianas",
"Norway","Oman","Pakistan","Palau","Panama","Papua New Guinea","Paraguay","Peru",
"Philippines","Pitcairn Islands","Poland","Portugal","Puerto Rico","Qatar",
"Reunion","Romania","Russia","Rwanda","Sqo Tome and Principe","Saint Helena",
"Saint Kitts and Nevis","Saint Lucia","Saint Pierre and Miquelon",
"Saint Vincent and the Grenadines","Samoa","San Marino","Saudi Arabia","Senegal",
"Seychelles","Sierra Leone","Singapore","Slovakia","Slovenia","Solomon Islands",
"Somalia","South Africa","South Georgia and the South Sandwich Islands","South Korea",
"Spain","Sri Lanka","Sudan","Suriname","Svalbard and Jan Mayen","Swaziland","Sweden",
"Switzerland","Syria","Taiwan","Tajikistan","Tanzania","Thailand","The Bahamas",
"The Gambia","Togo","Tokelau","Tonga","Trinidad and Tobago","Tunisia","Turkey",
"Turkmenistan","Turks and Caicos Islands","Tuvalu","Virgin Islands","Uganda",
"Ukraine","United Arab Emirates","United Kingdom",
"United States","United States Minor Outlying Islands","Uruguay","Uzbekistan",
"Vanuatu","Vatican City","Venezuela","Vietnam","Wallis and Futuna","Western Sahara",
"Yemen","Yugoslavia","Zambia","Zimbabwe"
};

Esta es la matriz de cadenas que se colocará en ListView el.


Ejecute la aplicación. Puede desplazarse por la lista o escribir para filtrarla y, a continuación, hacer clic en un
elemento para ver un mensaje. Verá algo parecido a esto:
Tenga en cuenta que el uso de una matriz de cadenas codificadas de forma rígida no es el mejor procedimiento
de diseño. Una se usa en este tutorial para simplificar, a fin de demostrar el ListView widget. El procedimiento
recomendado consiste en hacer referencia a una matriz de cadenas definida por un recurso externo, como
string-array con un recurso en el archivo de recursos/valores/Strings. XML del proyecto. Por ejemplo:

<?xml version="1.0" encoding="utf-8"?>


<resources>
<string name="app_name">HelloListView</string>
<string-array name="countries_array">
<item>Bahrain</item>
<item>Bangladesh</item>
<item>Barbados</item>
<item>Belarus</item>
<item>Belgium</item>
<item>Belize</item>
<item>Benin</item>
</string-array>
</resources>

Para usar estas cadenas de recursos para ArrayAdapter , reemplace el original ListAdapter línea con lo
siguiente:

string[] countries = Resources.GetStringArray (Resource.Array.countries_array);


ListAdapter = new ArrayAdapter<string> (this, Resource.Layout.list_item, countries);

Ejecute la aplicación. Verá algo parecido a esto:


Continuar con ListView
Los temas restantes (vinculados a continuación) tienen una visión completa del trabajo ListView con la clase y
los distintos tipos de tipos de adaptador que puede usar con él. La estructura es como se detalla a continuación:
Apariencia visual – Partes ListView del control y cómo funcionan.
Clases de Información general de las clases utilizadas para mostrar ListView un. –
Mostrar datos en un control ListView Cómo mostrar una lista simple de datos, cómo implementar
ListView's características de facilidad de uso, cómo usar diferentes diseños de fila integrados y cómo
los adaptadores ahorran memoria mediante la reutilización de las vistas de fila. –
Apariencia personalizada Cambiar el estilo ListView de con diseños personalizados, fuentes y
colores. –
Usar SQLite Cómo Mostrar datos de una base de datos SQLite con CursorAdapter un. –
Ciclo de vida de actividad Consideraciones de diseño al ListView implementar actividades, incluido el
lugar del ciclo de vida, debe rellenar los datos y cuándo liberar recursos. –
La discusión (dividida en seis partes) comienza con una visión general ListView de la propia clase antes de
introducir ejemplos más complejos de cómo usarlas.
Elementos y funcionalidad de ListView
Rellenar un control ListView con datos
Personalización de la apariencia de ListView
Uso de CursorAdapters
Uso de ContentProvider
ListView y ciclo de vida de actividad

Resumen
Este conjunto de temas se ListView ha introducido y proporcionado algunos ejemplos de cómo usar las
características integradas ListActivity de. Se han explicado las implementaciones personalizadas de ListView
que permitían diseños multicolor y el uso de una base de datos de SQLite, y se toca brevemente en la relevancia
del ciclo de vida de la actividad en la ListView implementación.

Vínculos relacionados
AccessoryViews (ejemplo)
BasicTableAndroid (ejemplo)
BasicTableAdapter (ejemplo)
BuiltInViews (ejemplo)
CustomRowView (ejemplo)
FastScroll (ejemplo)
SectionIndex (ejemplo)
SimpleCursorTableAdapter (ejemplo)
CursorTableAdapter (ejemplo)
Tutorial del ciclo de vida de actividad
Trabajar con tablas y celdas (en Xamarin. iOS )
Referencia de clases de ListView
Referencia de la clase ListActivity
Referencia de la clase BaseAdapter
Referencia de la clase ArrayAdapter
CursorAdapter (referencia de clase)
Componentes y funcionalidad de ListView de
Xamarin. Android
27/07/2019 • 4 minutes to read • Edit Online

Un ListView consta de las siguientes partes:


Filas de – Representación visible de los datos de la lista.
Adaptador de – Una clase no visual que enlaza el origen de datos a la vista de lista.
Desplazamiento rápido – Identificador que permite al usuario desplazarse por la longitud de la lista.
Índice de sección – Un elemento de la interfaz de usuario que flota sobre las filas de desplazamiento para
indicar en qué lugar de la lista se encuentran las filas actuales.
Estas capturas de pantallas ListView usan un control básico para mostrar cómo se representan el desplazamiento
rápido y el índice de sección:

Los elementos que componen ListView un se describen con más detalle a continuación:

Filas
Cada fila tiene su propia View . La vista puede ser una de las vistas integradas definidas en Android.Resources o
una vista personalizada. Cada fila puede usar el mismo diseño de vista o puede ser diferente. Hay ejemplos en este
documento sobre el uso de diseños integrados y otros que explican cómo definir diseños personalizados.

Adaptador
El ListView control View requiere que proporcione el formato para cada fila. Adapter Android tiene adaptadores
y vistas integrados que se pueden usar, o bien se pueden crear clases personalizadas.
Desplazamiento rápido
Cuando un ListView contiene muchas filas de datos, se puede habilitar el desplazamiento rápido para ayudar al
usuario a desplazarse a cualquier parte de la lista. La barra de desplazamiento de desplazamiento rápido se puede
habilitar opcionalmente (y personalizarse en el nivel de API 11 y versiones posteriores).

Índice de sección
Al desplazarse por las listas largas, el índice de sección opcional proporciona al usuario información sobre la parte
de la lista que está viendo actualmente. Solo es adecuado en listas largas, normalmente junto con desplazamiento
rápido.

Información general sobre clases


A continuación se muestran las clases ListViews principales que se usan para mostrar:

A continuación se describe el propósito de cada clase:


Vista de – elemento de la interfaz de usuario que muestra una colección desplazable de filas. En los
teléfonos, normalmente usa toda la pantalla (en cuyo caso se puede ListActivity usar la clase) o podría
formar parte de un diseño mayor en teléfonos o dispositivos de tableta.
Vista de una vista en Android puede ser cualquier elemento de la interfaz de usuario, pero en el ListView
contexto de, View requiere que se proporcione un para cada fila. –
BaseAdapter Clase base para las implementaciones de adaptador para ListView enlazar un a un origen de
datos. –
ArrayAdapter Clase de adaptador integrado que enlaza una matriz de cadenas a un ListView para su
presentación. – El genérico ArrayAdapter<T> hace lo mismo para otros tipos.
CursorAdapter – Use opara SimpleCursorAdapter Mostrar datos basados en una consulta de SQLite.
CursorAdapter

Este documento contiene ejemplos sencillos que usan ArrayAdapter , así como ejemplos más complejos que
requieren implementaciones personalizadas de BaseAdapter o CursorAdapter .
Rellenar un control ListView de Xamarin. Android
con datos
16/08/2019 • 11 minutes to read • Edit Online

Para agregar filas a un ListView , debe agregarlo al diseño e implementar un IListAdapter con métodos que las
ListView llamadas a se rellenan a sí mismos. Android incluye las clases ListActivity y ArrayAdapter integradas
que puede usar sin definir ningún código o XML de diseño personalizado. La ListActivity clase crea
automáticamente un ListView y expone una ListAdapter propiedad para proporcionar las vistas de fila que se
van a mostrar a través de un adaptador.
Los adaptadores integrados toman un identificador de recurso de vista como parámetro que se utiliza para cada
fila. Puede usar recursos integrados como los de Android.Resource.Layout para que no tenga que escribir los
suyos propios.

Usar la cadena ListActivity<y ArrayAdapter>


En el ejemplo BasicTable/HomeScreen. CS se muestra cómo usar estas clases para mostrar en solo unas pocas
líneas de código: ListView

[Activity(Label = "BasicTable", MainLauncher = true, Icon = "@drawable/icon")]


public class HomeScreen : ListActivity {
string[] items;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
items = new string[] { "Vegetables","Fruits","Flower Buds","Legumes","Bulbs","Tubers" };
ListAdapter = new ArrayAdapter<String>(this, Android.Resource.Layout.SimpleListItem1, items);
}
protected override void OnListItemClick(ListView l, View v, int position, long id)
}

Controlar los clics de fila


ListView Normalmente, también permitirá al usuario tocar una fila para realizar alguna acción (como reproducir
una canción, llamar a un contacto o Mostrar otra pantalla). Para responder a los toques de los usuarios, debe
haber un método más ListActivity implementado de la – OnListItemClick – siguiente manera:
protected override void OnListItemClick(ListView l, View v, int position, long id)
{
var t = items[position];
Android.Widget.Toast.MakeText(this, t, Android.Widget.ToastLength.Short).Show();
}

Ahora el usuario puede tocar una fila y aparecerá Toast una alerta:
Implementar un ListAdapter
ArrayAdapter<string> es excelente debido a su simplicidad, pero es extremadamente limitado. Sin embargo, a
menudo se tiene una colección de entidades de negocio, en lugar de solo las cadenas que desea enlazar. Por
ejemplo, si los datos constan de una colección de clases Employee, es posible que desee que la lista muestre los
nombres de cada empleado. Para personalizar el comportamiento de un ListView control para controlar qué
datos se muestran, debe implementar una subclase BaseAdapter de invalidar los cuatro elementos siguientes:
Recuento – Para indicar al control cuántas filas hay en los datos.
GetView ( – Para devolver una vista para cada fila, rellenado con datos. Este método tiene un parámetro
para ListView que se pase en una fila existente sin usar para volver a usar.
GetItemId – Devuelve un identificador de fila (normalmente, el número de fila, aunque puede ser
cualquier valor largo que desee).
Este indexador – [int] para devolver los datos asociados a un número de fila determinado.
En el código de ejemplo de BasicTableAdapter/HomeScreenAdapter. CS se muestra cómo BaseAdapter
subclase:

public class HomeScreenAdapter : BaseAdapter<string> {


string[] items;
Activity context;
public HomeScreenAdapter(Activity context, string[] items) : base() {
this.context = context;
this.items = items;
}
public override long GetItemId(int position)
{
return position;
}
public override string this[int position] {
get { return items[position]; }
}
public override int Count {
get { return items.Length; }
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
View view = convertView; // re-use an existing view, if one is available
if (view == null) // otherwise create a new one
view = context.LayoutInflater.Inflate(Android.Resource.Layout.SimpleListItem1, null);
view.FindViewById<TextView>(Android.Resource.Id.Text1).Text = items[position];
return view;
}
}

Usar un adaptador personalizado


El uso del adaptador personalizado es similar al integrado ArrayAdapter , pasando un context y el string[] de
los valores que se van a mostrar:

ListAdapter = new HomeScreenAdapter(this, items);

Dado que en este ejemplo se usa el mismo SimpleListItem1 diseño de fila (), la aplicación resultante tendrá el
mismo aspecto que el ejemplo anterior.
Reutilización de la vista de filas
En este ejemplo solo hay seis elementos. Dado que la pantalla puede caber en ocho, no es necesario volver a usar
ninguna fila. Sin embargo, al mostrar cientos o miles de filas, sería un desperdicio de memoria para crear cientos o
miles de View objetos cuando solo ocho caben en la pantalla al mismo tiempo. Para evitar esta situación, cuando
una fila desaparece de la pantalla, su vista se coloca en una cola para su reutilización. A medida que el usuario se
desplaza ListView , GetView las llamadas para solicitar nuevas vistas – para mostrar si están disponibles pasa
una vista no utilizada convertView en el parámetro. Si este valor es null, el código debe crear una nueva instancia
de vista; de lo contrario, puede volver a establecer las propiedades de ese objeto y volver a utilizarlo.
El GetView método debe seguir este patrón para volver a usar las vistas de fila:
public override View GetView(int position, View convertView, ViewGroup parent)
{
View view = convertView; // re-use an existing view, if one is supplied
if (view == null) // otherwise create a new one
view = context.LayoutInflater.Inflate(Android.Resource.Layout.SimpleListItem1, null);
// set view properties to reflect data for the given row
view.FindViewById<TextView>(Android.Resource.Id.Text1).Text = items[position];
// return the view, populated with data, for display
return view;
}

Las implementaciones de adaptador personalizado siempre deben volver a convertView usar el objeto antes de
crear nuevas vistas para asegurarse de que no se queden sin memoria al mostrar listas largas.
CursorAdapter Algunas implementaciones de adaptador (como) no tienen un GetView método, sino que requieren
dos métodos NewView diferentes y BindView que aplican la reutilización de filas al separar las responsabilidades
GetView de en dos modalidades. Hay un CursorAdapter ejemplo más adelante en el documento.

Habilitar el desplazamiento rápido


El desplazamiento rápido ayuda al usuario a desplazarse por las listas largas proporcionando un "controlador"
adicional que actúa como una barra de desplazamiento para tener acceso directamente a una parte de la lista. En
esta captura de pantalla se muestra el controlador de desplazamiento rápido:
Hacer que el controlador de desplazamiento rápido aparezca es tan sencillo como establecer la FastScrollEnabled
propiedad en true :

ListView.FastScrollEnabled = true;

Agregar un índice de sección


Un índice de sección proporciona información adicional a los usuarios cuando se desplaza rápidamente a través
de una larga – lista que muestra la "sección" a la que se han desplazado. Para que el índice de la sección aparezca,
la subclase del adaptador ISectionIndexer debe implementar la interfaz para proporcionar el texto del índice en
función de las filas que se muestran:
Para implementar ISectionIndexer , debe agregar tres métodos a un adaptador:
GetSections – Proporciona la lista completa de títulos de índice de la sección que se pueden mostrar. Este
método requiere una matriz de objetos de Java, por lo que el código Java.Lang.Object[] debe crear un
objeto a partir de una colección .net. En nuestro ejemplo, devuelve una lista de los caracteres iniciales de la
lista como Java.Lang.String .
GetPositionForSection – Devuelve la primera posición de fila de un índice de sección determinado.
GetSectionForPosition – Devuelve el índice de la sección que se va a mostrar para una fila determinada.
El archivo SectionIndex/HomeScreenAdapter.cs de ejemplo implementa esos métodos y código adicional en el
constructor. El constructor crea el índice de la sección recorriendo en bucle todas las filas y extrayendo el primer
carácter del título (los elementos ya deben estar ordenados para que funcione).
alphaIndex = new Dictionary<string, int>();
for (int i = 0; i < items.Length; i++) { // loop through items
var key = items[i][0].ToString();
if (!alphaIndex.ContainsKey(key))
alphaIndex.Add(key, i); // add each 'new' letter to the index
}
sections = new string[alphaIndex.Keys.Count];
alphaIndex.Keys.CopyTo(sections, 0); // convert letters list to string[]

// Interface requires a Java.Lang.Object[], so we create one here


sectionsObjects = new Java.Lang.Object[sections.Length];
for (int i = 0; i < sections.Length; i++) {
sectionsObjects[i] = new Java.Lang.String(sections[i]);
}

Con las estructuras de datos creadas, ISectionIndexer los métodos son muy sencillos:

public Java.Lang.Object[] GetSections()


{
return sectionsObjects;
}
public int GetPositionForSection(int section)
{
return alphaIndexer[sections[section]];
}
public int GetSectionForPosition(int position)
{ // this method isn't called in this example, but code is provided for completeness
int prevSection = 0;
for (int i = 0; i < sections.Length; i++)
{
if (GetPositionForSection(i) > position)
{
break;
}
prevSection = i;
}
return prevSection;
}

Los títulos de índice de la sección no necesitan asignar 1:1 a las secciones reales. Este es el motivo
GetPositionForSection por el cual existe el método. GetPositionForSection ofrece la oportunidad de asignar los
índices que se encuentran en la lista de índices a las secciones que se encuentran en la vista de lista. Por ejemplo,
puede tener una "z" en el índice, pero es posible que no tenga una sección de tabla para cada letra, por lo que en
lugar de la asignación "z" a 26, puede asignarse a 25 o 24, o al índice de sección "z" que debe asignarse.

Vínculos relacionados
BasicTableAndroid (ejemplo)
BasicTableAdapter (ejemplo)
FastScroll (ejemplo)
Personalización de la apariencia de un control
ListView con Xamarin. Android
16/08/2019 • 18 minutes to read • Edit Online

La apariencia de un control ListView viene determinada por el diseño de las filas que se muestran. Para cambiar la
apariencia de un ListView , utilice un diseño de fila diferente.

Vistas de fila integradas


Hay doce vistas integradas a las que se puede hacer referencia mediante Android. resource. layout:
TestListItem – Una sola línea de texto con un formato mínimo.
SimpleListItem1 – Una sola línea de texto.
SimpleListItem2 – Dos líneas de texto.
SimpleSelectableListItem – Una sola línea de texto que admite la selección de uno o varios elementos
(agregado en el nivel de API 11).
SimpleListItemActivated1 – Similar a SimpleListItem1, pero el color de fondo indica cuándo se
selecciona una fila (agregada en el nivel de API 11).
SimpleListItemActivated2 – Similar a SimpleListItem2, pero el color de fondo indica cuándo se
selecciona una fila (agregada en el nivel de API 11).
SimpleListItemChecked – Muestra las marcas de verificación para indicar la selección.
SimpleListItemMultipleChoice – Muestra las casillas para indicar la selección de varias opciones.
SimpleListItemSingleChoice – Muestra los botones de radio para indicar la selección mutuamente
excluyente.
TwoLineListItem – Dos líneas de texto.
ActivityListItem – Una sola línea de texto con una imagen.
SimpleExpandableListItem – Agrupa las filas por categorías y cada grupo se puede expandir o contraer.
Cada vista de fila integrada tiene un estilo integrado asociado. Estas capturas de pantallas muestran cómo aparece
cada vista:
El archivo de ejemplo BuiltInViews/HomeScreenAdapter. CS (en la solución BuiltInViews ) contiene el código
para generar las pantallas de elementos de lista no expansibles. La vista se establece en el GetView método de la
siguiente manera:

view = context.LayoutInflater.Inflate(Android.Resource.Layout.SimpleListItem1, null);

A continuación, se pueden establecer las propiedades de la vista haciendo referencia a los Text1 identificadores
Icon Text2 de Android.Resource.Id control estándar y en (no establezca las propiedades que la vista no contiene
o se producirá una excepción):
view.FindViewById<TextView>(Android.Resource.Id.Text1).Text = item.Heading;
view.FindViewById<TextView>(Android.Resource.Id.Text2).Text = item.SubHeading;
view.FindViewById<ImageView>(Android.Resource.Id.Icon).SetImageResource(item.ImageResourceId); // only use
with ActivityListItem

El archivo de ejemplo BuiltInExpandableViews/ExpandableScreenAdapter. CS (en la solución BuiltInViews


) contiene el código para generar la pantalla SimpleExpandableListItem. La vista de grupo se establece en
GetGroupView el método de la siguiente manera:

view = context.LayoutInflater.Inflate(Android.Resource.Layout.SimpleExpandableListItem1, null);

La vista secundaria se establece en el GetChildView método de la siguiente manera:

view = context.LayoutInflater.Inflate(Android.Resource.Layout.SimpleExpandableListItem2, null);

Las propiedades de la vista de grupo y la vista secundaria se pueden establecer haciendo referencia a los Text1
identificadores estándar y Text2 de control, tal y como se muestra anteriormente. La captura de pantalla
SimpleExpandableListItem (mostrada anteriormente) proporciona un ejemplo de una vista de grupo de una línea
(SimpleExpandableListItem1) y una vista secundaria de dos líneas (SimpleExpandableListItem2). Como alternativa,
se puede configurar la vista de grupo para dos líneas (SimpleExpandableListItem2) y la vista secundaria se puede
configurar para una línea (SimpleExpandableListItem1), o ambas vistas de grupo y secundarias pueden tener el
mismo número de líneas.

Accesorios
Las filas pueden tener accesorios agregados a la derecha de la vista para indicar el estado de la selección:
SimpleListItemChecked – Crea una lista de selección única con una comprobación como indicador.
SimpleListItemSingleChoice – Crea listas de tipo botón de radio donde solo se puede elegir una opción.
SimpleListItemMultipleChoice – Crea listas de tipo de casilla donde se pueden elegir varias opciones.
Los accesorios anteriores se muestran en las pantallas siguientes, en su orden respectivo:

Para mostrar uno de estos accesorios, pase el identificador de recurso de diseño necesario al adaptador y, a
continuación, establezca manualmente el estado de selección para las filas necesarias. En esta línea de código se
muestra cómo crear y asignar Adapter una mediante uno de estos diseños:

ListAdapter = new ArrayAdapter<String>(this, Android.Resource.Layout.SimpleListItemChecked, items);

El ListView mismo es compatible con los distintos modos de selección, independientemente del accesorio que se
muestre. Para evitar confusiones, Single use el modo SingleChoice de selección con Checked accesorios
Multiple y el modo MultipleChoice o con el estilo. El modo ChoiceMode ListView de selección se controla
mediante la propiedad de.
Control de nivel de API
Las versiones anteriores de Xamarin. Android implementaban las enumeraciones como propiedades de entero. La
versión más reciente ha introducido los tipos de enumeración de .NET adecuados, lo que facilita la detección de las
opciones posibles.
En función del nivel de API de destino, ChoiceMode es un entero o una enumeración. El archivo de ejemplo
AccessoryViews/HomeScreen. CS tiene un bloque comentado si desea tener como destino la API de
Gingerbread:

// For targeting Gingerbread the ChoiceMode is an int, otherwise it is an


// enumeration.

lv.ChoiceMode = Android.Widget.ChoiceMode.Single; // 1
//lv.ChoiceMode = Android.Widget.ChoiceMode.Multiple; // 2
//lv.ChoiceMode = Android.Widget.ChoiceMode.None; // 0

// Use this block if targeting Gingerbread or lower


/*
lv.ChoiceMode = 1; // Single
//lv.ChoiceMode = 0; // none
//lv.ChoiceMode = 2; // Multiple
//lv.ChoiceMode = 3; // MultipleModal
*/

Seleccionar elementos mediante programación


La configuración manual de los elementos seleccionados se realiza con el método SetItemChecked (se puede
llamar varias veces para la selección múltiple):

// Set the initially checked row ("Fruits")


lv.SetItemChecked(1, true);

El código también debe detectar las selecciones únicas de manera diferente de las selecciones múltiples. Para
determinar qué fila se ha seleccionado en Single el modo, CheckedItemPosition use la propiedad de entero:

FindViewById<ListView>(Android.Resource.Id.List).CheckedItemPosition

Para determinar qué filas se han seleccionado en Multiple modo, debe recorrer el. CheckedItemPositions
SparseBooleanArray Una matriz dispersa es como un diccionario que solo contiene entradas en las que se ha
cambiado el valor, por lo que debe atravesar toda la matriz true buscando valores para saber lo que se ha
seleccionado en la lista, tal y como se muestra en el siguiente fragmento de código:
var sparseArray = FindViewById<ListView>(Android.Resource.Id.List).CheckedItemPositions;
for (var i = 0; i < sparseArray.Size(); i++ )
{
Console.Write(sparseArray.KeyAt(i) + "=" + sparseArray.ValueAt(i) + ",");
}
Console.WriteLine();

Crear diseños de fila personalizados


Las cuatro vistas de filas integradas son muy sencillas. Para mostrar diseños más complejos (como una lista de
correos electrónicos, tweets o información de contacto), se necesita una vista personalizada. Las vistas
personalizadas se declaran generalmente como archivos AXML en el directorio de recursos/diseño y, a
continuación, se cargan con su identificador de recurso mediante un adaptador personalizado. La vista puede
contener cualquier número de clases de presentación (como TextViews, ImageViews y otros controles) con colores
personalizados, fuentes y diseño.
Este ejemplo difiere de los ejemplos anteriores de varias maneras:
Hereda de, Activity no ListActivity de. Puede personalizar las filas de cualquier ListView , pero
también se pueden incluir otros controles en un Activity diseño (por ejemplo, un encabezado, botones u
otros elementos de la interfaz de usuario). En este ejemplo se agrega un encabezado ListView encima de
para mostrar.
Requiere un archivo de diseño de AXML para la pantalla. en los ejemplos ListActivity anteriores, no
requiere un archivo de diseño. Este AXML contiene una ListView declaración de control.
Requiere un archivo de diseño AXML para representar cada fila. Este archivo AXML contiene los controles
de texto e imagen con la configuración personalizada de fuente y color.
Usa un archivo XML de selector personalizado opcional para establecer la apariencia de la fila cuando está
seleccionada.
La Adapter implementación de devuelve un diseño personalizado de GetView la invalidación.
ItemClick se debe declarar de forma diferente (se adjunta ListView.ItemClick un controlador de eventos
en lugar de un reemplazo OnListItemClick en ListActivity ).
Estos cambios se detallan a continuación, empezando por crear la vista de la actividad y la vista de fila
personalizada y, a continuación, abarcando las modificaciones en el adaptador y la actividad para representarlas.
Agregar un control ListView a un diseño de actividad
Dado HomeScreen que ya no se hereda ListActivity de, no tiene una vista predeterminada, por lo que se debe
crear un archivo de diseño AXML para la vista de HomeScreen. En este ejemplo, la vista tendrá un encabezado
(con TextView ) y un ListView para mostrar los datos. El diseño se define en el archivo Resources
/layout/HomeScreen. axml que se muestra aquí:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView android:id="@+id/Heading"
android:text="Vegetable Groups"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#00000000"
android:textSize="30dp"
android:textColor="#FF267F00"
android:textStyle="bold"
android:padding="5dp"
/>
<ListView android:id="@+id/List"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:cacheColorHint="#FFDAFF7F"
/>
</LinearLayout>

La ventaja de usar un Activity con un diseño personalizado (en lugar de un ListActivity ) radica en poder
agregar controles adicionales a la pantalla, como el encabezado TextView de este ejemplo.
Crear un diseño de fila personalizado
Se requiere otro archivo de diseño AXML para que contenga el diseño personalizado para cada fila que aparecerá
en la vista de lista. En este ejemplo, la fila tendrá un fondo verde, texto marrón y imagen alineada a la derecha. El
marcado XML de Android para declarar este diseño se describe en Resources /layout/CustomView. axml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#FFDAFF7F"
android:padding="8dp">
<LinearLayout android:id="@+id/Text"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dip">
<TextView
android:id="@+id/Text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FF7F3300"
android:textSize="20dip"
android:textStyle="italic"
/>
<TextView
android:id="@+id/Text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14dip"
android:textColor="#FF267F00"
android:paddingLeft="100dip"
/>
</LinearLayout>
<ImageView
android:id="@+id/Image"
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="5dp"
android:src="@drawable/icon"
android:layout_alignParentRight="true" />
</RelativeLayout >

Aunque un diseño de fila personalizado puede contener muchos controles diferentes, el rendimiento del
desplazamiento puede verse afectado por diseños complejos y el uso de imágenes (especialmente si tienen que
cargarse a través de la red). Vea el artículo de Google para obtener más información sobre cómo solucionar
problemas de rendimiento de desplazamiento.
Hacer referencia a una vista de fila personalizada
La implementación del ejemplo de adaptador personalizado está en HomeScreenAdapter.cs . El método clave es
GetView donde carga el AXML personalizado mediante el identificador Resource.Layout.CustomView de recurso y, a
continuación, establece las propiedades de cada uno de los controles de la vista antes de devolverlos. Se muestra la
clase de adaptador completa:
public class HomeScreenAdapter : BaseAdapter<TableItem> {
List<TableItem> items;
Activity context;
public HomeScreenAdapter(Activity context, List<TableItem> items)
: base()
{
this.context = context;
this.items = items;
}
public override long GetItemId(int position)
{
return position;
}
public override TableItem this[int position]
{
get { return items[position]; }
}
public override int Count
{
get { return items.Count; }
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
var item = items[position];
View view = convertView;
if (view == null) // no view to re-use, create new
view = context.LayoutInflater.Inflate(Resource.Layout.CustomView, null);
view.FindViewById<TextView>(Resource.Id.Text1).Text = item.Heading;
view.FindViewById<TextView>(Resource.Id.Text2).Text = item.SubHeading;
view.FindViewById<ImageView>(Resource.Id.Image).SetImageResource(item.ImageResourceId);
return view;
}
}

Hacer referencia al control ListView personalizado en la actividad


Dado que HomeScreen la clase ahora hereda de Activity , se ListView declara un campo en la clase para que
contenga una referencia al control declarado en AXML:

ListView listView;

A continuación, la clase debe cargar el AXML de diseño personalizado de SetContentView la actividad mediante el
método. Después, puede encontrar el ListView control en el diseño y, a continuación, crea y asigna el adaptador y
asigna el controlador de clic. Aquí se muestra el código para el método de creación:

SetContentView(Resource.Layout.HomeScreen); // loads the HomeScreen.axml as this activity's view


listView = FindViewById<ListView>(Resource.Id.List); // get reference to the ListView in the layout

// populate the listview with data


listView.Adapter = new HomeScreenAdapter(this, tableItems);
listView.ItemClick += OnListItemClick; // to be defined

Por último ItemClick , se debe definir el controlador; en este caso, solo Toast muestra un mensaje:

void OnListItemClick(object sender, AdapterView.ItemClickEventArgs e)


{
var listView = sender as ListView;
var t = tableItems[e.Position];
Android.Widget.Toast.MakeText(this, t.Heading, Android.Widget.ToastLength.Short).Show();
}
La pantalla resultante tiene el siguiente aspecto:

Personalizar el color del selector de filas


Cuando se toca una fila, debe resaltarse para los comentarios de los usuarios. Cuando una vista personalizada
especifica como color de fondo como CustomView. axml , también invalida el resaltado de la selección. Esta línea
de código de CustomView. axml establece el fondo en verde claro, pero también significa que no hay ningún
indicador visual cuando se toca la fila:

android:background="#FFDAFF7F"

Para volver a habilitar el comportamiento de resaltado y también para personalizar el color que se usa, establezca
el atributo Background en un selector personalizado en su lugar. El selector declarará el color de fondo
predeterminado y el color de resaltado. El archivo Resources/drawable/CustomSelector. XML contiene la
siguiente declaración:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="false"
android:state_selected="false"
android:drawable="@color/cellback" />
<item android:state_pressed="true" >
<shape>
<gradient
android:startColor="#E77A26"
android:endColor="#E77A26"
android:angle="270" />
</shape>
</item>
<item android:state_selected="true"
android:state_pressed="false"
android:drawable="@color/cellback" />
</selector>

Para hacer referencia al selector personalizado, cambie el atributo Background de CustomView. axml a:

android:background="@drawable/CustomSelector"

Una fila seleccionada y el mensaje Toast correspondiente ahora tienen el siguiente aspecto:
Evitar el parpadeo en los diseños personalizados
Android intenta mejorar el rendimiento del desplazamiento ListView mediante el almacenamiento en caché de la
información de diseño. Si tiene listas de desplazamiento de datos de gran tamaño, también debe establecer
android:cacheColorHint la propiedad en ListView la declaración de la definición de AXML de la actividad (en el
mismo valor de color que el fondo del diseño de fila personalizado). Si no se incluye esta sugerencia, se podría
producir un "parpadeo" cuando el usuario se desplace a través de una lista con colores de fondo de fila
personalizados.

Vínculos relacionados
BuiltInViews (ejemplo)
AccessoryViews (ejemplo)
CustomRowView (ejemplo)
Uso de CursorAdapters con Xamarin. Android
31/07/2019 • 10 minutes to read • Edit Online

Android proporciona clases de adaptador específicamente para Mostrar datos de una consulta de base de datos
SQLite:
SimpleCursorAdapter : similar a un ArrayAdapter porque se puede usar sin subclases. Simplemente proporcione
los parámetros necesarios (como un cursor y la información de diseño) en el constructor y, a continuación
ListView , asígnelo a.

CursorAdapter : una clase base de la que se puede heredar cuando se necesita más control sobre el enlace de
valores de datos a los controles de diseño (por ejemplo, ocultar o mostrar controles o cambiar sus propiedades).
Los adaptadores de cursor proporcionan una forma de alto rendimiento para desplazarse a través de las largas
listas de datos que se almacenan en SQLite. El código utilizado debe definir una consulta SQL en un Cursor
objeto y, a continuación, describir cómo crear y rellenar las vistas de cada fila.

Crear una base de datos de SQLite


Para mostrar los adaptadores de cursores se requiere una implementación de base de datos SQLite simple. El
código de SimpleCursorTableAdapter/VegetableDatabase. CS contiene el código y SQL para crear una tabla
y rellenarla con algunos datos. Aquí se VegetableDatabase muestra la clase completa:

class VegetableDatabase : SQLiteOpenHelper {


public static readonly string create_table_sql =
"CREATE TABLE [vegetables] ([_id] INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL UNIQUE, [name] TEXT NOT
NULL UNIQUE)";
public static readonly string DatabaseName = "vegetables.db";
public static readonly int DatabaseVersion = 1;
public VegetableDatabase(Context context) : base(context, DatabaseName, null, DatabaseVersion) { }
public override void OnCreate(SQLiteDatabase db)
{
db.ExecSQL(create_table_sql);
// seed with data
db.ExecSQL("INSERT INTO vegetables (name) VALUES ('Vegetables')");
db.ExecSQL("INSERT INTO vegetables (name) VALUES ('Fruits')");
db.ExecSQL("INSERT INTO vegetables (name) VALUES ('Flower Buds')");
db.ExecSQL("INSERT INTO vegetables (name) VALUES ('Legumes')");
db.ExecSQL("INSERT INTO vegetables (name) VALUES ('Bulbs')");
db.ExecSQL("INSERT INTO vegetables (name) VALUES ('Tubers')");
}
public override void OnUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{ // not required until second version :)
throw new NotImplementedException();
}
}

Se creará una instancia de la clase OnCreate en el método HomeScreen de la actividad. La


VegetableDatabase
SQLiteOpenHelper clase base administra la configuración del archivo de base de datos y garantiza que el SQL
OnCreate en su método solo se ejecuta una vez. Esta clase se utiliza en los dos ejemplos siguientes para
SimpleCursorAdapter y CursorAdapter .

La consulta de cursor debe tener una columna _id de enteros para CursorAdapter que funcione. Si la tabla
subyacente no tiene una columna de enteros denominada _id , utilice un alias de columna para otro entero único
RawQuery en que conforma el cursor. Consulte los documentos de Android para obtener más información.
Crear el cursor
En los ejemplos RawQuery se usa para convertir una consulta SQL en Cursor un objeto. La lista de columnas que
se devuelve desde el cursor define las columnas de datos que están disponibles para su presentación en el
adaptador de cursor. Aquí se muestra el código que crea la base de datos en el método
SimpleCursorTableAdapter/HomeScreen. CS OnCreate :

vdb = new VegetableDatabase(this);


cursor = vdb.ReadableDatabase.RawQuery("SELECT * FROM vegetables", null); // cursor query
StartManagingCursor(cursor);
// use either SimpleCursorAdapter or CursorAdapter subclass here!

Cualquier código que llame StartManagingCursor a también debe StopManagingCursorllamar a. En los ejemplos
OnCreate se usa para iniciar OnDestroy y para cerrar el cursor. El OnDestroy método contiene este código:

StopManagingCursor(cursor);
cursor.Close();

Una vez que una aplicación tiene una base de datos SQLite disponible y ha creado un objeto Cursor como se
muestra, SimpleCursorAdapter puede utilizar o una subclase de CusorAdapter para mostrar las ListView filas en
un.

Usar SimpleCursorAdapter
SimpleCursorAdapter es como, ArrayAdapter pero especializado para su uso con SQLite. No requiere creación de
subclases: solo tiene que establecer algunos parámetros simples al crear el objeto y, a continuación ListView ,
Adapter asignarlo a la propiedad de.

Los parámetros para el constructor SimpleCursorAdapter son:


Context : referencia a la actividad contenedora.
Diseño : el identificador de recurso de la vista de fila que se va a usar.
ICursor : un cursor que contiene la consulta de SQLite para los datos que se van a mostrar.
De la matriz de cadenas: matriz de cadenas que corresponden a los nombres de las columnas del cursor.
En matriz de enteros: matriz de identificadores de diseño que corresponden a los controles del diseño de fila. El
valor de la columna especificada en la from matriz se enlazará al ControlID especificado en esta matriz en el
mismo índice.
Las from matrices to y deben tener el mismo número de entradas porque forman una asignación desde el
origen de datos a los controles de diseño de la vista.
El código SimpleCursorAdapter de ejemplo SimpleCursorTableAdapter/HomeScreen. CS es similar al
siguiente:

// which columns map to which layout controls


string[] fromColumns = new string[] {"name"};
int[] toControlIDs = new int[] {Android.Resource.Id.Text1};
// use a SimpleCursorAdapter
listView.Adapter = new SimpleCursorAdapter (this, Android.Resource.Layout.SimpleListItem1, cursor,
fromColumns,
toControlIDs);

SimpleCursorAdapter es una manera rápida y sencilla de mostrar los datos de SQLite ListView en un. La principal
limitación es que solo puede enlazar valores de columna a controles de visualización, no permite cambiar otros
aspectos del diseño de fila (por ejemplo, mostrar u ocultar controles o cambiar propiedades).

Subclase de CursorAdapter
Una CursorAdapter subclase tiene las mismas ventajas de rendimiento que SimpleCursorAdapter para mostrar los
datos de SQLite, pero también proporciona un control completo sobre la creación y el diseño de cada vista de fila.
La CursorAdapter implementación es muy diferente de la BaseAdapter subclase porque no invalida GetView ,
GetItemId Count o this[] el indizador.

Dada una base de datos de SQLite en funcionamiento, solo necesita invalidar dos métodos CursorAdapter para
crear una subclase:
BindView : dada una vista, actualícelo para mostrar los datos en el cursor proporcionado.
NewView : se llama cuando ListView requiere una nueva vista para mostrar. El CursorAdapter se
encargará de las vistas de reciclaje ( GetView a diferencia del método en los adaptadores normales).
Las subclases de adaptador de ejemplos anteriores tienen métodos para devolver el número de filas y para
recuperar el elemento actual: CursorAdapter el no requiere estos métodos porque esa información se puede
obtener del propio cursor. Al dividir la creación y el rellenado de cada vista en estos dos métodos CursorAdapter ,
el aplica la reutilización de la vista. Esto contrasta con un adaptador normal en el que es posible omitir el
convertView parámetro BaseAdapter.GetView del método.

Implementar CursorAdapter
El código de CursorTableAdapter/HomeScreenCursorAdapter. CS contiene una CursorAdapter subclase.
Almacena una referencia LayoutInflater de contexto pasada en el constructor para que pueda tener acceso a en el
NewView método. La clase completa tiene el siguiente aspecto:

public class HomeScreenCursorAdapter : CursorAdapter {


Activity context;
public HomeScreenCursorAdapter(Activity context, ICursor c)
: base(context, c)
{
this.context = context;
}
public override void BindView(View view, Context context, ICursor cursor)
{
var textView = view.FindViewById<TextView>(Android.Resource.Id.Text1);
textView.Text = cursor.GetString(1); // 'name' is column 1 in the cursor query
}
public override View NewView(Context context, ICursor cursor, ViewGroup parent)
{
return this.context.LayoutInflater.Inflate(Android.Resource.Layout.SimpleListItem1, parent, false);
}
}

Asignación de CursorAdapter
En el Activity que mostrará el ListView , cree el cursor y CursorAdapter , a continuación, asígnelo a la vista de
lista.
El código que realiza esta acción en el método CursorTableAdapter/HomeScreen. CS OnCreate se muestra
aquí:
// create the cursor
vdb = new VegetableDatabase(this);
cursor = vdb.ReadableDatabase.RawQuery("SELECT * FROM vegetables", null);
StartManagingCursor(cursor);

// create the CursorAdapter


listView.Adapter = (IListAdapter)new HomeScreenCursorAdapter(this, cursor, false);

El OnDestroy método contiene la StopManagingCursor llamada al método que se ha descrito anteriormente.

Vínculos relacionados
SimpleCursorTableAdapter (ejemplo)
CursorTableAdapter (ejemplo)
Uso de un ContentProvider con Xamarin. Android
27/07/2019 • 2 minutes to read • Edit Online

CursorAdapters también se puede usar para mostrar los datos de un ContentProvider. ContentProviders le
permiten tener acceso a los datos expuestos por otras aplicaciones (incluidos los datos del sistema Android como
contactos, información multimedia y calendario).
La mejor manera de tener acceso a un ContentProvider es con un CursorLoader mediante LoaderManager.
LoaderManager se presentó en Android 3,0 (nivel de API 11, Honeycomb) para quitar las tareas de bloqueo del
subproceso principal y el uso de CursorLoader permite cargar los datos en un subproceso antes de enlazarlos a un
control ListView para su presentación.
Consulte Introducción a ContentProviders para obtener más información.
ListView. Android ListView y el ciclo de vida de la
actividad
27/07/2019 • 3 minutes to read • Edit Online

Las actividades pasan por determinados Estados a medida que se ejecuta la aplicación, como el inicio, la ejecución,
la pausa y la detención. Para obtener más información e instrucciones específicas sobre el control de las
transiciones de estado, vea el tutorial del ciclo de vidade la actividad. Es importante comprender el ciclo de vida de
la actividad y ListView colocar el código en las ubicaciones correctas.
Todos los ejemplos de este documento realizan tareas de configuración en el método de OnCreate la actividad y, si
es necesario, realizan el "Desmontaje" en. OnDestroy Los ejemplos suelen usar pequeños conjuntos de datos que
no cambian, por lo que no es necesario volver a cargar los datos con más frecuencia.
Sin embargo, si los datos cambian con frecuencia o usan una gran cantidad de memoria, podría ser adecuado
utilizar distintos métodos de ciclo de vida para ListView rellenar y actualizar. Por ejemplo, si los datos subyacentes
cambian constantemente (o pueden verse afectados por actualizaciones en otras actividades), al crear el adaptador
OnStart en OnResume o se garantizará que se muestren los datos más recientes cada vez que se muestre la
actividad.
Si el adaptador usa recursos como memoria, o un cursor administrado, recuerde liberar esos recursos en el
método complementario en el que se crearon instancias (por ejemplo, los objetos creados OnStart en se pueden
desechar en OnStop ).

Cambios de configuración
Es importante recordar que los cambios – de configuración, especialmente el giro de la pantalla y la visibilidad –
del teclado, pueden hacer que la actividad actual se destruya y se vuelva a ConfigurationChanges crear (a menos
que se especifique lo contrario mediante el atributo). Esto significa que, en condiciones normales, la rotación de un
dispositivo ListView Adapter hará que se vuelva a crear y (a menos que haya escrito código OnPause en
OnResume y), se perderán los Estados de selección de fila y posición de desplazamiento.

El atributo siguiente impedirá que una actividad se destruya y se vuelva a crear como resultado de los cambios de
configuración:

[Activity(ConfigurationChanges="keyboardHidden|orientation")]

Después, la actividad debe OnConfigurationChanged reemplazar para responder a los cambios de forma adecuada.
Para obtener más información sobre cómo controlar los cambios de configuración, consulte la documentación de.
GridView de Xamarin. Android
16/08/2019 • 7 minutes to read • Edit Online

GridView es un ViewGroup que muestra los elementos en una cuadrícula bidimensional desplazable. Los elementos
de la cuadrícula se insertan automáticamente en el ListAdapter diseño mediante.
En este tutorial, creará una cuadrícula de miniaturas de imagen. Cuando se selecciona un elemento, se muestra la
posición de la imagen en un mensaje del sistema.
Inicie un nuevo proyecto denominado HelloGridView.
Busque algunas fotos que le gustaría usar o Descargue estas imágenes de ejemplo. Agregue los archivos de
imagen al directorio Resources /drawable del proyecto. En la ventana propiedades , establezca la acción de
compilación para cada en AndroidResource.
Abra el archivo Resources /layout/main. axml e inserte lo siguiente:

<?xml version="1.0" encoding="utf-8"?>


<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/gridview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:columnWidth="90dp"
android:numColumns="auto_fit"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp"
android:stretchMode="columnWidth"
android:gravity="center"
/>

Esto GridView rellenará toda la pantalla. Los atributos son bastante descriptivos. Para obtener más información
sobre los atributos válidos GridView , vea la referencia.
Abra HelloGridView.cs e inserte el código siguiente para el OnCreate() forma

protected override void OnCreate (Bundle bundle)


{
base.OnCreate (bundle);

SetContentView (Resource.Layout.Main);

var gridview = FindViewById<GridView> (Resource.Id.gridview);


gridview.Adapter = new ImageAdapter (this);

gridview.ItemClick += delegate (object sender, AdapterView.ItemClickEventArgs args) {


Toast.MakeText (this, args.Position.ToString (), ToastLength.Short).Show ();
};
}

Una vez establecido el diseño Main. axml para la vista de contenido, GridView se captura desde el diseño con
FindViewById . El Adapter a continuación, se utiliza la propiedad para establecer un ImageAdapter adaptador
personalizado () como el origen de todos los elementos que se van a mostrar en la cuadrícula. ImageAdapter Se
crea en el paso siguiente.
Para hacer algo cuando se hace clic en un elemento de la cuadrícula, se suscribe un delegado anónimo al
ItemClick evento. Muestra un Toast que muestra la posición de índice (basada en cero) del elemento
seleccionado (en un escenario real, la posición se podría usar para obtener la imagen de tamaño completo para
otra tarea). Tenga en cuenta que se pueden usar clases de agente de escucha de estilo Java en lugar de eventos de
.NET.
Cree una nueva clase denominada ImageAdapter BaseAdapter subclases:

public class ImageAdapter : BaseAdapter


{
Context context;

public ImageAdapter (Context c)


{
context = c;
}

public override int Count {


get { return thumbIds.Length; }
}

public override Java.Lang.Object GetItem (int position)


{
return null;
}

public override long GetItemId (int position)


{
return 0;
}

// create a new ImageView for each item referenced by the Adapter


public override View GetView (int position, View convertView, ViewGroup parent)
{
ImageView imageView;

if (convertView == null) { // if it's not recycled, initialize some attributes


imageView = new ImageView (context);
imageView.LayoutParameters = new GridView.LayoutParams (85, 85);
imageView.SetScaleType (ImageView.ScaleType.CenterCrop);
imageView.SetPadding (8, 8, 8, 8);
} else {
imageView = (ImageView)convertView;
}

imageView.SetImageResource (thumbIds[position]);
return imageView;
}

// references to our images


int[] thumbIds = {
Resource.Drawable.sample_2, Resource.Drawable.sample_3,
Resource.Drawable.sample_4, Resource.Drawable.sample_5,
Resource.Drawable.sample_6, Resource.Drawable.sample_7,
Resource.Drawable.sample_0, Resource.Drawable.sample_1,
Resource.Drawable.sample_2, Resource.Drawable.sample_3,
Resource.Drawable.sample_4, Resource.Drawable.sample_5,
Resource.Drawable.sample_6, Resource.Drawable.sample_7,
Resource.Drawable.sample_0, Resource.Drawable.sample_1,
Resource.Drawable.sample_2, Resource.Drawable.sample_3,
Resource.Drawable.sample_4, Resource.Drawable.sample_5,
Resource.Drawable.sample_6, Resource.Drawable.sample_7
};
}

En primer lugar, implementa algunos métodos necesarios heredados BaseAdapter de. El constructor y la Count
propiedad se explican por sí solos. Regla GetItem(int) debe devolver el objeto real situado en la posición
especificada en el adaptador, pero se omite en este ejemplo. Forma GetItemId(int) debe devolver el ID. de fila del
elemento, pero no es necesario aquí.
El primer método necesario es GetView() . Este método crea una nueva View para cada imagen agregada a
ImageAdapter . Cuando se llama a, un View se pasa, que suele ser un objeto reciclado (al menos después de que se
haya llamado una vez), por lo que hay una comprobación para ver si el objeto es NULL. Si es null, un valor de
ImageView se crea una instancia y se configura con las propiedades deseadas para la presentación de la imagen:

LayoutParams establece el alto y el ancho de la—vista, lo que garantiza que, independientemente del tamaño
de la dibujable, cada imagen cambia de tamaño y se recorta para ajustarse a estas dimensiones, según
corresponda.
SetScaleType() declara que las imágenes se deben recortar hacia el centro (si es necesario).
SetPadding(int, int, int, int) define el relleno de todos los lados. (Tenga en cuenta que, si las imágenes
tienen diferentes proporciones de aspecto, menos espaciado provocará un recorte de la imagen si no
coincide con las dimensiones proporcionadas a ImageView ).
Si el View que se GetView() pasa a no es null, el local ImageView se inicializa con el objeto reciclado View .
Al final de la GetView() , el position entero que se pasa al método se usa para seleccionar una imagen de la
thumbIds matriz, que se establece como ImageView el recurso de imagen para.

Lo único que queda es definir la matriz thumbIds de recursos que se van a dibujar.
Ejecute la aplicación. El diseño de la cuadrícula debería tener un aspecto similar al siguiente:

Pruebe a experimentar con los comportamientos de GridView y ImageView elementos ajustando sus propiedades.
Por ejemplo, en lugar de usar LayoutParams try using SetAdjustViewBounds() .

Referencias
GridView
ImageView
BaseAdapter

Algunas partes de esta página son modificaciones basadas en el trabajo creado y compartido por el proyecto de
código abierto de Android y que se usan según los términos descritos en la licencia de atribución de Creative
Commons 2,5.
GridLayout de Xamarin. Android
31/07/2019 • 6 minutes to read • Edit Online

Es GridLayout una nueva ViewGroup subclase que admite la colocación de vistas en una cuadrícula 2D, similar a
una tabla HTML, como se muestra a continuación:

GridLayout funciona con una jerarquía de vista plana, en la que las vistas secundarias establecen sus ubicaciones
en la cuadrícula especificando las filas y las columnas en las que deben estar. De este modo, el GridLayout puede
colocar las vistas en la cuadrícula sin necesidad de que las vistas intermedias proporcionen una estructura de
tabla, como se muestra en las filas de la tabla que se usan en TableLayout. Al mantener una jerarquía plana,
GridLayout puede diseñar más rápidamente sus vistas secundarias. Echemos un vistazo a un ejemplo para ilustrar
lo que significa realmente este concepto en el código.

Crear un diseño de cuadrícula


El siguiente XML agrega varios TextView controles a un GridLayout.

<?xml version="1.0" encoding="utf-8"?>


<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:rowCount="2"
android:columnCount="2">
<TextView
android:text="Cell 0"
android:textSize="14dip" />
<TextView
android:text="Cell 1"
android:textSize="14dip" />
<TextView
android:text="Cell 2"
android:textSize="14dip" />
<TextView
android:text="Cell 3"
android:textSize="14dip" />
</GridLayout>

El diseño ajustará el tamaño de las filas y las columnas para que puedan ajustarse a su contenido, tal como se
muestra en el diagrama siguiente:
Esto da como resultado la siguiente interfaz de usuario cuando se ejecuta en una aplicación:

Especificar orientación
Observe que en el XML anterior, TextView cada no especifica una fila o columna. Cuando no se especifican, el
GridLayout asigna cada vista secundaria en orden, en función de la orientación. Por ejemplo, vamos a cambiar la
orientación del GridLayout del valor predeterminado, que es horizontal, a vertical similar a la siguiente:
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:rowCount="2"
android:columnCount="2"
android:orientation="vertical">
</GridLayout>

Ahora, el GridLayout colocará las celdas de arriba abajo en cada columna, en lugar de izquierda a derecha, como
se muestra a continuación:

Esto da como resultado la siguiente interfaz de usuario en tiempo de ejecución:


Especificar la posición explícita
Si queremos controlar explícitamente las posiciones de las vistas secundarias en GridLayout , podemos establecer
sus layout_row atributos y layout_column . Por ejemplo, el siguiente código XML hará que el diseño se muestre
en la primera captura de pantalla (mostrada anteriormente), independientemente de la orientación.
<?xml version="1.0" encoding="utf-8"?>
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:rowCount="2"
android:columnCount="2">
<TextView
android:text="Cell 0"
android:textSize="14dip"
android:layout_row="0"
android:layout_column="0" />
<TextView
android:text="Cell 1"
android:textSize="14dip"
android:layout_row="0"
android:layout_column="1" />
<TextView
android:text="Cell 2"
android:textSize="14dip"
android:layout_row="1"
android:layout_column="0" />
<TextView
android:text="Cell 3"
android:textSize="14dip"
android:layout_row="1"
android:layout_column="1" />
</GridLayout>

Especificar el espaciado
Tenemos un par de opciones que proporcionarán espaciado entre las vistas secundarias de GridLayout . Podemos
usar el layout_margin atributo para establecer el margen en cada vista secundaria directamente, como se muestra
a continuación.

<TextView
android:text="Cell 0"
android:textSize="14dip"
android:layout_row="0"
android:layout_column="0"
android:layout_margin="10dp" />

Además, en Android 4, ya está disponible una nueva vista de espaciado Space de uso general denominada. Para
usarlo, simplemente agréguelo como una vista secundaria. Por ejemplo, el XML siguiente agrega una fila adicional
al estableciendo GridLayout el rowcount valor de en 3, y agrega una Space vista que proporciona espaciado
entre el TextViews .
<?xml version="1.0" encoding="utf-8"?>
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:rowCount="3"
android:columnCount="2"
android:orientation="vertical">
<TextView
android:text="Cell 0"
android:textSize="14dip"
android:layout_row="0"
android:layout_column="0" />
<TextView
android:text="Cell 1"
android:textSize="14dip"
android:layout_row="0"
android:layout_column="1" />
<Space
android:layout_row="1"
android:layout_column="0"
android:layout_width="50dp"
android:layout_height="50dp" />
<TextView
android:text="Cell 2"
android:textSize="14dip"
android:layout_row="2"
android:layout_column="0" />
<TextView
android:text="Cell 3"
android:textSize="14dip"
android:layout_row="2"
android:layout_column="1" />
</GridLayout>

Este XML crea el espaciado en GridLayout el, tal y como se muestra a continuación:
La ventaja de usar la nueva Space vista es que permite el espaciado y no es necesario establecer atributos en cada
vista secundaria.
Expandir columnas y filas
GridLayout También admite celdas que abarcan varias columnas y filas. Por ejemplo, suponga que agregamos
otra fila que contiene un botón GridLayout a, tal y como se muestra a continuación:
<?xml version="1.0" encoding="utf-8"?>
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:rowCount="4"
android:columnCount="2"
android:orientation="vertical">
<TextView
android:text="Cell 0"
android:textSize="14dip"
android:layout_row="0"
android:layout_column="0" />
<TextView
android:text="Cell 1"
android:textSize="14dip"
android:layout_row="0"
android:layout_column="1" />
<Space
android:layout_row="1"
android:layout_column="0"
android:layout_width="50dp"
android:layout_height="50dp" />
<TextView
android:text="Cell 2"
android:textSize="14dip"
android:layout_row="2"
android:layout_column="0" />
<TextView
android:text="Cell 3"
android:textSize="14dip"
android:layout_row="2"
android:layout_column="1" />
<Button
android:id="@+id/myButton"
android:text="@string/hello"
android:layout_row="3"
android:layout_column="0" />
</GridLayout>

Esto hará que la primera columna de GridLayout se estire para acomodar el tamaño del botón, como se ve aquí:
Para evitar que la primera columna se ajuste, podemos establecer el botón para que abarque dos columnas; para
ello, establezca su ColumnSpan de la siguiente manera:

<Button
android:id="@+id/myButton"
android:text="@string/hello"
android:layout_row="3"
android:layout_column="0"
android:layout_columnSpan="2" />

Esto da como resultado un diseño para TextViews que sea similar al diseño que teníamos anteriormente, con el
botón agregado a la parte inferior GridLayout de, como se muestra a continuación:
Vínculos relacionados
GridLayoutDemo (ejemplo)
Presentación del bocadillo de helado
Plataforma Android 4,0
Diseños con pestañas
16/08/2019 • 2 minutes to read • Edit Online

Información general
Las pestañas son un conocido patrón de interfaz de usuario en aplicaciones móviles debido a su simplicidad y
facilidad de uso. Proporcionan una manera coherente y sencilla de desplazarse entre varias pantallas en una
aplicación. Android tiene varias API para las interfaces con pestañas:
Barra – Esto forma parte de un nuevo conjunto de API que se presentó en Android 3,0 (nivel de API 11)
con el objetivo de proporcionar una interfaz de navegación y cambio de vista coherente. Se ha trasladado a
Android 2,2 (nivel de API 8) con la biblioteca de compatibilidad de Android V7.
PagerTabStrip Indica las páginas actual, siguiente y anterior ViewPager de. – ViewPager solo está
disponible a través de la biblioteca de compatibilidad de Android V4. Para obtener más información
PagerTabStrip sobre, vea ViewPager.

Barra de herramientas es un componente de barra de acción más reciente y flexible ActionBar que
reemplaza a. – Toolbar Toolbar está disponible en Android 5,0 Lollipop o posterior y también está
disponible para versiones anteriores de Android mediante el paquete NuGet de la biblioteca de
compatibilidad de Android V7 . Toolbar es actualmente el componente de la barra de acciones
recomendado que se usará en las aplicaciones Android. Para obtener más información, vea barra de
herramientas.

Vínculos relacionados
Diseño material: pestañas- barra
Biblioteca de compatibilidad de Android V7 paquete NuGet de NuGet
V7 biblioteca AppCompat
Diseños con pestañas con barra
16/08/2019 • 10 minutes to read • Edit Online

En esta guía se presenta y explica cómo usar las API de barra para crear una interfaz de usuario con pestañas en
una aplicación de Xamarin. Android.

Información general
La barra de acción es un patrón de interfaz de usuario de Android que se usa para proporcionar una interfaz de
usuario coherente para características clave como pestañas, identidad de la aplicación, menús y búsqueda. En
Android 3,0 (nivel de API 11), Google presentó las API de barra en la plataforma Android. Las API de barra
introducen temas de interfaz de usuario para proporcionar una apariencia y un funcionamiento coherentes, y clases
que permiten las interfaces de usuario con pestañas. En esta guía se explica cómo agregar pestañas de Barra de
acciones a una aplicación de Xamarin. Android. También se explica cómo usar la biblioteca de compatibilidad de
Android V7 para reportar las pestañas de barra a las aplicaciones de Xamarin. Android dirigidas a Android 2,1 a
Android 2,3.
Tenga en Toolbarcuenta que es un componente de barra de acciones más reciente y más generalizado que debe
ActionBar usar Toolbar en lugar de ( ActionBar se diseñó para reemplazar ). Para obtener más información, vea
barra de herramientas.

Requisitos
Cualquier aplicación de Xamarin. Android que tenga como destino el nivel de API 11 (Android 3,0) o superior tiene
acceso a las API de barra como parte de las API nativas de Android.
Algunas de las API de barra se han trasladado al nivel de API 7 (Android 2,1) y están disponibles a través de la
biblioteca de AppCompatde la versión V7, que está disponible para las aplicaciones de Xamarin. Android a través
del paquete biblioteca de compatibilidad de Android-V7 .

Introducción a las pestañas de barra


La barra de acción intenta mostrar todas sus pestañas simultáneamente y hacer que todas las pestañas tengan el
mismo tamaño en función del ancho de la etiqueta de la pestaña más ancha. Esto se muestra en la siguiente
captura de pantalla:

Cuando el barra no puede mostrar todas las pestañas, se configuran las pestañas en una vista con desplazamiento
horizontal. El usuario puede deslizar el dedo hacia la izquierda o la derecha para ver las pestañas restantes. Esta
captura de pantalla de Google Play muestra un ejemplo de esto:
Cada pestaña de la barra de acciones debe estar asociada a un fragmento. Cuando el usuario selecciona una
pestaña, la aplicación mostrará el fragmento que está asociado a la ficha. Barra no es responsable de mostrar el
fragmento adecuado al usuario. En su lugar, barra notificará a una aplicación los cambios de estado en una pestaña
a través de una clase que implementa la interfaz barra. ITabListener. Esta interfaz proporciona tres métodos de
devolución de llamada que Android invocará cuando cambie el estado de la pestaña:
OnTabSelected : se llama a este método cuando el usuario selecciona la pestaña. Debe mostrar el
fragmento.
OnTabReselected : se llama a este método cuando la pestaña ya está seleccionada pero el usuario la
selecciona de nuevo. Esta devolución de llamada se usa normalmente para actualizar o actualizar el
fragmento mostrado.
OnTabUnselected : se llama a este método cuando el usuario selecciona otra pestaña. Esta devolución de
llamada se utiliza para guardar el estado en el fragmento mostrado antes de desaparecer.
Xamarin. Android encapsula el ActionBar.ITabListener con eventos en la ActionBar.Tab clase. Las aplicaciones
pueden asignar controladores de eventos a uno o varios de estos eventos. Hay tres eventos (uno para cada método
en ActionBar.ITabListener ) que generará una pestaña de la barra de acciones:
TabSelected
TabReselected
TabUnselected
Agregar pestañas a barra
Barra es nativo para Android 3,0 (nivel de API 11) y superior y está disponible para cualquier aplicación de
Xamarin. Android que tenga como mínimo esta API.
En los pasos siguientes se muestra cómo agregar pestañas de barra a una actividad de Android:
1. En el método de una actividad – – antes de inicializar los widgets de interfaz de usuario
OnCreate
NavigationMode ActionBar.NavigationModeTabs , una ActionBar aplicación debe establecer en en como se
muestra en este fragmento de código:

ActionBar.NavigationMode = ActionBarNavigationMode.Tabs;
SetContentView(Resource.Layout.Main);

2. Cree una nueva pestaña con ActionBar.NewTab() .


3. Asigne controladores de eventos o proporcione una implementación ActionBar.ITabListener personalizada
que responderá a los eventos que se producen cuando el usuario interactúa con las pestañas de barra.
4. Agregue la pestaña que se creó en el paso anterior al ActionBar .
El código siguiente es un ejemplo del uso de estos pasos para agregar pestañas a una aplicación que usa
controladores de eventos para responder a los cambios de estado:
protected override void OnCreate(Bundle bundle)
{
ActionBar.NavigationMode = ActionBarNavigationMode.Tabs;
SetContentView(Resource.Layout.Main);

ActionBar.Tab tab = ActionBar.NewTab();


tab.SetText(Resources.GetString(Resource.String.tab1_text));
tab.SetIcon(Resource.Drawable.tab1_icon);
tab.TabSelected += (sender, args) => {
// Do something when tab is selected
};
ActionBar.AddTab(tab);

tab = ActionBar.NewTab();
tab.SetText(Resources.GetString(Resource.String.tab2_text));
tab.SetIcon(Resource.Drawable.tab2_icon);
tab.TabSelected += (sender, args) => {
// Do something when tab is selected
};
ActionBar.AddTab(tab);
}

Controladores de eventos frente a barra. ITabListener


Las aplicaciones deben usar controladores de eventos ActionBar.ITabListener y para distintos escenarios. Los
controladores de eventos ofrecen una determinada cantidad de comodidad sintáctica; evitan tener que crear una
clase e implementar ActionBar.ITabListener . Esta comodidad se aplica a un costo – que Xamarin. Android realiza
esta transformación, ya que crea una clase e ActionBar.ITabListener implementa automáticamente. Esto es
correcto cuando una aplicación tiene un número limitado de pestañas.
Al tratar con muchas pestañas o compartir la funcionalidad común entre las pestañas de barra, puede ser más
eficaz en cuanto a memoria y rendimiento para crear una clase personalizada ActionBar.ITabListener que
implemente y comparta una única instancia de la clase. Esto reducirá el número de GREF que usa una aplicación
de Xamarin. Android.
Compatibilidad con versiones anteriores de dispositivos antiguos
La biblioteca de compatibilidad de Android V7 Reports barra pestañas en Android 2,1 (nivel de API 7). Se puede
acceder a las pestañas en una aplicación de Xamarin. Android una vez que este componente se ha agregado al
proyecto.
Para usar barra, una actividad debe ser una subclase ActionBarActivity y usar el tema AppCompat tal y como se
muestra en el siguiente fragmento de código:

[Activity(Label = "@string/app_name", Theme = "@style/Theme.AppCompat", MainLauncher = true, Icon =


"@drawable/ic_launcher")]
public class MainActivity: ActionBarActivity

Una actividad puede obtener una referencia a su barra desde la ActionBarActivity.SupportingActionBar propiedad.
En el fragmento de código siguiente se muestra un ejemplo de la configuración de barra en una actividad:
[Activity(Label = "@string/app_name", Theme = "@style/Theme.AppCompat", MainLauncher = true, Icon =
"@drawable/ic_launcher")]
public class MainActivity : ActionBarActivity, ActionBar.ITabListener
{
static readonly string Tag = "ActionBarTabsSupport";

public void OnTabReselected(ActionBar.Tab tab, FragmentTransaction ft)


{
// Optionally refresh/update the displayed tab.
Log.Debug(Tag, "The tab {0} was re-selected.", tab.Text);
}

public void OnTabSelected(ActionBar.Tab tab, FragmentTransaction ft)


{
// Display the fragment the user should see
Log.Debug(Tag, "The tab {0} has been selected.", tab.Text);
}

public void OnTabUnselected(ActionBar.Tab tab, FragmentTransaction ft)


{
// Save any state in the displayed fragment.
Log.Debug(Tag, "The tab {0} as been unselected.", tab.Text);
}

protected override void OnCreate(Bundle bundle)


{
base.OnCreate(bundle);
SupportActionBar.NavigationMode = ActionBar.NavigationModeTabs;
SetContentView(Resource.Layout.Main);
}

void AddTabToActionBar(int labelResourceId, int iconResourceId)


{
ActionBar.Tab tab = SupportActionBar.NewTab()
.SetText(labelResourceId)
.SetIcon(iconResourceId)
.SetTabListener(this);
SupportActionBar.AddTab(tab);
}
}

Resumen
En esta guía se describe cómo crear una interfaz de usuario con pestañas en Xamarin. Android mediante barra.
Hemos explicado cómo agregar pestañas a barra y cómo una actividad puede interactuar con eventos de pestaña a
ActionBar.ITabListener través de la interfaz. También vimos cómo el paquete AppCompat de la biblioteca de
compatibilidad de Android V7 traslada las pestañas de barra a versiones anteriores de Android.

Vínculos relacionados
ActionBarTabs (ejemplo)
Toolbar
Fragmentos
ActionBar
ActionBarActivity
Patrón de Barra de acciones
AppCompat de Android V7
Biblioteca de compatibilidad de Xamarin. Android, paquete de NuGet de AppCompat de la V7
Controles de Xamarin. Android (widgets)
30/07/2019 • 6 minutes to read • Edit Online

Xamarin. Android expone todos los controles de interfaz de usuario (widgets) nativos proporcionados por Android.
Estos controles se pueden agregar fácilmente a las aplicaciones de Xamarin. Android mediante el Android
Designer o mediante programación a través de archivos de diseño XML. Independientemente del método que
elija, Xamarin. Android expone todas las propiedades y métodos de los objetos de la interfaz de C#usuario en. En
las secciones siguientes se presentan los controles de interfaz de usuario de Android más comunes y se explica
cómo incorporarlos a las aplicaciones de Xamarin. Android.

Barra de acciones
ActionBar es una barra de herramientas que muestra el título de la actividad, las interfaces de navegación y otros
elementos interactivos. Normalmente, la barra de acciones aparece en la parte superior de la ventana de una
actividad.

Autocompletar
AutoCompleteTextView es un elemento de la vista de texto editable que muestra sugerencias de finalización
automáticamente mientras el usuario está escribiendo. La lista de sugerencias se muestra en un menú desplegable
en el que el usuario puede elegir un elemento del que reemplazar el contenido del cuadro de edición.

Botones
Los botones son elementos de la interfaz de usuario que el usuario puntea para realizar una acción.
Calendar
La Calendar clase se usa para convertir una instancia específica en el tiempo (un valor de milisegundos que se
desplaza del tiempo) a valores como Year, month, hour, Day del mes y la fecha de la semana siguiente. Calendar
admite una gran cantidad de opciones de interacción con datos de calendario, incluida la capacidad de leer y
escribir eventos, asistentes y recordatorios. Al usar el proveedor de calendario en la aplicación, los datos que
agregue a través de la API aparecerán en la aplicación de calendario integrada que se incluye en Android.

CardView
CardView es un componente de interfaz de usuario que presenta el contenido de texto e imagen en las vistas que
se parecen a las tarjetas. CardView se implementa como un FrameLayout widget con esquinas redondeadas y una
sombra. Normalmente, CardView se usa para presentar un elemento de una sola fila en ListView un GridView
grupo de vistas o.
Editar texto
EditText es un elemento de la interfaz de usuario que se utiliza para escribir y modificar texto.

Galería
Gallery es un widget de diseño que se usa para mostrar los elementos en una lista de desplazamiento horizontal.
coloca la selección actual en el centro de la vista.

Barra de navegación
La barra de navegación proporciona controles de navegación en dispositivos que no incluyen botones de
hardware para Inicio, atrásy menú.

Selectores
Los selectores son elementos de interfaz de usuario que permiten al usuario seleccionar una fecha o una hora
mediante los cuadros de diálogo proporcionados por Android.
Menú emergente
PopupMenu se usa para mostrar menús emergentes que están asociados a una vista determinada.
RatingBar
Un RatingBar es un elemento de la interfaz de usuario que muestra una clasificación en estrellas.

Spinner
Spinner es un elemento de la interfaz de usuario que proporciona una manera rápida de seleccionar un valor de
un conjunto. Se simmilar en una lista desplegable.

Switch
Switch es un elemento de la interfaz de usuario que permite a los usuarios alternar entre dos Estados, como
activado o desactivado. El Switch valor predeterminado es OFF.
TextureView
TextureView es una vista que usa la representación 2D con aceleración de hardware para habilitar la presentación
de un flujo de contenido de vídeo o OpenGL.

ToolBar
El Toolbar widget (introducido en Android 5,0 Lollipop) puede considerarse como una generalización de la
interfaz – de la barra de acciones, por lo que se pretende reemplazar la barra de acciones. Se Toolbar puede usar
en cualquier parte del diseño de una aplicación y es mucho más personalizable que una barra de acción.
ViewPager
ViewPager Es un administrador de diseño que permite al usuario voltear a la izquierda y a la derecha a través de
las páginas de datos.

WebView
WebView es un elemento de la interfaz de usuario que le permite crear su propia ventana para ver páginas web (o
incluso desarrollar un explorador completo).
Barra para Xamarin. Android
31/07/2019 • 7 minutes to read • Edit Online

Cuando se TabActivity usa, el código para crear los iconos de pestaña no tiene ningún efecto cuando se ejecuta
en el marco de trabajo de Android 4,0. Aunque funcionalmente funciona como en las versiones de Android
anteriores a 2,3, la TabActivity propia clase ha quedado en desuso en 4,0. Se ha introducido una nueva forma de
crear una interfaz con pestañas que usa el Barra de acciones, que trataremos A continuación.

Barra de acciones pestañas


El Barra de acciones incluye compatibilidad para agregar interfaces con pestañas en Android 4,0. En la captura de
pantalla siguiente se muestra un ejemplo de este tipo de interfaz.

Para crear pestañas en el barra de acciones, primero es necesario establecer su NavigationMode propiedad para
admitir pestañas. En Android 4, hay ActionBar una propiedad disponible en la clase de actividad, que se puede
usar para establecer NavigationMode lo siguiente:
this.ActionBar.NavigationMode = ActionBarNavigationMode.Tabs;

Una vez hecho esto, podemos crear una pestaña llamando al NewTab método en el barra de acciones. Con esta
instancia de la pestaña, podemos llamar SetText a SetIcon los métodos y para establecer el texto y el icono de la
etiqueta de la pestaña; estas llamadas se realizan en orden en el código que se muestra a continuación:

var tab = this.ActionBar.NewTab ();


tab.SetText (tabText);
tab.SetIcon (Resource.Drawable.ic_tab_white);

Sin embargo, antes de poder agregar la pestaña, es necesario controlar TabSelected el evento. En este
controlador, podemos crear el contenido de la pestaña. Barra de acciones pestañas están diseñadas para trabajar
con fragmentos, que son clases que representan una parte de la interfaz de usuario en una actividad. En este
ejemplo, la vista del fragmento contiene una única TextView , que se infla en nuestra Fragment subclase de esta
manera:

class SampleTabFragment: Fragment


{
public override View OnCreateView (LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState)
{
base.OnCreateView (inflater, container, savedInstanceState);

var view = inflater.Inflate (


Resource.Layout.Tab, container, false);

var sampleTextView =
view.FindViewById<TextView> (Resource.Id.sampleTextView);
sampleTextView.Text = "sample fragment text";

return view;
}
}

El argumento de evento que se TabSelected pasa en el evento TabEventArgs es de tipo, FragmentTransaction que
incluye una propiedad que se puede usar para agregar el fragmento tal y como se muestra a continuación:

tab.TabSelected += delegate(object sender, ActionBar.TabEventArgs e) {


e.FragmentTransaction.Add (Resource.Id.fragmentContainer,
new SampleTabFragment ());
};

Por último, podemos agregar la pestaña al barra de acciones llamando AddTab al método como se muestra en
este código:

this.ActionBar.AddTab (tab);

Para obtener el ejemplo completo, vea el proyecto HelloTabsICS en el código de ejemplo de este documento.

ShareActionProvider
La ShareActionProvider clase permite que se lleve a cabo una acción de uso compartido desde un barra de
acciones. Se encarga de crear una vista de acción con una lista de aplicaciones que pueden controlar un intento de
uso compartido y mantener un historial de las aplicaciones usadas anteriormente para facilitar el acceso a ellas
más adelante desde el Barra de acciones. Esto permite que las aplicaciones compartan datos a través de una
experiencia de usuario coherente en Android.
Ejemplo de uso compartido de imágenes
Por ejemplo, a continuación se muestra una captura de pantalla de un Barra de acciones con un elemento de menú
para compartir una imagen (tomada del ejemplo ShareActionProvider ). Cuando el usuario puntea el elemento de
menú en el Barra de acciones, el ShareActionProvider carga la aplicación para controlar un intento que está
asociado a ShareActionProvider . En este ejemplo, la aplicación de mensajería se ha usado previamente, por lo que
se presenta en el Barra de acciones.

Cuando el usuario hace clic en el elemento en el Barra de acciones, se inicia la aplicación de mensajería que
contiene la imagen compartida, como se muestra a continuación:
Especificar la clase del proveedor de acciones
Para usar ShareActionProvider , establezca el android:actionProviderClass atributo en un elemento de menú en el
XML para el menú del barra de acciones como se indica a continuación:

<?xml version="1.0" encoding="utf-8"?>


<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/shareMenuItem"
android:showAsAction="always"
android:title="@string/sharePicture"
android:actionProviderClass="android.widget.ShareActionProvider" />
</menu>

Inflar el menú
Para inflar el menú, se invalida OnCreateOptionsMenu en la subclase de actividad. Una vez que tenemos una
referencia al menú, podemos obtener el ShareActionProvider de la ActionProvider propiedad del elemento de
menú y, a continuación, usar el método SetShareIntent para ShareActionProvider establecer la intención de, como
se muestra a continuación:
public override bool OnCreateOptionsMenu (IMenu menu)
{
MenuInflater.Inflate (Resource.Menu.ActionBarMenu, menu);

var shareMenuItem = menu.FindItem (Resource.Id.shareMenuItem);


var shareActionProvider =
(ShareActionProvider)shareMenuItem.ActionProvider;
shareActionProvider.SetShareIntent (CreateIntent ());
}

Crear el intento
Usará la intención, pasada SetShareIntent al método en el código anterior, para iniciar la actividad adecuada.
ShareActionProvider En este caso, se crea un intento de enviar una imagen mediante el código siguiente:

Intent CreateIntent ()
{
var sendPictureIntent = new Intent (Intent.ActionSend);
sendPictureIntent.SetType ("image/*");
var uri = Android.Net.Uri.FromFile (GetFileStreamPath ("monkey.png"));
sendPictureIntent.PutExtra (Intent.ExtraStream, uri);
return sendPictureIntent;
}

La imagen del ejemplo de código anterior se incluye como un recurso con la aplicación y se copia en una ubicación
públicamente accesible cuando se crea la actividad, por lo que será accesible para otras aplicaciones, como la
aplicación de mensajería. El código de ejemplo que acompaña a este artículo contiene el código fuente completo
de este ejemplo, que ilustra su uso.

Vínculos relacionados
Pestañas Hello ICS (ejemplo)
Demostración de ShareActionProvider (ejemplo)
Presentación del bocadillo de helado
Plataforma Android 4,0
Autocompletar para Xamarin. Android
16/08/2019 • 7 minutes to read • Edit Online

AutoCompleteTextView es un elemento de la vista de texto editable que muestra sugerencias de finalización


automáticamente mientras el usuario está escribiendo. La lista de sugerencias se muestra en un menú desplegable
en el que el usuario puede elegir un elemento del que reemplazar el contenido del cuadro de edición.

Información general
Para crear un widget de entrada de texto que proporcione sugerencias de autocompletar, use el
AutoCompleteTextView widget. Las sugerencias se reciben de una colección de cadenas asociadas al widget a través
ArrayAdapter de.

En este tutorial, creará un AutoCompleteTextView widget que proporciona sugerencias para un nombre de país.

<?xml version="1.0" encoding="utf-8"?>


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="5dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Country" />
<AutoCompleteTextView android:id="@+id/autocomplete_country"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"/>
</LinearLayout>

TextView Es una etiqueta que presenta el AutoCompleteTextView widget.

Tutorial
Inicie un nuevo proyecto denominado HelloAutoComplete.
Cree un archivo XML denominado list_item.xml y guárdelo dentro de la carpeta recursos/diseño . Establezca la
acción de compilación de este archivo AndroidResource en. Edite el archivo para que tenga el siguiente aspecto:
<?xml version="1.0" encoding="utf-8"?>

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dp"
android:textSize="16sp"
android:textColor="#000">
</TextView>

Este archivo define un simple TextView que se utilizará para cada elemento que aparece en la lista de sugerencias.
Abra Resources/layout/main. axml e inserte lo siguiente:

<?xml version="1.0" encoding="utf-8"?>


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="5dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Country" />
<AutoCompleteTextView android:id="@+id/autocomplete_country"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"/>
</LinearLayout>

Abra MainActivity.CS e inserte el código siguiente para el OnCreate() forma

protected override void OnCreate (Bundle bundle)


{
base.OnCreate (bundle);

// Set our view from the "Main" layout resource


SetContentView (Resource.Layout.Main);

AutoCompleteTextView textView = FindViewById<AutoCompleteTextView> (Resource.Id.autocomplete_country);


var adapter = new ArrayAdapter<String> (this, Resource.Layout.list_item, COUNTRIES);

textView.Adapter = adapter;
}

Una vez que la vista de contenido se main.xml establece en el diseño, el AutoCompleteTextView widget se captura
desde el diseño con FindViewById . A continuación ArrayAdapter , se inicializa un nuevo para enlazar el
list_item.xml diseño a cada elemento de COUNTRIES lista de la matriz de cadenas (definido en el paso siguiente).
Por último SetAdapter() , se llama a para ArrayAdapter asociar el con el AutoCompleteTextView widget para que la
matriz de cadenas rellene la lista de sugerencias.
Dentro de MainActivity la clase, agregue la matriz de cadenas:
static string[] COUNTRIES = new string[] {
"Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra",
"Angola", "Anguilla", "Antarctica", "Antigua and Barbuda", "Argentina",
"Armenia", "Aruba", "Australia", "Austria", "Azerbaijan",
"Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium",
"Belize", "Benin", "Bermuda", "Bhutan", "Bolivia",
"Bosnia and Herzegovina", "Botswana", "Bouvet Island", "Brazil", "British Indian Ocean Territory",
"British Virgin Islands", "Brunei", "Bulgaria", "Burkina Faso", "Burundi",
"Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde",
"Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
"Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
"Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic",
"Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", "Dominican Republic",
"East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea",
"Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland",
"Former Yugoslav Republic of Macedonia", "France", "French Guiana", "French Polynesia",
"French Southern Territories", "Gabon", "Georgia", "Germany", "Ghana", "Gibraltar",
"Greece", "Greenland", "Grenada", "Guadeloupe", "Guam", "Guatemala", "Guinea", "Guinea-Bissau",
"Guyana", "Haiti", "Heard Island and McDonald Islands", "Honduras", "Hong Kong", "Hungary",
"Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland", "Israel", "Italy", "Jamaica",
"Japan", "Jordan", "Kazakhstan", "Kenya", "Kiribati", "Kuwait", "Kyrgyzstan", "Laos",
"Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg",
"Macau", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands",
"Martinique", "Mauritania", "Mauritius", "Mayotte", "Mexico", "Micronesia", "Moldova",
"Monaco", "Mongolia", "Montserrat", "Morocco", "Mozambique", "Myanmar", "Namibia",
"Nauru", "Nepal", "Netherlands", "Netherlands Antilles", "New Caledonia", "New Zealand",
"Nicaragua", "Niger", "Nigeria", "Niue", "Norfolk Island", "North Korea", "Northern Marianas",
"Norway", "Oman", "Pakistan", "Palau", "Panama", "Papua New Guinea", "Paraguay", "Peru",
"Philippines", "Pitcairn Islands", "Poland", "Portugal", "Puerto Rico", "Qatar",
"Reunion", "Romania", "Russia", "Rwanda", "Sqo Tome and Principe", "Saint Helena",
"Saint Kitts and Nevis", "Saint Lucia", "Saint Pierre and Miquelon",
"Saint Vincent and the Grenadines", "Samoa", "San Marino", "Saudi Arabia", "Senegal",
"Seychelles", "Sierra Leone", "Singapore", "Slovakia", "Slovenia", "Solomon Islands",
"Somalia", "South Africa", "South Georgia and the South Sandwich Islands", "South Korea",
"Spain", "Sri Lanka", "Sudan", "Suriname", "Svalbard and Jan Mayen", "Swaziland", "Sweden",
"Switzerland", "Syria", "Taiwan", "Tajikistan", "Tanzania", "Thailand", "The Bahamas",
"The Gambia", "Togo", "Tokelau", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey",
"Turkmenistan", "Turks and Caicos Islands", "Tuvalu", "Virgin Islands", "Uganda",
"Ukraine", "United Arab Emirates", "United Kingdom",
"United States", "United States Minor Outlying Islands", "Uruguay", "Uzbekistan",
"Vanuatu", "Vatican City", "Venezuela", "Vietnam", "Wallis and Futuna", "Western Sahara",
"Yemen", "Yugoslavia", "Zambia", "Zimbabwe"
};

Esta es la lista de sugerencias que se proporcionarán en una lista desplegable cuando el usuario escribe en el
AutoCompleteTextView widget.

Ejecute la aplicación. A medida que escribe, debería ver algo parecido a esto:
Más información
Tenga en cuenta que el uso de una matriz de cadenas codificadas de forma rígida no es una práctica de diseño
recomendada, ya que el código de la aplicación debe centrarse en el comportamiento, no en el contenido. El
contenido de la aplicación, como las cadenas, se debe externalizar desde el código para facilitar modificaciones en
el contenido y facilitar la localización del contenido. Las cadenas codificadas de forma rígida se usan en este
tutorial solo para simplificar y centrarse en el AutoCompleteTextView widget. En su lugar, la aplicación debe declarar
dichas matrices de cadenas en un archivo XML. Esto se puede hacer con un <string-array> recurso en el archivo
res/values/strings.xml del proyecto. Por ejemplo:

<?xml version="1.0" encoding="utf-8"?>


<resources>
<string-array name="countries_array">
<item>Bahrain</item>
<item>Bangladesh</item>
<item>Barbados</item>
<item>Belarus</item>
<item>Belgium</item>
<item>Belize</item>
<item>Benin</item>
</string-array>
</resources>

Para usar estas cadenas de recursos para ArrayAdapter , reemplace el original ArrayAdapter línea del constructor
con lo siguiente:

string[] countries = Resources.GetStringArray (Resource.array.countries_array);


var adapter = new ArrayAdapter<String> (this, Resource.layout.list_item, countries);

Referencias
Receta AutoCompleteTextView – Proyecto de ejemplo de Xamarin. Android para el AutoCompleteTextView
ArrayAdapter
AutoCompleteTextView

Algunas partes de esta página son modificaciones basadas en el trabajo creado y compartido por el proyecto de
código abierto de Android y que se usan según los términos descritos en la licencia de atribución de Creative
Commons 2,5. Este tutorial se basa en el tutorial de autocompletar de Android *.
Botones de Xamarin. Android
16/08/2019 • 2 minutes to read • Edit Online

La Button clase se usa para representar distintos estilos de botón en pantallas Android. En esta sección se
presentan las diferentes opciones para trabajar con botones en Xamarin. Android:
RadioButton permite al usuario seleccionar una opción de un conjunto.
ToggleButton permite al usuario voltear (alternar) una configuración entre dos Estados.
CheckBox es un tipo especial de botón que puede estar activado o desactivado para indicar uno de los dos
Estados posibles.
También puede crear un botón personalizado que use una imagen en lugar de texto.
RadioButton
27/07/2019 • 2 minutes to read • Edit Online

En esta sección, creará dos botones de radio mutuamente excluyentes (habilitando uno, se deshabilitará el otro)
mediante el RadioGroup etc RadioButton widgets. Cuando se presiona cualquiera de los botones de radio, se
mostrará un mensaje de notificación.
Abra el archivo Resources /layout/main. axml y RadioButton agregue dos objetos anidados en RadioGroup un
(dentro LinearLayout de):

<RadioGroup
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RadioButton android:id="@+id/radio_red"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Red" />
<RadioButton android:id="@+id/radio_blue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Blue" />
</RadioGroup>

Es importante que RadioButton los elementos estén agrupados por el RadioGroup elemento para que no se pueda
seleccionar más de uno a la vez. Esta lógica la controla automáticamente el sistema Android. Cuando uno
RadioButton dentro de un grupo seleccionado, todos los demás se anulan automáticamente.

Para hacer algo cuando se RadioButton selecciona cada uno, es necesario escribir un controlador de eventos:

private void RadioButtonClick (object sender, EventArgs e)


{
RadioButton rb = (RadioButton)sender;
Toast.MakeText (this, rb.Text, ToastLength.Short).Show ();
}

En primer lugar, el remitente que se pasa se convierte en un RadioButton. Después, un Toast mensaje muestra el
texto del botón de radio seleccionado.
Ahora, en la parte inferior del OnCreate() Agregue lo siguiente:

RadioButton radio_red = FindViewById<RadioButton>(Resource.Id.radio_red);


RadioButton radio_blue = FindViewById<RadioButton>(Resource.Id.radio_blue);

radio_red.Click += RadioButtonClick;
radio_blue.Click += RadioButtonClick;

Esto captura cada RadioButton s del diseño y agrega el controlador de eventos recién creado a cada uno de ellos.
Ejecute la aplicación.
TIP
Si necesita cambiar el estado (por ejemplo, al cargar un guardado CheckBoxPreference ), use el Checked establecedor de
propiedad o Toggle() .

Algunas partes de esta página son modificaciones basadas en el trabajo creado y compartido por el proyecto de
código abierto de Android y que se usan según los términos descritos en la licencia de atribución deCreative
Commons 2,5.
ToggleButton
27/07/2019 • 2 minutes to read • Edit Online

En esta sección, creará un botón que se usa específicamente para alternar entre dos Estados, mediante
ToggleButton el widget. Este widget es una alternativa excelente a los botones de radio si tiene dos Estados
simples que se excluyen mutuamente ("ON" y "OFF", por ejemplo). Android 4,0 (nivel de Switch API 14) presentó
una alternativa al botón de alternancia conocido como.
Un ejemplo de un control ToggleButton puede verse en el par izquierdo de imágenes, mientras que el par
derecho de imágenes presenta un ejemplo de un modificador:

El control que usa una aplicación es una cuestión de estilo. Ambos widgets son funcionalmente equivalentes.
Abra el archivo Resources /layout/main. axml y ToggleButton agregue el elemento ( LinearLayout dentro del):
Para hacer algo cuando se cambia el estado, agregue el código siguiente al final de la OnCreate() forma

ToggleButton togglebutton = FindViewById<ToggleButton>(Resource.Id.togglebutton);

togglebutton.Click += (o, e) => {


// Perform action on clicks
if (togglebutton.Checked)
Toast.MakeText(this, "Checked", ToastLength.Short).Show ();
else
Toast.MakeText(this, "Not checked", ToastLength.Short).Show ();
};

Esto captura el ToggleButton elemento del diseño y controla el evento de clic, que define la acción que se realizará
cuando se haga clic en el botón. En este ejemplo, el método comprueba el nuevo estado del botón y, a
continuación, Toast muestra un mensaje que indica el estado actual.
Tenga en cuenta ToggleButton que el controla su propio cambio de estado entre Checked y unchecked, por lo que
solo tiene que preguntar qué es.
Ejecute la aplicación.

TIP
Si necesita cambiar el estado (por ejemplo, al cargar un guardado CheckBoxPreference ), use el Checked establecedor de
propiedad o Toggle() .

Vínculos relacionados
ToggleButton
Switch
CheckBox
27/07/2019 • 2 minutes to read • Edit Online

En esta sección, creará una casilla para seleccionar elementos, mediante el CheckBox widget. Cuando se presiona la
casilla, un mensaje del sistema indicará el estado actual de la casilla.
Abra el archivo Resources /layout/main. axml y CheckBox agregue el elemento ( LinearLayout dentro del):

<CheckBox android:id="@+id/checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="check it out" />

Para hacer algo cuando se cambia el estado, agregue el código siguiente al final de la OnCreate() forma

CheckBox checkbox = FindViewById<CheckBox>(Resource.Id.checkbox);

checkbox.Click += (o, e) => {


if (checkbox.Checked)
Toast.MakeText (this, "Selected", ToastLength.Short).Show ();
else
Toast.MakeText (this, "Not selected", ToastLength.Short).Show ();
};

Esto captura el CheckBox del diseño y, a continuación, controla el evento click, que define la acción que se realizará
cuando se haga clic en la casilla. Al hacer clic en él, el Checked se llama a la propiedad para comprobar el nuevo
estado de la casilla. Si se ha activado, Toast muestra el mensaje "seleccionado"; en caso contrario, muestra "no
seleccionado". El CheckBox controla sus propios cambios de estado, por lo que solo necesita consultar el estado
actual.
Ejecútelo.

TIP
Si necesita cambiar el estado por su cuenta (por ejemplo, al cargar un CheckBoxPreference guardado, use el Checked
establecedor de propiedad o Toggle() .

Algunas partes de esta página son modificaciones basadas en el trabajo creado y compartido por el proyecto de
código abierto de Android y que se usan según los términos descritos en la licencia de atribución deCreative
Commons 2,5.
Botón personalizado
27/07/2019 • 4 minutes to read • Edit Online

En esta sección, creará un botón con una imagen personalizada en lugar de texto, con el Button widget y un
archivo XML que define tres imágenes diferentes que se usarán para los distintos Estados del botón. Cuando se
presiona el botón, se muestra un mensaje breve.
Haga clic con el botón derecho y descargue las tres imágenes siguientes y, a continuación, cópielos en el directorio
Resources /drawable del proyecto. Se usarán para los distintos Estados de botón.

Icono verde de Android para el icono de Android de estado de foco


Cree un nuevo archivo en el directorio Resources /Drawing llamado android_button. XML. Inserte el siguiente
código XML:

<?xml version="1.0" encoding="utf-8"?>


<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/android_pressed"
android:state_pressed="true" />
<item android:drawable="@drawable/android_focused"
android:state_focused="true" />
<item android:drawable="@drawable/android_normal" />
</selector>

Define un único recurso que se va a dibujar, que cambiará su imagen en función del estado actual del botón. El
primero <item> define android_pressed. png como la imagen cuando se presiona el botón (se activa); el
segundo <item> define android_focused. png como la imagen cuando el botón está enfocado (cuando el botón
es resaltado mediante el panel de control o la almohadilla direccional); y el tercero <item> define
android_normal. png como la imagen para el estado normal (cuando no se presiona ni se centra). Ahora, este
archivo XML representa un único recurso dibujable y, cuando se hace Button referencia a él en el fondo, la
imagen que se muestra cambiará en función de estos tres Estados.

NOTE
El orden de los <item> elementos es importante. Cuando se hace referencia a esta dibujable, <item> los s se recorren en
orden para determinar cuál es el adecuado para el estado actual del botón. Dado que la imagen "normal" es la última, solo se
aplica cuando las android:state_pressed condiciones android:state_focused y se evalúan como false.

Abra el archivo Resources /layout/main. axml y Button agregue el elemento:

<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:background="@drawable/android_button" />

El android:background atributo especifica el recurso de dibujo que se va a usar para el fondo del botón (que,
cuando se guarda en Resources /drawable/Android. XML, se hace referencia como @drawable/android ). Esto
reemplaza la imagen de fondo normal que se usa para los botones en todo el sistema. Para que el objeto drawable
cambie su imagen en función del estado del botón, la imagen debe aplicarse al fondo.
Para hacer que el botón haga algo cuando se presiona, agregue el código siguiente al final de la OnCreate() forma

Button button = FindViewById<Button>(Resource.Id.button);

button.Click += (o, e) => {


Toast.MakeText (this, "Beep Boop", ToastLength.Short).Show ();
};

Esto captura el Button del diseño y, a continuación, agrega Toast un mensaje Button que se mostrará cuando se
haga clic en.
Ahora ejecute la aplicación.
Algunas partes de esta página son modificaciones basadas en el trabajo creado y compartido por el proyecto de
código abierto de Android y que se usan según los términos descritos en la licencia de atribución deCreative
Commons 2,5.
Calendario de Xamarin. Android
16/08/2019 • 13 minutes to read • Edit Online

API de calendario
Un nuevo conjunto de API de calendario introducido en Android 4 es compatible con aplicaciones diseñadas para
leer o escribir datos en el proveedor de calendario. Estas API admiten una gran cantidad de opciones de
interacción con datos de calendario, incluida la capacidad de leer y escribir eventos, asistentes y recordatorios. Al
usar el proveedor de calendario en la aplicación, los datos que agregue a través de la API aparecerán en la
aplicación de calendario integrada que se incluye en Android 4.

Agregar permisos
Al trabajar con las nuevas API de calendario en la aplicación, lo primero que debe hacer es agregar los permisos
adecuados al manifiesto de Android. Los permisos que necesita agregar son android.permisson.READ_CALENDAR y
android.permission.WRITE_CALENDAR , dependiendo de si está leyendo o escribiendo datos de calendario.

Usar el contrato de calendario


Una vez establecidos los permisos, puede interactuar con los datos del calendario mediante la CalendarContract
clase. Esta clase proporciona un modelo de datos que las aplicaciones pueden usar cuando interactúan con el
proveedor de calendario. CalendarContract Permite a las aplicaciones resolver los URI para entidades de
calendario, como calendarios y eventos. También proporciona una manera de interactuar con varios campos de
cada entidad, como el nombre y el identificador de un calendario, o la fecha de inicio y finalización de un evento.
Echemos un vistazo a un ejemplo que usa la API Calendar. En este ejemplo, examinaremos cómo enumerar los
calendarios y sus eventos, además de cómo agregar un nuevo evento a un calendario.

Enumerar calendarios
En primer lugar, vamos a examinar cómo enumerar los calendarios que se han registrado en la aplicación de
calendario. Para ello, podemos crear una instancia de un CursorLoader . Introducida en Android 3,0 (API 11)
CursorLoader , es la manera preferida de ContentProvider consumir un. Como mínimo, es necesario especificar el
URI de contenido para los calendarios y las columnas que se van a devolver. Esta especificación de columna se
conoce como proyección.
Llamar al CursorLoader.LoadInBackground método nos permite consultar los datos de un proveedor de contenido,
como el proveedor de calendario. LoadInBackground realiza la operación de carga real y devuelve Cursor un con
los resultados de la consulta.
Nos ayuda a especificar tanto el contenido Uri como la proyección. CalendarContract Para obtener el contenido
Uri para consultar los calendarios, podemos usar simplemente la propiedad
CalendarContract.Calendars.ContentUri de la siguiente manera:

var calendarsUri = CalendarContract.Calendars.ContentUri;

CalendarContract Usar para especificar las columnas de calendario que queremos es igualmente simple. Solo se
agregan campos de CalendarContract.Calendars.InterfaceConsts la clase a una matriz. Por ejemplo, el código
siguiente incluye el identificador, el nombre para mostrar y el nombre de cuenta del calendario:
string[] calendarsProjection = {
CalendarContract.Calendars.InterfaceConsts.Id,
CalendarContract.Calendars.InterfaceConsts.CalendarDisplayName,
CalendarContract.Calendars.InterfaceConsts.AccountName
};

Es importante incluir si SimpleCursorAdapter usa para enlazar los datos a la interfaz de usuario, como veremos en
breve. Id Con el URI de contenido y la proyección en contexto, creamos CursorLoader una instancia de
CursorLoader.LoadInBackground y llamarán al método para devolver un cursor con los datos del calendario como se
muestra a continuación:

var loader = new CursorLoader(this, calendarsUri, calendarsProjection, null, null, null);


var cursor = (ICursor)loader.LoadInBackground();

La interfaz de usuario de este ejemplo ListView contiene un, con cada elemento de la lista que representa un solo
calendario. En el código XML siguiente se muestra el marcado ListView que incluye:

<?xml version="1.0" encoding="utf-8"?>


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ListView
android:id="@android:id/android:list"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>

Además, es necesario especificar la interfaz de usuario para cada elemento de lista, que se coloca en un archivo
XML independiente de la siguiente manera:

<?xml version="1.0" encoding="utf-8"?>


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView android:id="@+id/calDisplayName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16dip" />
<TextView android:id="@+id/calAccountName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="12dip" />
</LinearLayout>

A partir de este punto, es solo código de Android normal para enlazar los datos del cursor a la interfaz de usuario.
Usaremos como se SimpleCursorAdapter indica a continuación:
string[] sourceColumns = {
CalendarContract.Calendars.InterfaceConsts.CalendarDisplayName,
CalendarContract.Calendars.InterfaceConsts.AccountName };

int[] targetResources = {
Resource.Id.calDisplayName, Resource.Id.calAccountName };

SimpleCursorAdapter adapter = new SimpleCursorAdapter (this,


Resource.Layout.CalListItem, cursor, sourceColumns, targetResources);

ListAdapter = adapter;

En el código anterior, el adaptador toma las columnas especificadas en sourceColumns la matriz y las escribe en los
elementos de la interfaz targetResources de usuario de la matriz para cada entrada de calendario del cursor. La
actividad utilizada aquí es una subclase de ListActivity ; incluye la ListAdapter propiedad en la que se establece
el adaptador.
Esta es una captura de pantalla que muestra el resultado final, con la información del ListView calendario que se
muestra en la:

Enumerar eventos de calendario


A continuación, veamos cómo enumerar los eventos de un calendario determinado. Basándose en el ejemplo
anterior, se presentará una lista de eventos cuando el usuario seleccione uno de los calendarios. Por lo tanto, es
necesario controlar la selección del elemento en el código anterior:

ListView.ItemClick += (sender, e) => {


int i = (e as ItemEventArgs).Position;

cursor.MoveToPosition(i);
int calId =
cursor.GetInt (cursor.GetColumnIndex (calendarsProjection [0]));

var showEvents = new Intent(this, typeof(EventListActivity));


showEvents.PutExtra("calId", calId);
StartActivity(showEvents);
};

En este código, vamos a crear una intención de abrir una actividad de tipo EventListActivity , pasando el
identificador del calendario en el intento. Necesitaremos el identificador para saber en qué calendario se deben
consultar los eventos. En el EventListActivity método OnCreate de, se puede Intent recuperar el identificador
de, como se muestra a continuación:

_calId = Intent.GetIntExtra ("calId", -1);

Ahora, vamos a consultar eventos para este identificador de calendario. El proceso de consulta de eventos es
similar a la forma en que hemos consultado una lista de calendarios anteriores, pero esta vez trabajaremos con
CalendarContract.Events la clase. En el código siguiente se crea una consulta para recuperar eventos:

var eventsUri = CalendarContract.Events.ContentUri;

string[] eventsProjection = {
CalendarContract.Events.InterfaceConsts.Id,
CalendarContract.Events.InterfaceConsts.Title,
CalendarContract.Events.InterfaceConsts.Dtstart
};

var loader = new CursorLoader(this, eventsUri, eventsProjection,


String.Format ("calendar_id={0}", _calId), null, "dtstart ASC");
var cursor = (ICursor)loader.LoadInBackground();

En este código, primero se obtiene el contenido Uri de los eventos de CalendarContract.Events.ContentUri la


propiedad. A continuación, se especifican las columnas de evento que se desean recuperar en la matriz
eventsProjection. Por último, se crea una CursorLoader instancia de con esta información y se llama
LoadInBackground al método del cargador Cursor para devolver un con los datos del evento.

Para mostrar los datos de evento en la interfaz de usuario, podemos usar el marcado y el código tal como hicimos
antes de mostrar la lista de calendarios. De nuevo, se SimpleCursorAdapter usa para enlazar los datos ListView a
un, tal y como se muestra en el código siguiente:
string[] sourceColumns = {
CalendarContract.Events.InterfaceConsts.Title,
CalendarContract.Events.InterfaceConsts.Dtstart };

int[] targetResources = {
Resource.Id.eventTitle,
Resource.Id.eventStartDate };

var adapter = new SimpleCursorAdapter (this, Resource.Layout.EventListItem,


cursor, sourceColumns, targetResources);

adapter.ViewBinder = new ViewBinder ();


ListAdapter = adapter;

La diferencia principal entre este código y el código que hemos usado antes para mostrar la lista de calendarios es
el uso ViewBinder de, que se establece en la línea:

adapter.ViewBinder = new ViewBinder ();

La ViewBinder clase nos permite controlar mejor cómo se enlazan los valores a las vistas. En este caso, se usa para
convertir la hora de inicio del evento de milisegundos a una cadena de fecha, como se muestra en la siguiente
implementación:

class ViewBinder : Java.Lang.Object, SimpleCursorAdapter.IViewBinder


{
public bool SetViewValue (View view, Android.Database.ICursor cursor,
int columnIndex)
{
if (columnIndex == 2) {
long ms = cursor.GetLong (columnIndex);

DateTime date = new DateTime (1970, 1, 1, 0, 0, 0,


DateTimeKind.Utc).AddMilliseconds (ms).ToLocalTime ();

TextView textView = (TextView)view;


textView.Text = date.ToLongDateString ();

return true;
}
return false;
}
}

Esto muestra una lista de eventos, como se muestra a continuación:


Agregar un evento de calendario
Hemos visto cómo leer los datos de calendario. Ahora veamos cómo agregar un evento a un calendario. Para que
esto funcione, asegúrese de incluir el android.permission.WRITE_CALENDAR permiso que hemos mencionado
anteriormente. Para agregar un evento a un calendario, haremos lo siguiente:
1. Cree una ContentValues instancia de.
2. Use las claves de CalendarContract.Events.InterfaceConsts la clase para rellenar la ContentValues instancia.
3. Establezca las zonas horarias para las horas de inicio y finalización del evento.
4. ContentResolver Utilice para insertar los datos de evento en el calendario.

En el código siguiente se muestran estos pasos:


ContentValues eventValues = new ContentValues ();

eventValues.Put (CalendarContract.Events.InterfaceConsts.CalendarId,
_calId);
eventValues.Put (CalendarContract.Events.InterfaceConsts.Title,
"Test Event from M4A");
eventValues.Put (CalendarContract.Events.InterfaceConsts.Description,
"This is an event created from Xamarin.Android");
eventValues.Put (CalendarContract.Events.InterfaceConsts.Dtstart,
GetDateTimeMS (2011, 12, 15, 10, 0));
eventValues.Put (CalendarContract.Events.InterfaceConsts.Dtend,
GetDateTimeMS (2011, 12, 15, 11, 0));

eventValues.Put(CalendarContract.Events.InterfaceConsts.EventTimezone,
"UTC");
eventValues.Put(CalendarContract.Events.InterfaceConsts.EventEndTimezone,
"UTC");

var uri = ContentResolver.Insert (CalendarContract.Events.ContentUri,


eventValues);

Tenga en cuenta que si no se establece la zona horaria, se producirá Java.Lang.IllegalArgumentException una


excepción de tipo. Dado que los valores de tiempo de evento deben expresarse en milisegundos desde la
GetDateTimeMS época, creamos un método (en EventListActivity ) para convertir nuestras especificaciones de
fecha en formato de milisegundos:

long GetDateTimeMS (int yr, int month, int day, int hr, int min)
{
Calendar c = Calendar.GetInstance (Java.Util.TimeZone.Default);

c.Set (Java.Util.CalendarField.DayOfMonth, 15);


c.Set (Java.Util.CalendarField.HourOfDay, hr);
c.Set (Java.Util.CalendarField.Minute, min);
c.Set (Java.Util.CalendarField.Month, Calendar.December);
c.Set (Java.Util.CalendarField.Year, 2011);

return c.TimeInMillis;
}

Si agregamos un botón a la interfaz de usuario de la lista de eventos y ejecutamos el código anterior en el


controlador de eventos Click del botón, el evento se agrega al calendario y se actualiza en la lista, como se muestra
a continuación:
Si se abre la aplicación de calendario, veremos que el evento también se escribe allí:
Como puede ver, Android permite un acceso eficaz y sencillo para recuperar y conservar datos de calendario, lo
que permite a las aplicaciones integrar sin problemas las capacidades del calendario.

Vínculos relacionados
Demo de calendario (ejemplo)
Presentación del bocadillo de helado
Plataforma Android 4,0
CardView de Xamarin. Android
16/08/2019 • 18 minutes to read • Edit Online

El widget CardView es un componente de interfaz de usuario que presenta el contenido de texto e imagen en las
vistas que se parecen a las tarjetas. En esta guía se explica cómo usar y personalizar CardView en aplicaciones
de Xamarin. Android, a la vez que se mantiene la compatibilidad con versiones anteriores de Android.

Información general
El Cardview widget, introducido en Android 5,0 (Lollipop), es un componente de interfaz de usuario que
presenta el contenido de texto e imagen en las vistas que se parecen a las tarjetas. CardView se implementa
como un FrameLayout widget con esquinas redondeadas y una sombra. Normalmente, CardView se usa para
presentar un elemento de una sola fila en ListView un GridView grupo de vistas o. Por ejemplo, la siguiente
captura de pantalla es un ejemplo de una aplicación de reserva de viajes CardView que implementa tarjetas de
destino de viaje basadas en ListView desplazable:

En esta guía se explica cómo agregar CardView el paquete al proyecto de Xamarin. Android, cómo agregarlo
CardView a su diseño y cómo personalizar la apariencia de CardView en la aplicación. Además, en esta guía se
proporciona una lista detallada CardView de los atributos que puede cambiar, incluidos los atributos que le
CardView ayudarán a usar en versiones de Android anteriores al círculo 5,0 de Android.

Requisitos
Lo siguiente es necesario para usar las nuevas características de Android 5,0 y versiones CardView posteriores
(incluido) en las aplicaciones basadas en Xamarin:
Xamarin. Android – Xamarin. Android 4,20 o posterior debe estar instalado y configurado con Visual
Studio o Visual Studio para Mac.
Android SDK – Android 5,0 (API 21) o posterior debe instalarse a través del administrador de Android
SDK.
Java JDK 1,8 – JDK 1,7 puede usarse si se trata de destino de nivel de API 23 y versiones anteriores. JDK
1,8 está disponible en Oracle.
La aplicación también debe incluir el Xamarin.Android.Support.v7.CardView paquete. Para agregar el
Xamarin.Android.Support.v7.CardView paquete en Visual Studio para Mac:
1. Abra el proyecto, haga clic con el botón derecho en paquetes y seleccione agregar paquetes.
2. En el cuadro de diálogo agregar paquetes , busque CardView.
3. Seleccione biblioteca de soporte de Xamarin V7 CardViewy haga clic en Agregar paquete.
Para agregar el Xamarin.Android.Support.v7.CardView paquete en Visual Studio:
1. Abra el proyecto, haga clic con el botón secundario en el nodo referencias (en el panel Explorador de
soluciones ) y seleccione administrar paquetes NuGet.. ..
2. Cuando se muestre el cuadro de diálogo administrar paquetes NuGet , escriba CardView en el cuadro
de búsqueda.
3. Cuando aparezca la biblioteca de compatibilidad de Xamarin V7 CardView , haga clic en instalar.
Para obtener información sobre cómo configurar un proyecto de aplicación de Android 5,0, consulte
configuración de un proyecto de android 5,0. Para obtener más información sobre la instalación de paquetes
NuGet, consulte Tutorial: Incluir un NuGet en el proyecto.

Introducción a CardView
El valor CardView predeterminado es similar a una tarjeta blanca con esquinas redondeadas mínimas y una
pequeña sombra. En el siguiente ejemplo de diseño Main. axml se CardView muestra un único TextView
widget que contiene:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center_horizontal"
android:padding="5dp">
<android.support.v7.widget.CardView
android:layout_width="fill_parent"
android:layout_height="245dp"
android:layout_gravity="center_horizontal">
<TextView
android:text="Basic CardView"
android:layout_marginTop="0dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:layout_centerVertical="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true" />
</android.support.v7.widget.CardView>
</LinearLayout>

Si usa este código XML para reemplazar el contenido existente de Main. axml, asegúrese de comentar
cualquier código de MainActivity.CS que haga referencia a los recursos del XML anterior.
En este ejemplo de diseño se CardView crea un valor predeterminado con una sola línea de texto, tal como se
muestra en la siguiente captura de pantalla:

En este ejemplo, el estilo de la aplicación se establece en el tema de Theme.Material.Light material claro ()


CardView para que las sombras y los bordes sean más fáciles de ver. Para obtener más información sobre cómo
crear aplicaciones para Android 5,0, consulte el tema material. En la siguiente sección, veremos cómo
personalizar CardView para una aplicación.

Personalizar CardView
Puede modificar los atributos básicos CardView para personalizar la apariencia CardView de en la aplicación. Por
ejemplo, la elevación de CardView se puede aumentar para convertir una sombra más grande (lo que hace que
la carta parezca flotar más arriba que el fondo). Además, el radio de esquina se puede aumentar para que las
esquinas de la tarjeta se redondeen más.
En el siguiente ejemplo de diseño, se CardView utiliza un personalizado para crear una simulación de una
fotografía de impresión (una "instantánea"). Se ImageView agrega un CardView al para mostrar TextView la
imagen y se coloca debajo ImageView de para mostrar el título de la imagen. En este diseño de ejemplo,
CardView el tiene las siguientes personalizaciones:

cardElevation Se aumenta a 4DP para convertir una sombra mayor.


cardCornerRadius Se aumenta a 5dp para que las esquinas aparezcan más redondeadas.

Dado CardView que se proporciona mediante la biblioteca de compatibilidad de Android V7, sus atributos no
están android: disponibles en el espacio de nombres. Por lo tanto, debe definir su propio espacio de nombres
XML y usar dicho CardView espacio de nombres como prefijo del atributo. En el ejemplo de diseño siguiente,
usaremos esta línea para definir un espacio de cardview nombres denominado:

xmlns:cardview="http://schemas.android.com/apk/res-auto"

Puede llamar a este espacio card_view de nombres myapp o incluso si elige (solo es accesible en el ámbito de
este archivo). Sea cual sea la opción que elija para llamar a este espacio de nombres, CardView debe usarlo para
prefijar el atributo que desea modificar. En este ejemplo de diseño, cardview el espacio de nombres es
cardElevation el cardCornerRadius prefijo para y:

<?xml version="1.0" encoding="utf-8"?>


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:cardview="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center_horizontal"
android:padding="5dp">
<android.support.v7.widget.CardView
android:layout_width="fill_parent"
android:layout_height="245dp"
android:layout_gravity="center_horizontal"
cardview:cardElevation="4dp"
cardview:cardCornerRadius="5dp">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="240dp"
android:orientation="vertical"
android:padding="8dp">
<ImageView
android:layout_width="fill_parent"
android:layout_height="190dp"
android:id="@+id/imageView"
android:scaleType="centerCrop" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#333333"
android:text="Photo Title"
android:id="@+id/textView"
android:layout_gravity="center_horizontal"
android:layout_marginLeft="5dp" />
</LinearLayout>
</android.support.v7.widget.CardView>
</LinearLayout>

Cuando este ejemplo de diseño se usa para mostrar una imagen en una aplicación de visualización fotográfica,
CardView tiene la apariencia de una instantánea de fotografía, como se muestra en la siguiente captura de
pantalla:

Esta captura de pantalla se toma de la aplicación de ejemplo RecyclerViewer , RecyclerView que usa un widget
para presentar una lista CardView desplazable de imágenes para ver las fotos. Para obtener más información
RecyclerView acerca de, consulte la guía de RecyclerView .

Tenga en cuenta CardView que puede mostrar más de una vista secundaria en su área de contenido. Por
ejemplo, en el ejemplo anterior de la aplicación de visualización de fotografías, el área de contenido ListView se
compone de ImageView un que TextView contiene un y un. Aunque CardView las instancias suelen estar
organizadas verticalmente, también puede organizarlas horizontalmente (vea crear un estilo de vista
personalizado para obtener una captura de pantalla de ejemplo).
Opciones de diseño CardView
CardView los diseños se pueden personalizar estableciendo uno o más atributos que afecten a su relleno,
elevación, radio de redondeo y color de fondo:

Cada atributo también se puede cambiar dinámicamente llamando a un método CardView homólogo (para
obtener más información CardView sobre los métodos, vea la referencia de la clase CardView ). Tenga en cuenta
que estos atributos (excepto el color de fondo) aceptan un valor de dimensión, que es un número decimal
seguido de la unidad. Por ejemplo, 11.5dp especifica 11,5 píxeles independientes de la densidad.
Relleno
CardView ofrece cinco atributos de relleno para colocar el contenido dentro de la tarjeta. Puede establecerlos en
el XML de diseño o puede llamar a métodos análogos en el código:

Los atributos de relleno se explican de la siguiente manera:


contentPadding Relleno interior entre las vistas secundarias CardView de y todos los bordes de la tarjeta. –
contentPaddingBottom Relleno interior entre las vistas secundarias CardView de y el borde inferior de la
tarjeta. –
contentPaddingLeft Relleno interior entre las vistas secundarias CardView de y el borde izquierdo de la
tarjeta. –
contentPaddingRight Relleno interior entre las vistas secundarias CardView de y el borde derecho de la
tarjeta. –
contentPaddingTop Relleno interior entre las vistas secundarias CardView de y el borde superior de la
tarjeta. –
Los atributos de relleno de contenido son relativos al límite del área de contenido en lugar de a cualquier widget
determinado ubicado en el área de contenido. Por ejemplo, si contentPadding se ha aumentado suficientemente
en la aplicación de visualización fotográfica CardView , recortaría tanto la imagen como el texto que se muestra
en la tarjeta.
Indicador
CardView ofrece dos atributos de elevación para controlar su elevación y, como resultado, el tamaño de su
sombra:
Los atributos de elevación se explican de la siguiente manera:
cardElevation – Elevación CardView de (representa su eje Z ).
cardMaxElevation Valor máximo de la CardView elevación de. –

Los valores más cardElevation grandes de aumentan el tamaño de CardView la sombra para que parezca flotar
más arriba encima del fondo. El cardElevation atributo también determina el orden de dibujo de las vistas
superpuestas; es CardView decir, se dibujará en otra vista superpuesta con una configuración de elevación
superior y encima de las vistas superpuestas con una configuración de elevación inferior. La cardMaxElevation
configuración es útil cuando la aplicación cambia la elevación – dinámicamente, lo que impide que la sombra se
extienda más allá del límite que se define con esta configuración.
Color de fondo y radio de esquina
CardView proporciona atributos que se pueden usar para controlar el radio de esquina y su color de fondo. Estas
dos propiedades permiten cambiar el estilo general del CardView :

Estos atributos se explican de la siguiente manera:


cardCornerRadius Radio de redondeo de todas las esquinas CardView de. –
cardBackgroundColor Color de fondo del. CardView –

En este diagrama, cardCornerRadius se establece en un 10dp redondeado y cardBackgroundColor se establece en


"#FFFFCC" (amarillo claro).

Compatibilidad
Puede usar CardView en versiones de Android anteriores a Android 5,0 Lollipop. Dado CardView que forma
parte de la biblioteca de compatibilidad de Android V7, CardView puede usar con Android 2,1 (nivel de API 7) y
versiones posteriores. Sin embargo, debe instalar el Xamarin.Android.Support.v7.CardView paquete tal y como se
describe en requisitosanteriores.
CardView exhibe un comportamiento ligeramente diferente en los dispositivos antes del círculo (nivel de API 21):
CardView usa una implementación de instantáneas mediante programación que agrega relleno adicional.
no recorta las vistas secundarias que forman
CardView CardView una intersección con las esquinas
redondeadas de.
Para ayudar a administrar estas diferencias de compatibilidad CardView , proporciona varios atributos
adicionales que puede configurar en el diseño:
cardPreventCornerOverlap Establezca este atributo en true para agregar relleno cuando la aplicación se
ejecuta en versiones anteriores de Android (nivel de API 20 y anteriores). – Esta configuración evita
CardView que el contenido se interseque con CardView las esquinas redondeadas.

cardUseCompatPadding Establezca este atributo en true para agregar relleno cuando la aplicación se
ejecuta en versiones de Android en o superior al nivel de API 21. – Si desea usar CardView en
dispositivos con un círculo anterior y hacer que tenga el mismo aspecto en el círculo (o en versiones
posteriores), establezca true este atributo en. Cuando este atributo está habilitado CardView , agrega
relleno adicional para dibujar sombras cuando se ejecuta en dispositivos con un círculo previo. Esto ayuda
a superar las diferencias en el relleno que se introducen cuando se aplican las implementaciones de
instantáneas de programación en el círculo previo.
Para obtener más información sobre cómo mantener la compatibilidad con versiones anteriores de Android, vea
mantener la compatibilidad.

Resumen
En esta guía se presentó CardView el nuevo widget incluido en Android 5,0 (Lollipop). Se ha demostrado la
CardView apariencia predeterminada y se ha explicado cómo personalizar CardView cambiando la elevación, el
redondeo de la esquina, el relleno de contenido y el color de fondo. En él se CardView enumeran los atributos de
diseño (con diagramas de referencia) y CardView se explica cómo usar en dispositivos Android anteriores a
Android 5,0 Lollipop. Para obtener más información CardView sobre, vea la referencia de la clase CardView.

Vínculos relacionados
RecyclerView (ejemplo)
Introducción al círculo
Referencia de la clase CardView
Editar texto de Xamarin. Android
19/08/2019 • 3 minutes to read • Edit Online

En esta sección, usará el widget EditText para crear un campo de texto para los datos proporcionados por el
usuario. Una vez que el texto se ha escrito en el campo, la tecla entrar mostrará el texto en un mensaje del sistema.
Abra Resources/layout/activity_main. axml y agregue el elemento EditText a un diseño contenedor. En el
ejemplo siguiente, activity_main. axml tiene un EditText que se ha agregado LinearLayout a un:

<?xml version="1.0" encoding="utf-8"?>


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="@+id/edittext"
android:layout_width="match_parent"
android:imeOptions="actionGo"
android:inputType="text"
android:layout_height="wrap_content" />
</LinearLayout>

En este ejemplo de código, EditText el android:imeOptions atributo se establece actionGo en. Esta configuración
cambia la acción de listo predeterminada a la acción Go para que al pulsar la tecla entrar se KeyPress
desencadene el controlador de entrada. (Normalmente, actionGo se usa para que la tecla entrar lleve al usuario al
destino de una dirección URL que se escribe).
Para controlar la entrada de texto del usuario, agregue el código siguiente al final del métodoOnCreate en
MainActivity.cs:

EditText edittext = FindViewById<EditText>(Resource.Id.edittext);


edittext.KeyPress += (object sender, View.KeyEventArgs e) => {
e.Handled = false;
if (e.Event.Action == KeyEventActions.Down && e.KeyCode == Keycode.Enter)
{
Toast.MakeText(this, edittext.Text, ToastLength.Short).Show();
e.Handled = true;
}
};

Además, agregue la siguiente using instrucción a la parte superior de MainActivity.CS si aún no está presente:

using Android.Views;

En este ejemplo de código se infla el elemento EditText del diseño y se agrega un controlador KeyPress que define
la acción que se debe realizar cuando se presiona una tecla mientras el widget tiene el foco. En este caso, el método
se define para que escuche la tecla entrar (al puntear) y, a continuación, mostrar un mensaje del sistema con el
texto que se ha escrito. Tenga en cuenta que la propiedad controlada siempre true debe ser si se ha controlado el
evento. Esto es necesario para evitar que el evento se propague (lo que daría lugar a un retorno de carro en el
campo de texto).
Ejecute la aplicación y escriba texto en el campo de texto. Al presionar la tecla entrar , la notificación del sistema se
mostrará como se muestra a la derecha:
Algunas partes de esta página son modificaciones basadas en el trabajo creado y compartido por el proyecto de
código abierto de Android y se usan según los términos descritos en el Licencia de atribución de Creative
Commons 2,5 . Este tutorial se basa en el tutorial de formularios de Android .

Vínculos relacionados
EditTextSample
Control de la galería de Xamarin. Android
16/08/2019 • 5 minutes to read • Edit Online

Gallery es un widget de diseño que se usa para mostrar los elementos en una lista de desplazamiento horizontal y
coloca la selección actual en el centro de la vista.

IMPORTANT
Este widget quedó en desuso en Android 4,1 (nivel de API 16).

En este tutorial, creará una galería de fotos y mostrará un mensaje de notificación cada vez que se seleccione un
elemento de la galería.
Una vez Main.axml establecido el diseño para la vista de contenido Gallery , se captura desde el diseño con
FindViewById . El Adapter a continuación, se utiliza la propiedad para establecer un ImageAdapter adaptador
personalizado () como el origen de todos los elementos que se van a mostrar en el dallery. ImageAdapter Se crea
en el paso siguiente.
Para hacer algo cuando se hace clic en un elemento de la galería, se suscribe un delegado anónimo a la ItemClick .
Muestra un Toast que muestra la posición de índice (basada en cero) del elemento seleccionado (en un escenario
real, la posición se podría usar para obtener la imagen de tamaño completo para otra tarea).
En primer lugar, hay algunas variables de miembro, incluida una matriz de identificadores que hacen referencia a
las imágenes guardadas en el directorio de recursos Dibujables (Resources /drawable).
A continuación se encuentra el constructor de clase, donde Context para una ImageAdapter instancia de se define y
se guarda en un campo local. A continuación, se implementan algunos métodos necesarios heredados de
BaseAdapter . El constructor y el Count la propiedad se explica por sí misma. Regla GetItem(int) debe devolver el
objeto real situado en la posición especificada en el adaptador, pero se omite en este ejemplo. Forma
GetItemId(int) debe devolver el ID. de fila del elemento, pero no es necesario aquí.

El método realiza el trabajo para aplicar una imagen a un ImageView que se incrustará en el Gallery En este
método, el miembro Context se usa para crear un nuevo ImageView . El ImageView se prepara aplicando una
imagen de la matriz local de recursos que se van a dibujar y estableciendo Gallery.LayoutParams alto y ancho de la
imagen, estableciendo la escala para que quepa el ImageView dimensiones y, por último, establecer el fondo para
usar el atributo con estilo adquirido en el constructor.
Vea ImageView.ScaleType para ver otras opciones de escalado de imágenes.

Tutorial
Inicie un nuevo proyecto denominado HelloGallery.
Busque algunas fotos que le gustaría usar o Descargue estas imágenes de ejemplo. Agregue los archivos de
imagen al directorio Resources /drawable del proyecto. En la ventana propiedades , establezca la acción de
compilación para cada en AndroidResource.
Abra Resources/layout/main. axml e inserte lo siguiente:

<?xml version="1.0" encoding="utf-8"?>


<Gallery xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/gallery"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>

Abra MainActivity.cs e inserte el código siguiente para el OnCreate() forma

protected override void OnCreate (Bundle bundle)


{
base.OnCreate (bundle);

// Set our view from the "main" layout resource


SetContentView (Resource.Layout.Main);

Gallery gallery = (Gallery) FindViewById<Gallery>(Resource.Id.gallery);

gallery.Adapter = new ImageAdapter (this);

gallery.ItemClick += delegate (object sender, Android.Widget.AdapterView.ItemClickEventArgs args) {


Toast.MakeText (this, args.Position.ToString (), ToastLength.Short).Show ();
};
}

Cree una nueva clase denominada ImageAdapter BaseAdapter subclases:


public class ImageAdapter : BaseAdapter
{
Context context;

public ImageAdapter (Context c)


{
context = c;
}

public override int Count { get { return thumbIds.Length; } }

public override Java.Lang.Object GetItem (int position)


{
return null;
}

public override long GetItemId (int position)


{
return 0;
}

// create a new ImageView for each item referenced by the Adapter


public override View GetView (int position, View convertView, ViewGroup parent)
{
ImageView i = new ImageView (context);

i.SetImageResource (thumbIds[position]);
i.LayoutParameters = new Gallery.LayoutParams (150, 100);
i.SetScaleType (ImageView.ScaleType.FitXy);

return i;
}

// references to our images


int[] thumbIds = {
Resource.Drawable.sample_1,
Resource.Drawable.sample_2,
Resource.Drawable.sample_3,
Resource.Drawable.sample_4,
Resource.Drawable.sample_5,
Resource.Drawable.sample_6,
Resource.Drawable.sample_7
};
}

Ejecute la aplicación. Debería ser similar a la captura de pantalla siguiente:


Referencias
BaseAdapter
Gallery
ImageView

Algunas partes de esta página son modificaciones basadas en el trabajo creado y compartido por el proyecto de
código abierto de Android y que se usan según los términos descritos en la licencia de atribución de Creative
Commons 2,5.
Barra de navegación de Xamarin. Android
16/08/2019 • 3 minutes to read • Edit Online

Android 4 presentó una nueva característica de interfaz de usuario del sistema denominada barra de navegación,
que proporciona controles de navegación en los dispositivos que no incluyen botones de hardware para Inicio,
atrásy menú. En la captura de pantalla siguiente se muestra la barra de navegación desde un dispositivo primo de
Nexus:

Hay disponibles varias nuevas marcas que controlan la visibilidad de la barra de navegación y sus controles, así
como la visibilidad de la barra del sistema que se presentó en Android 3. Las marcas se definen en la
Android.View.View clase y se enumeran a continuación:

SystemUiFlagVisible – Hace que la barra de navegación esté visible.


SystemUiFlagLowProfile – Atenúa los controles de la barra de navegación.
SystemUiFlagHideNavigation – Oculta la barra de navegación.

Estas marcas se pueden aplicar a cualquier vista de la jerarquía de vistas estableciendo la SystemUiVisibility
propiedad. Si varias vistas tienen esta propiedad establecida, el sistema las combina con una operación OR y las
aplica siempre que la ventana en la que se establecen las marcas conserva el foco. Al quitar una vista, también se
quitarán las marcas que haya establecido.
En el ejemplo siguiente se muestra una aplicación sencilla en la que al hacer clic SystemUiVisibility en cualquiera
de los botones cambia:

El código para cambiar el SystemUiVisibility establece la propiedad en un TextView controlador de eventos Click
de cada botón, como se muestra a continuación:
var tv = FindViewById<TextView> (Resource.Id.systemUiFlagTextView);
var lowProfileButton = FindViewById<Button>(Resource.Id.lowProfileButton);
var hideNavButton = FindViewById<Button> (Resource.Id.hideNavigation);
var visibleButton = FindViewById<Button> (Resource.Id.visibleButton);

lowProfileButton.Click += delegate {
tv.SystemUiVisibility =
(StatusBarVisibility)View.SystemUiFlagLowProfile;
};

hideNavButton.Click += delegate {
tv.SystemUiVisibility =
(StatusBarVisibility)View.SystemUiFlagHideNavigation;
};

visibleButton.Click += delegate {
tv.SystemUiVisibility = (StatusBarVisibility)View.SystemUiFlagVisible;
}

Además, un SystemUiVisibility cambio genera un SystemUiVisibilityChange evento. Al igual que si


SystemUiVisibility se establece la propiedad, se SystemUiVisibilityChange puede registrar un controlador para el
evento para cualquier vista de la jerarquía. Por ejemplo, el código siguiente usa la TextView instancia para
registrarse para el evento:

tv.SystemUiVisibilityChange +=
delegate(object sender, View.SystemUiVisibilityChangeEventArgs e) {
tv.Text = String.Format ("Visibility = {0}", e.Visibility);
};

Vínculos relacionados
SystemUIVisibilityDemo (sample)
Presentación del bocadillo de helado
Plataforma Android 4,0
Controles de selector para Xamarin. Android
30/07/2019 • 2 minutes to read • Edit Online

Los selectores son elementos de interfaz de usuario que permiten al usuario seleccionar una fecha o una hora
mediante los cuadros de diálogo proporcionados por Android:
Selector de fecha se usa para seleccionar una fecha (año, mes y día).
Selector de tiempo se usa para seleccionar una hora (hora, minuto y AM/PM ).
Selector de fecha de Android
27/07/2019 • 7 minutes to read • Edit Online

Información general
Hay ocasiones en las que un usuario debe introducir datos en una aplicación Android. Para ayudar con esto, el
marco de trabajo de DatePicker Android proporciona el DatePickerDialog widget y el. DatePicker Permite a los
usuarios seleccionar el año, el mes y el día en una interfaz coherente entre dispositivos y aplicaciones. Es una clase
auxiliar que encapsula el DatePicker en un cuadro de diálogo. DatePickerDialog
Las aplicaciones modernas DatePickerDialog DialogFragment de Android deben mostrar en. Esto permitirá que
una aplicación muestre el DatePicker como un cuadro de diálogo emergente o incrustado en una actividad.
Además, DialogFragment administrará el ciclo de vida y la presentación del cuadro de diálogo, lo que reduce la
cantidad de código que se debe implementar.
En esta guía se muestra cómo usar DatePickerDialog , encapsulado en un. DialogFragment La aplicación de
ejemplo mostrará el DatePickerDialog como un cuadro de diálogo modal cuando el usuario haga clic en un botón
de una actividad. Cuando el usuario establece la fecha, TextView se actualizará con la fecha seleccionada.

Requisitos
La aplicación de ejemplo de esta guía tiene como destino Android 4,1 (nivel de API). 16) o superior, pero es
aplicable a Android 3,0 (nivel de API 11 o superior). Es posible admitir versiones anteriores de Android con la
incorporación de la biblioteca de compatibilidad de Android V4 al proyecto y algunos cambios de código.

Usar DatePicker
Este ejemplo se extenderá DialogFragment . La subclase hospedará y mostrará un DatePickerDialog :
Cuando el usuario selecciona una fecha y hace clic en el botón Aceptar , DatePickerDialog el llamará al
IOnDateSetListener.OnDateSet método. El hospedaje DialogFragment implementa esta interfaz. Si el usuario hace
clic en el botón Cancelar , el fragmento y el cuadro de diálogo se descartarán por sí mismos.
Hay varias maneras DialogFragment en las que puede devolver la fecha seleccionada a la actividad de hospedaje:
1. Invocar un método o establecer una propiedad – La actividad puede proporcionar una propiedad o un
método específicamente para establecer este valor.
2. Generar un evento Puede definir un evento que se generará cuando OnDateSet se invoque. –
DialogFragment

3. Use un Action – puedeinvocar Action<DateTime> un para mostrar la fecha en la actividad. DialogFragment


La actividad proporcionará el Action<DateTime al crear instancias de DialogFragment . En este ejemplo se
utiliza la tercera técnica y se requiere que la actividad proporcione Action<DateTime> un a. DialogFragment
Extender DialogFragment
El primer paso para mostrar un DatePickerDialog es a la subclase DialogFragment y hacer que implemente la
IOnDateSetListener interfaz:

public class DatePickerFragment : DialogFragment,


DatePickerDialog.IOnDateSetListener
{
// TAG can be any string of your choice.
public static readonly string TAG = "X:" + typeof (DatePickerFragment).Name.ToUpper();

// Initialize this value to prevent NullReferenceExceptions.


Action<DateTime> _dateSelectedHandler = delegate { };

public static DatePickerFragment NewInstance(Action<DateTime> onDateSelected)


{
DatePickerFragment frag = new DatePickerFragment();
frag._dateSelectedHandler = onDateSelected;
return frag;
}

public override Dialog OnCreateDialog(Bundle savedInstanceState)


{
DateTime currently = DateTime.Now;
DatePickerDialog dialog = new DatePickerDialog(Activity,
this,
currently.Year,
currently.Month - 1,
currently.Day);
return dialog;
}

public void OnDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth)
{
// Note: monthOfYear is a value between 0 and 11, not 1 and 12!
DateTime selectedDate = new DateTime(year, monthOfYear + 1, dayOfMonth);
Log.Debug(TAG, selectedDate.ToLongDateString());
_dateSelectedHandler(selectedDate);
}
}

Se NewInstanceinvoca el método para crear una instancia de un DatePickerFragment nuevo. Este método toma un
Action<DateTime> que se invocará cuando el usuario haga clic en el botón Aceptar en el DatePickerDialog .

Cuando se va a mostrar el fragmento, Android llamará al método OnCreateDialog . Este método creará un nuevo
DatePickerDialog objeto e inicializarlo con la fecha actual y el objeto DatePickerFragment de devolución de llamada
(que es la instancia actual del).
NOTE
Tenga en cuenta que el valor del mes IOnDateSetListener.OnDateSet en el que se invoca está en el intervalo de 0 a 11, y
no de 1 a 12. El día del mes estará en el intervalo de 1 a 31 (según el mes seleccionado).

Mostrar el DatePickerFragment
Ahora que DialogFragment se ha implementado, en esta sección se examinará cómo usar el fragmento en una
actividad. En la aplicación de ejemplo que acompaña a esta guía, la actividad creará una DialogFragment instancia
del NewInstance mediante el Factory Method y, a DialogFragment.Show continuación, lo mostrará invocación. Como
parte de la creación de instancias DialogFragment de, la actividad pasa Action<DateTime> un, que mostrará la fecha
en una TextView que se hospeda en la actividad:

[Activity(Label = "@string/app_name", MainLauncher = true, Icon = "@drawable/icon")]


public class MainActivity : Activity
{
TextView _dateDisplay;
Button _dateSelectButton;

protected override void OnCreate(Bundle bundle)


{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);

_dateDisplay = FindViewById<TextView>(Resource.Id.date_display);
_dateSelectButton = FindViewById<Button>(Resource.Id.date_select_button);
_dateSelectButton.Click += DateSelect_OnClick;
}

void DateSelect_OnClick(object sender, EventArgs eventArgs)


{
DatePickerFragment frag = DatePickerFragment.NewInstance(delegate(DateTime time)
{
_dateDisplay.Text =
time.ToLongDateString();
});
frag.Show(FragmentManager, DatePickerFragment.TAG);
}
}

Resumen
En este ejemplo se describe cómo mostrar DatePicker un widget como un cuadro de diálogo modal emergente
como parte de una actividad de Android. Proporcionó una implementación de DialogFragment de ejemplo y
IOnDateSetListener explicó la interfaz. En este ejemplo también se muestra cómo DialogFragment puede
interactuar con la actividad del host para mostrar la fecha seleccionada.

Vínculos relacionados
DialogFragment
DatePicker
DatePickerDialog
DatePickerDialog.IOnDateSetListener
Seleccionar una fecha
Selector de tiempo de Android
19/08/2019 • 13 minutes to read • Edit Online

Para proporcionar una manera para que el usuario seleccione una hora, puede usar TimePicker. Las aplicaciones
de Android TimePicker suelen usar con TimePickerDialog para seleccionar un – valor de tiempo, lo que ayuda a
garantizar una interfaz coherente entre dispositivos y aplicaciones. TimePicker permite a los usuarios seleccionar
la hora del día en el modo de 24 horas o de 12 horas. TimePickerDialog es una clase auxiliar que encapsula el
TimePicker en un cuadro de diálogo.
Información general
Las aplicaciones modernas de Android TimePickerDialog muestran el en un DialogFragment. Esto hace posible
que una aplicación muestre el TimePicker como un cuadro de diálogo emergente o lo inserte en una actividad.
Además, DialogFragment administra el ciclo de vida y la presentación del cuadro de diálogo, lo que reduce la
cantidad de código que se debe implementar.
En esta guía se muestra cómo usar TimePickerDialog , encapsulado en DialogFragment un. La aplicación de
ejemplo muestra TimePickerDialog como un cuadro de diálogo modal cuando el usuario hace clic en un botón de
una actividad. Cuando el usuario establece la hora, el cuadro de diálogo se cierra y un controlador actualiza
TextView en la pantalla de actividad con el tiempo seleccionado.

Requisitos
La aplicación de ejemplo de esta guía tiene como destino Android 4,1 (nivel de API). 16) o superior, pero se puede
usar con Android 3,0 (nivel de API 11 o superior). Es posible admitir versiones anteriores de Android con la
incorporación de la biblioteca de compatibilidad de Android V4 al proyecto y algunos cambios de código.

Usar el TimePicker
Este ejemplo extiende DialogFragment ; la implementación de subclases de TimePickerFragment DialogFragment (a
la que se llama TimePickerDialog a continuación) hospeda y muestra un. Cuando se inicia la aplicación de ejemplo
por primera vez, se muestra un botón de TextView hora de picking encima de un que se usará para mostrar la
hora seleccionada:

Al hacer clic en el botón de hora de selección , en la TimePickerDialog aplicación de ejemplo se inicia el tal como
aparece en esta captura de pantalla:
En, si selecciona una hora y hace clic en el botón Aceptar TimePickerDialog , el invocará el método
IOnTimeSetListener. OnTimeSet. TimePickerDialog Esta interfaz se implementa mediante el hospedaje
DialogFragment ( TimePickerFragment , que se describe a continuación). Al hacer clic en el botón Cancelar , se
descartan el fragmento y el cuadro de diálogo.
DialogFragment Devuelve la hora seleccionada a la actividad de hospedaje de una de estas tres maneras:
1. Invocar un método o establecer una propiedad – La actividad puede proporcionar una propiedad o un
método específicamente para establecer este valor.
2. Generar un evento Puede definir un evento que se generará cuando OnTimeSet se invoque. –
DialogFragment

3. Mediante, puede invocar un Action<DateTime> para mostrar la hora en la actividad. Action –


DialogFragment La actividad proporcionará el Action<DateTime al crear instancias de DialogFragment .

En este ejemplo se utiliza la tercera técnica, que requiere que la actividad proporcione Action<DateTime> un
controlador a. DialogFragment

Iniciar un proyecto de aplicación


Inicie un nuevo proyecto de Android llamado TimePickerDemo (si no está familiarizado con la creación de
proyectos de Xamarin. Android, consulte Hello, Android para obtener información sobre cómo crear un nuevo
proyecto).
Edite Resources /layout/main. axml y reemplace su contenido por el siguiente código XML:

<?xml version="1.0" encoding="utf-8"?>


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:padding="16dp">
<Button
android:id="@+id/select_button"
android:paddingLeft="24dp"
android:paddingRight="24dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="PICK TIME"
android:textSize="20dp" />
<TextView
android:id="@+id/time_display"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:paddingTop="22dp"
android:text="Picked time will be displayed here"
android:textSize="24dp" />
</LinearLayout>

Se trata de un LinearLayout básico con una TextView que muestra la hora y un botón que abre TimePickerDialog .
Tenga en cuenta que este diseño utiliza cadenas y dimensiones codificadas de forma rígida para que la aplicación
sea más sencilla – y más fácil de entender. normalmente, una aplicación de producción usa recursos para estos
valores (como se puede ver en el ejemplo de código DatePicker ).
Edite MainActivity.CS y reemplace su contenido por el código siguiente:
using Android.App;
using Android.Widget;
using Android.OS;
using System;
using Android.Util;
using Android.Text.Format;

namespace TimePickerDemo
{
[Activity(Label = "TimePickerDemo", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{
TextView timeDisplay;
Button timeSelectButton;

protected override void OnCreate(Bundle bundle)


{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
timeDisplay = FindViewById<TextView>(Resource.Id.time_display);
timeSelectButton = FindViewById<Button>(Resource.Id.select_button);
}
}
}

Al compilar y ejecutar este ejemplo, debería ver una pantalla inicial similar a la siguiente captura de pantalla:

Al hacer clic en el botón de hora de DialogFragment selección no se hace nada porque aún no TimePicker se ha
implementado para mostrar. El siguiente paso es crear este DialogFragment .

Extender DialogFragment
Para extender DialogFragment para su uso TimePicker con, es necesario crear una subclase
TimePickerDialog.IOnTimeSetListener derivada de DialogFragment e implementa. Agregue la siguiente clase a
MainActivity.CS:

public class TimePickerFragment : DialogFragment, TimePickerDialog.IOnTimeSetListener


{
public static readonly string TAG = "MyTimePickerFragment";
Action<DateTime> timeSelectedHandler = delegate { };

public static TimePickerFragment NewInstance(Action<DateTime> onTimeSelected)


{
TimePickerFragment frag = new TimePickerFragment();
frag.timeSelectedHandler = onTimeSelected;
return frag;
}

public override Dialog OnCreateDialog (Bundle savedInstanceState)


{
DateTime currentTime = DateTime.Now;
bool is24HourFormat = DateFormat.Is24HourFormat(Activity);
TimePickerDialog dialog = new TimePickerDialog
(Activity, this, currentTime.Hour, currentTime.Minute, is24HourFormat);
return dialog;
}

public void OnTimeSet(TimePicker view, int hourOfDay, int minute)


{
DateTime currentTime = DateTime.Now;
DateTime selectedTime = new DateTime(currentTime.Year, currentTime.Month, currentTime.Day, hourOfDay,
minute, 0);
Log.Debug(TAG, selectedTime.ToLongTimeString());
timeSelectedHandler (selectedTime);
}
}

Esta TimePickerFragment clase se divide en partes más pequeñas y se explica en la sección siguiente.
Implementación de DialogFragment
TimePickerFragment implementa varios métodos: un Factory Method, un método de creación de instancias de
diálogo y OnTimeSet el método de controlador TimePickerDialog.IOnTimeSetListener que requiere.
TimePickerFragment es una subclase de DialogFragment . También implementa la
TimePickerDialog.IOnTimeSetListener interfaz (es decir, proporciona el método necesario OnTimeSet ):

public class TimePickerFragment : DialogFragment, TimePickerDialog.IOnTimeSetListener

TAG se inicializa con fines de registro (MyTimePickerFragment se puede cambiar a cualquier cadena que
desee usar). La timeSelectedHandler acción se inicializa en un delegado vacío para evitar excepciones de
referencia nulas:

public static readonly string TAG = "MyTimePickerFragment";


Action<DateTime> timeSelectedHandler = delegate { };

Se llama al TimePickerFragment FactoryMethodparacrearunainstancia NewInstance de un nuevo. Este


método toma un Action<DateTime> controlador que se invoca cuando el usuario hace clic en el botón
Aceptar en el TimePickerDialog :
public static TimePickerFragment NewInstance(Action<DateTime> onTimeSelected)
{
TimePickerFragment frag = new TimePickerFragment();
frag.timeSelectedHandler = onTimeSelected;
return frag;
}

Cuando se va a mostrar el fragmento, Android llama al DialogFragment método OnCreateDialog. Este


método crea un nuevo TimePickerDialog objeto y lo inicializa con la actividad, el objeto de devolución
TimePickerFragment de llamada (que es la instancia actual de) y la hora actual:

public override Dialog OnCreateDialog (Bundle savedInstanceState)


{
DateTime currentTime = DateTime.Now;
bool is24HourFormat = DateFormat.Is24HourFormat(Activity);
TimePickerDialog dialog = new TimePickerDialog
(Activity, this, currentTime.Hour, currentTime.Minute, is24HourFormat);
return dialog;
}

Cuando el usuario cambia la configuración de hora en TimePicker el cuadro de OnTimeSet diálogo, se


invoca el método. OnTimeSet crea un DateTime objeto con la fecha actual y se combina en la hora (hora y
minuto) seleccionada por el usuario:

public void OnTimeSet(TimePicker view, int hourOfDay, int minute)


{
DateTime currentTime = DateTime.Now;
DateTime selectedTime = new DateTime(currentTime.Year, currentTime.Month, currentTime.Day,
hourOfDay, minute, 0);

Este DateTime objeto se pasa a la timeSelectedHandler que se registra con el TimePickerFragment objeto en
el momento de su creación. OnTimeSet invoca este controlador para actualizar la presentación de la hora de
la actividad a la hora seleccionada (este controlador se implementa en la sección siguiente):

timeSelectedHandler (selectedTime);

Mostrar el TimePickerFragment
Ahora que DialogFragment se ha implementado, es el momento de crear una instancia DialogFragment del
mediante NewInstance el Factory Method y mostrarlo mediante la invocación de DialogFragment. show:
Agregue el método siguiente a MainActivity :

void TimeSelectOnClick (object sender, EventArgs eventArgs)


{
TimePickerFragment frag = TimePickerFragment.NewInstance (
delegate (DateTime time)
{
timeDisplay.Text = time.ToShortTimeString();
});

frag.Show(FragmentManager, TimePickerFragment.TAG);
}

Después TimeSelectOnClick de crear una TimePickerFragment instancia de, se crea y pasa un delegado para un
método anónimo que actualiza la presentación de la hora de la actividad con el valor de tiempo pasado. Por
último, inicia el TimePicker fragmento de diálogo ( DialogFragment.Show Via) para mostrar TimePicker al usuario.
Al final del OnCreate método, agregue la siguiente línea para adjuntar el controlador de eventos al botón de hora
de selección que inicia el cuadro de diálogo:

timeSelectButton.Click += TimeSelectOnClick;

Cuando se haga clic en el botón de hora TimeSelectOnClick de selección , se invocará para TimePicker mostrar el
fragmento de diálogo al usuario.

¡Inténtelo!
Compile y ejecute la aplicación. Al hacer clic en el botón elegir hora , TimePickerDialog se muestra en el formato
de hora predeterminado de la actividad (en este caso, el modo de 12 horas AM/PM ):
Al hacer clic en Aceptar en TimePicker el cuadro de diálogo, el controlador TextView actualiza la actividad con la
hora seleccionada y, a continuación, se cierra:
Después, agregue la siguiente línea de código a OnCreateDialog inmediatamente después is24HourFormat de que
se declare e inicialice:

is24HourFormat = true;

Este cambio obliga a que la marca pasada TimePickerDialog al constructor sea true para que se utilice el modo
de 24 horas en lugar del formato de hora de la actividad de hospedaje. Al compilar y ejecutar la aplicación de
nuevo, haga clic en el botón TimePicker de hora de selección , el cuadro de diálogo se muestra ahora en formato
de 24 horas:
Dado que el controlador llama a DateTime. ToShortTimeString para imprimir la hora en la TextView de la
actividad, la hora se sigue imprimiendo en el formato predeterminado de 12 horas AM/PM.

Resumen
En este artículo se ha explicado TimePicker cómo mostrar un widget como un cuadro de diálogo modal
emergente desde una actividad de Android. Proporcionó una implementación DialogFragment de ejemplo y
explicó IOnTimeSetListener la interfaz. En este ejemplo también se muestra DialogFragment cómo puede
interactuar con la actividad del host para mostrar la hora seleccionada.

Vínculos relacionados
DialogFragment
TimePicker
TimePickerDialog
TimePickerDialog.IOnTimeSetListener
TimePickerDemo (ejemplo)
Menú emergente de Xamarin. Android
31/07/2019 • 3 minutes to read • Edit Online

El menú desacoplado (también denominado menú contextual) es un menú delimitado a una vista determinada. En
el ejemplo siguiente, una sola actividad contiene un botón. Cuando el usuario pulsa el botón, se muestra un menú
emergente de tres elementos:

Crear un menú emergente


El primer paso es crear un archivo de recursos de menú para el menú y colocarlo en recursos/menú. Por ejemplo,
el siguiente XML es el código para el menú de tres elementos que se muestra en la captura de pantalla anterior,
Resources /Menu/popup_menu. XML:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/item1"
android:title="item 1" />
<item android:id="@+id/item1"
android:title="item 2" />
<item android:id="@+id/item1"
android:title="item 3" />
</menu>

A continuación, cree una instancia PopupMenu de y delimite a su vista. Cuando se crea una instancia de PopupMenu ,
se pasa a su constructor una referencia Context a y a la vista a la que se adjuntará el menú. Como resultado, el
menú emergente se delimita en esta vista durante su construcción.
En el ejemplo siguiente, PopupMenu se crea en el controlador de eventos click para el botón (que se denomina
showPopupMenu ). Este botón también es la vista a la que PopupMenu está anclada, tal como se muestra en el ejemplo
de código siguiente:

showPopupMenu.Click += (s, arg) => {


PopupMenu menu = new PopupMenu (this, showPopupMenu);
};

Por último, el menú emergente debe estar inflado con el recurso de menú que se creó anteriormente. En el
ejemplo siguiente, se agrega la llamada al método Inflate del menú y se llama a su método Show para mostrarlo:

showPopupMenu.Click += (s, arg) => {


PopupMenu menu = new PopupMenu (this, showPopupMenu);
menu.Inflate (Resource.Menu.popup_menu);
menu.Show ();
};

Control de eventos de menú


Cuando el usuario selecciona un elemento de menú, se genera el evento click de MenuItemClick y se descarta el
menú. Al puntear en cualquier lugar fuera del menú simplemente se descartará. En cualquier caso, cuando se
descarta el menú, se generará su DismissEvent . En el código siguiente se agregan controladores de eventos
MenuItemClick para DismissEvent los eventos y:

showPopupMenu.Click += (s, arg) => {


PopupMenu menu = new PopupMenu (this, showPopupMenu);
menu.Inflate (Resource.Menu.popup_menu);

menu.MenuItemClick += (s1, arg1) => {


Console.WriteLine ("{0} selected", arg1.Item.TitleFormatted);
};

menu.DismissEvent += (s2, arg2) => {


Console.WriteLine ("menu dismissed");
};
menu.Show ();
};

Vínculos relacionados
PopupMenuDemo (ejemplo)
RatingBar de Xamarin. Android
16/08/2019 • 2 minutes to read • Edit Online

Un RatingBar es un widget de interfaz de usuario que muestra una clasificación de una a cinco estrellas. El usuario
puede seleccionar una clasificación por punteando en una estrella en esta sección, creará un widget que permite al
usuario proporcionar una clasificación con el RatingBar widget.

Creación de un RatingBar
1. Abra el archivo Resource/layout/main. axml y agregue el RatingBar elemento (dentro del LinearLayout ):

<RatingBar android:id="@+id/ratingbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:numStars="5"
android:stepSize="1.0"/>

El android:numStars atributo define el número de estrellas que se van a mostrar para la barra de
clasificación. El android:stepSize atributo define la granularidad de cada estrella (por ejemplo, un valor de
0.5 permitiría clasificaciones de mitad de estrella).

2. Para hacer algo cuando se ha establecido una nueva clasificación, agregue el código siguiente al final de la
OnCreate() forma

RatingBar ratingbar = FindViewById<RatingBar>(Resource.Id.ratingbar);

ratingbar.RatingBarChange += (o, e) => {


Toast.MakeText(this, "New Rating: " + ratingbar.Rating.ToString (), ToastLength.Short).Show ();
};

Esto captura el RatingBar widget del diseño con FindViewById y, a continuación, establece un método de
evento y, a continuación, define la acción que se realizará cuando el usuario establezca una clasificación. En
este caso, un mensaje Toast simple muestra la nueva clasificación.
3. Ejecute la aplicación.
Número de Xamarin. Android
27/07/2019 • 7 minutes to read • Edit Online

Spinner es un widget que presenta una lista desplegable para seleccionar elementos. En esta guía se explica cómo
crear una aplicación sencilla que muestre una lista de opciones en un control de número, seguida de
modificaciones que muestran otros valores asociados a la opción seleccionada.

Control de número básico


En la primera parte de este tutorial, creará un widget de número simple que muestra una lista de planetas. Cuando
se selecciona un planeta, un mensaje de notificación de sistema muestra el elemento seleccionado:

Inicie un nuevo proyecto denominado HelloSpinner.


Abra Resources/layout/main. axml e inserte el siguiente código XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:padding="10dip"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dip"
android:text="@string/planet_prompt"
/>
<Spinner
android:id="@+id/spinner"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:prompt="@string/planet_prompt"
/>
</LinearLayout>

Observe que el TextView atributo android:text de y el Spinner atributo android:prompt de hacen referencia al
mismo recurso de cadena. Este texto se comporta como título del widget. Cuando se aplica a Spinner , el texto del
título aparecerá en el cuadro de diálogo de selección que aparece al seleccionar el widget.
Edite Resources /Values/Strings. XML y modifique el archivo para que tenga el siguiente aspecto:

<?xml version="1.0" encoding="utf-8"?>


<resources>
<string name="app_name">HelloSpinner</string>
<string name="planet_prompt">Choose a planet</string>
<string-array name="planets_array">
<item>Mercury</item>
<item>Venus</item>
<item>Earth</item>
<item>Mars</item>
<item>Jupiter</item>
<item>Saturn</item>
<item>Uranus</item>
<item>Neptune</item>
</string-array>
</resources>

El segundo <string> elemento define la cadena de título TextView a la que hace Spinner referencia y en el
diseño anterior. El <string-array> elemento define la lista de cadenas que se mostrarán como lista en el Spinner
widget.
Ahora Abra MainActivity.CS y agregue la siguiente using instrucción:

using System;

A continuación, inserte el siguiente código para OnCreate() el método):


protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);

// Set our view from the "Main" layout resource


SetContentView (Resource.Layout.Main);

Spinner spinner = FindViewById<Spinner> (Resource.Id.spinner);

spinner.ItemSelected += new EventHandler<AdapterView.ItemSelectedEventArgs> (spinner_ItemSelected);


var adapter = ArrayAdapter.CreateFromResource (
this, Resource.Array.planets_array, Android.Resource.Layout.SimpleSpinnerItem);

adapter.SetDropDownViewResource (Android.Resource.Layout.SimpleSpinnerDropDownItem);
spinner.Adapter = adapter;
}

Una vez Main.axml establecido el diseño como la vista de contenido, Spinner el widget se captura desde el diseño
FindViewById<>(int) con. El CreateFromResource() a continuación, crea un ArrayAdapter nuevo, que enlaza cada
elemento de la matriz de cadenas con la apariencia inicial Spinner de (que es cómo aparecerá cada elemento en el
control de número cuando se selecciona). El Resource.Array.planets_array identificador hace referencia
string-array a la definición anterior Android.Resource.Layout.SimpleSpinnerItem y el identificador hace referencia
a un diseño de la apariencia del control de número estándar, definido por la plataforma. SetDropDownViewResource
se llama a para definir la apariencia de cada elemento cuando se abre el widget. Por último, ArrayAdapter se
establece para asociar todos sus elementos Spinner al estableciendo la Adapter propiedad.
Ahora proporcione un método de devolución de llamada que notifique a la aplicación cuando se ha seleccionado
un Spinner elemento de. Este método debería ser similar al siguiente:

private void spinner_ItemSelected (object sender, AdapterView.ItemSelectedEventArgs e)


{
Spinner spinner = (Spinner)sender;
string toast = string.Format ("The planet is {0}", spinner.GetItemAtPosition (e.Position));
Toast.MakeText (this, toast, ToastLength.Long).Show ();
}

Cuando se selecciona un elemento, el remitente se convierte en un Spinner para que se pueda tener acceso a los
elementos. Mediante el Position uso de la ItemEventArgs propiedad en, puede averiguar el texto del objeto
seleccionado y usarlo para mostrar un Toast .
Ejecutar la aplicación; debería tener este aspecto:
Control de número mediante pares clave-valor
A menudo es necesario usar Spinner para mostrar los valores de clave asociados a algún tipo de datos que usa la
aplicación. Dado Spinner que no funciona directamente con pares clave-valor, debe almacenar el par clave-valor
por separado, rellenar Spinner los valores de clave y, a continuación, usar la posición de la clave seleccionada en el
control de número para buscar el valor de datos asociado.
En los pasos siguientes, la aplicación HelloSpinner se modifica para mostrar la temperatura media del planeta
seleccionado:
Agregue la siguiente using instrucción a MainActivity.CS:
using System.Collections.Generic;

Agregue la siguiente variable de instancia a MainActivity la clase. Esta lista contendrá pares clave-valor para los
planetas y las temperaturas medias:

private List<KeyValuePair<string, string>> planets;

En el OnCreate método, agregue el código siguiente antes adapter de que se declare:

planets = new List<KeyValuePair<string, string>>


{
new KeyValuePair<string, string>("Mercury", "167 degrees C"),
new KeyValuePair<string, string>("Venus", "464 degrees C"),
new KeyValuePair<string, string>("Earth", "15 degrees C"),
new KeyValuePair<string, string>("Mars", "-65 degrees C"),
new KeyValuePair<string, string>("Jupiter" , "-110 degrees C"),
new KeyValuePair<string, string>("Saturn", "-140 degrees C"),
new KeyValuePair<string, string>("Uranus", "-195 degrees C"),
new KeyValuePair<string, string>("Neptune", "-200 degrees C")
};

Este código crea un almacén simple para los planetas y sus temperaturas medias asociadas. (En una aplicación real,
una base de datos se usa normalmente para almacenar claves y sus datos asociados).
Inmediatamente después del código anterior, agregue las líneas siguientes para extraer las claves y colocarlas en
una lista (en orden):

List<string> planetNames = new List<string>();


foreach (var item in planets)
planetNames.Add (item.Key);

Pase esta lista al ArrayAdapter constructor (en lugar planets_array del recurso):

var adapter = new ArrayAdapter<string>(this,


Android.Resource.Layout.SimpleSpinnerItem, planetNames);

Modifique spinner_ItemSelected para que la posición seleccionada se use para buscar el valor (la temperatura)
asociada al planeta seleccionado:

private void spinner_ItemSelected(object sender, AdapterView.ItemSelectedEventArgs e)


{
Spinner spinner = (Spinner)sender;
string toast = string.Format("The mean temperature for planet {0} is {1}",
spinner.GetItemAtPosition(e.Position), planets[e.Position].Value);
Toast.MakeText(this, toast, ToastLength.Long).Show();
}

Ejecutar la aplicación; la notificación del sistema debe tener el siguiente aspecto:


Recursos
Resource.Layout
ArrayAdapter
Spinner

Algunas partes de esta página son modificaciones basadas en el trabajo creado y compartido por el proyecto de
código abierto de Android y que se usan según los términos descritos en la licencia de atribución deCreative
Commons 2,5.
Conmutador Xamarin. Android
31/07/2019 • 2 minutes to read • Edit Online

El Switch widget (que se muestra a continuación) permite que un usuario alterne entre dos Estados, como
activado o desactivado. El Switch valor predeterminado es OFF. El widget se muestra a continuación en los
Estados activado y desactivado:

Crear un modificador
Para crear un modificador, simplemente declare un Switch elemento en XML como se indica a continuación:

<Switch android:layout_width="wrap_content"
android:layout_height="wrap_content" />

Esto crea un modificador básico, como se muestra a continuación:


Cambiar valores predeterminados
El texto que el control muestra para los Estados ON y OFF y el valor predeterminado son configurables. Por
ejemplo, para que el modificador sea on y Read no/Yes en lugar de OFF/ON, se pueden establecer los checked
atributos textOn , y textOff en el código XML siguiente.

<Switch android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:textOn="YES"
android:textOff="NO" />

Proporcionar un título
El Switch widget también admite la inclusión de una etiqueta de texto text estableciendo el atributo de la
siguiente manera:
<Switch android:text="Is Xamarin.Android great?"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:textOn="YES"
android:textOff="NO" />

Este marcado produce la siguiente captura de pantalla en tiempo de ejecución:

Cuando el Switch valor de un cambia, genera un CheckedChange evento. Por ejemplo, en el código siguiente se
captura este evento y se presenta Toast un widget con un mensaje basado en isChecked el valor Switch de, que
se pasa CompoundButton.CheckedChangeEventArg al controlador de eventos como parte del argumento.

Switch s = FindViewById<Switch> (Resource.Id.monitored_switch);

s.CheckedChange += delegate(object sender, CompoundButton.CheckedChangeEventArgs e) {


var toast = Toast.MakeText (this, "Your answer is " +
(e.IsChecked ? "correct" : "incorrect"), ToastLength.Short);
toast.Show ();
};

Vínculos relacionados
SwitchDemo (ejemplo)
Tutorial de diseño de pestañas
TextureView de Xamarin. Android
31/07/2019 • 3 minutes to read • Edit Online

La TextureView clase es una vista que usa la representación 2D con aceleración de hardware para permitir que se
muestre un flujo de contenido de vídeo o OpenGL. Por ejemplo, en la siguiente captura de TextureView pantalla
se muestra la presentación de una fuente en directo desde la cámara del dispositivo:

A diferencia de SurfaceView la clase, que también se puede usar para mostrar contenido de OpenGL o vídeo,
TextureView no se representa en una ventana independiente. Por lo TextureView tanto, es capaz de admitir
transformaciones de vista como cualquier otra vista. Por ejemplo, la rotación TextureView de un se puede realizar
simplemente estableciendo Rotation su propiedad, su transparencia estableciendo su Alpha propiedad, etc.
Por lo tanto, TextureView con, ahora podemos hacer cosas como mostrar una secuencia en directo desde la
cámara y transformarla, tal como se muestra en el código siguiente:
public class TextureViewActivity : Activity,
TextureView.ISurfaceTextureListener
{
Camera _camera;
TextureView _textureView;

protected override void OnCreate (Bundle bundle)


{
base.OnCreate (bundle);
_textureView = new TextureView (this);
_textureView.SurfaceTextureListener = this;

SetContentView (_textureView);
}

public void OnSurfaceTextureAvailable (


Android.Graphics.SurfaceTexture surface,
int width, int height)
{
_camera = Camera.Open ();
var previewSize = _camera.GetParameters ().PreviewSize;
_textureView.LayoutParameters =
new FrameLayout.LayoutParams (previewSize.Width,
previewSize.Height, (int)GravityFlags.Center);

try {
_camera.SetPreviewTexture (surface);
_camera.StartPreview ();
} catch (Java.IO.IOException ex) {
Console.WriteLine (ex.Message);
}

// this is the sort of thing TextureView enables


_textureView.Rotation = 45.0f;
_textureView.Alpha = 0.5f;
}

}

En el código anterior se TextureView crea una instancia en el OnCreate método de la actividad y se TextureView
establece SurfaceTextureListener la actividad como. Para ser SurfaceTextureListener , la actividad implementa la
TextureView.ISurfaceTextureListener interfaz. El sistema llamará OnSurfaceTextAvailable al método cuando el
SurfaceTexture está listo para su uso. En este método, se toma el SurfaceTexture que se pasa y se establece en la
textura de vista previa de la cámara. A continuación, podemos realizar operaciones normales basadas en vistas,
como establecer Rotation y Alpha , como en el ejemplo anterior. La aplicación resultante, que se ejecuta en un
dispositivo, se muestra a continuación:
Para usar, TextureView la aceleración de hardware debe estar habilitada, que será de forma predeterminada a
partir del nivel de API 14. Además, dado que en este ejemplo se usa la cámara android.permission.CAMERA , el
permiso android.hardware.camera y la característica deben establecerse en archivo AndroidManifest. XML.

Vínculos relacionados
TextureViewDemo (sample)
Presentación del bocadillo de helado
Plataforma Android 4,0
Barra de herramientas
16/08/2019 • 4 minutes to read • Edit Online

La barra de herramientas es un componente de barra de acción que proporciona más flexibilidad que la barra
de acciones predeterminada: se puede colocar en cualquier parte de la aplicación, se puede cambiar su tamaño y
puede usar una combinación de colores diferente del tema de la aplicación. Además, cada pantalla de la
aplicación puede tener varias barras de herramientas.

Información general
Un elemento de diseño clave de cualquier actividad de Android es una barra de acciones. La barra de acciones es
el componente de la interfaz de usuario que se usa para la navegación, la búsqueda, los menús y la
personalización de marca en una aplicación Android. En las versiones de Android anteriores a Android 5,0
Lollipop, la barra de acciones (también conocida como la barra de la aplicación) era el componente recomendado
para proporcionar esta funcionalidad.
El Toolbar widget (introducido en Android 5,0 Lollipop) puede considerarse como una generalización de la
interfaz – de la barra de acciones, por lo que se pretende reemplazar la barra de acciones. Se Toolbar puede usar
en cualquier parte del diseño de una aplicación y es mucho más personalizable que una barra de acción. En la
captura de pantalla siguiente se Toolbar muestra el ejemplo personalizado creado en esta guía:

Hay algunas diferencias importantes entre Toolbar y la barra de acciones:


Se Toolbar puede colocar en cualquier parte de la interfaz de usuario.
Se pueden mostrar varias barras de herramientas en la misma pantalla.
Si se usan fragmentos, cada fragmento puede tener el suyo Toolbar propio.
Se Toolbar puede configurar para que abarque solo un ancho parcial de la pantalla.
Dado que no está enlazado a la combinación de colores del décor de ventana de la actividad, puede tener
una combinación de colores visualmente distinta. Toolbar
A diferencia de la barra de acciones Toolbar , no incluye un icono a la izquierda. Los menús de la derecha
usan menos espacio.
El Toolbar alto es ajustable.
Se pueden incluir otras vistas dentro de Toolbar .
Un Toolbar elemento puede contener uno o varios de los siguientes elementos:
Botón de navegación
Una imagen de logotipo con marca
Título y subtítulo
Vistas personalizadas
Menú Acción
Menú de desbordamiento
Las directrices de diseño de material de Google recomiendan aprovechar estos elementos para dar una
apariencia distintiva a las aplicaciones (en lugar de confiar exclusivamente en un icono de aplicación y un título).
En esta guía se tratan los escenarios de Toolbar uso más frecuente:
Reemplazar la barra de acciones predeterminada de una actividad Toolbar por un.
Agregar un segundo Toolbar a una actividad.
Con la biblioteca de compatibilidad de Android V7 , biblioteca de AppCompat (denominada
AppCompat en el resto de esta guía) Toolbar para implementar en versiones anteriores de Android.

Requisitos
Toolbar está disponible en Android 5,0 Lollipop (API 21) y versiones posteriores. Cuando el destino sea
versiones de Android anteriores a Android 5,0, use la biblioteca de compatibilidad de Android V7 AppCompat,
que Toolbar proporciona compatibilidad compatible con versiones anteriores en un paquete de NuGet. La
compatibilidad de la barra de herramientas explica cómo usar esta biblioteca.

Vínculos relacionados
Barra de herramientas de círculo (ejemplo)
Barra de herramientas AppCompat (ejemplo)
Reemplazo de la barra de acciones
16/08/2019 • 14 minutes to read • Edit Online

Información general
Uno de los usos más comunes para Toolbar es reemplazar la barra de acciones predeterminada con un
personalizado Toolbar (cuando se crea un nuevo proyecto de Android, usa la barra de acciones predeterminada).
Dado que Toolbar proporciona la capacidad de agregar logotipos marcados, títulos, elementos de menú, botones
de navegación e incluso vistas personalizadas a la sección de la barra de la aplicación de la interfaz de usuario de
una actividad, ofrece una actualización importante sobre la barra de acción predeterminada.
Para reemplazar la barra de acciones predeterminada de una aplicación Toolbar por una:
1. Cree un nuevo tema personalizado y modifique las propiedades de la aplicación para que use este nuevo
tema.
2. Deshabilite windowActionBar el atributo en el tema personalizado y habilite windowNoTitle el atributo.
3. Defina un diseño para Toolbar .
4. Incluya el Toolbar diseño en el archivo de diseño Main. axml de la actividad.
5. Agregue OnCreate código al método de la actividad para Toolbar buscar ToolBar y llamar SetActionBar
a para instalar como la barra de acciones.
En las secciones siguientes se explica en detalle este proceso. Se crea una aplicación sencilla y su barra de acción
se reemplaza por una Toolbar personalizada.

Iniciar un proyecto de aplicación


Cree un nuevo proyecto de Android denominado ToolbarFun (vea Hola, Android para obtener más información
sobre la creación de un nuevo proyecto de Android). Una vez creado este proyecto, establezca los niveles de
destino y mínimo de la API de Android en android 5,0 (nivel de API 21-Lollipop) o posterior. Para obtener más
información sobre cómo establecer los niveles de versión de Android, consulte Descripción de los nivelesde la API
de Android. Cuando la aplicación se compila y se ejecuta, muestra la barra de acciones predeterminada, tal como
se muestra en esta captura de pantalla:
Crear un tema personalizado
Abra el directorio Resources /Values y cree un nuevo archivo denominado styles. XML. Reemplace su contenido
por el siguiente código XML:

<?xml version="1.0" encoding="utf-8" ?>


<resources>
<style name="MyTheme" parent="@android:style/Theme.Material.Light.DarkActionBar">
<item name="android:windowNoTitle">true</item>
<item name="android:windowActionBar">false</item>
<item name="android:colorPrimary">#5A8622</item>
</style>
</resources>

Este XML define un nuevo tema personalizado denominado mis temas que se basa en el tema Theme. material.
Light. DarkActionBar en el círculo. El windowNoTitle atributo se establece en true para ocultar la barra de
título:

<item name="android:windowNoTitle">true</item>

Para mostrar la barra de herramientas personalizada, ActionBar el valor predeterminado debe estar deshabilitado:

<item name="android:windowActionBar">false</item>

Para el color de colorPrimary fondo de la barra de herramientas se usa un valor de verde oliva:

<item name="android:colorPrimary">#5A8622</item>

Aplicar el tema personalizado


Edite Properties/archivo AndroidManifest. XML y agregue el android:theme atributo siguiente al
<application> elemento para que la aplicación use el MyTheme tema personalizado:
<application android:label="@string/app_name" android:theme="@style/MyTheme"></application>

Para obtener más información sobre cómo aplicar un tema personalizado a una aplicación, consulte uso de temas
personalizados.

Definir un diseño de barra de herramientas


En el directorio Resources /layout , cree un nuevo archivo denominado Toolbar. XML. Reemplace su contenido
por el siguiente código XML:

<?xml version="1.0" encoding="utf-8"?>


<Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?android:attr/actionBarSize"
android:background="?android:attr/colorPrimary"
android:theme="@android:style/ThemeOverlay.Material.Dark.ActionBar"/>

Este XML define el personalizado Toolbar que reemplaza la barra de acciones predeterminada. El alto mínimo de
Toolbar se establece en el tamaño de la barra de acciones que reemplaza:

android:minHeight="?android:attr/actionBarSize"

El color de fondo de Toolbar se establece en el color verde oliva definido anteriormente en styles. XML:

android:background="?android:attr/colorPrimary"

A partir de Lollipop, el atributo se puede usar para aplicar estilo a una vista individual. Los
android:theme
ThemeOverlay.Material temas introducidos en el círculo hacen posible la superposición Theme.Material de los
temas predeterminados, sobrescribiendo los atributos relevantes para que sean claros o oscuros. En este ejemplo,
Toolbar usa un tema oscuro para que su contenido sea ligero en color:

android:theme="@android:style/ThemeOverlay.Material.Dark.ActionBar"

Esta configuración se usa para que los elementos de menú contrasten con el color de fondo más oscuro.

Incluir el diseño de la barra de herramientas


Edite el archivo de diseño Resources /layout/main. axml y reemplace su contenido por el siguiente código XML:

<?xml version="1.0" encoding="utf-8"?>


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
android:id="@+id/toolbar"
layout="@layout/toolbar" />
</RelativeLayout>

Este diseño incluye el Toolbar definido en Toolbar. XML y utiliza RelativeLayout para especificar que Toolbar
se va a colocar en la parte superior de la interfaz de usuario (encima del botón).
Búsqueda y activación de la barra de herramientas
Edite MainActivity.CS y agregue la siguiente instrucción using:

using Android.Views;

Además, agregue las siguientes líneas de código al final del OnCreate método:

var toolbar = FindViewById<Toolbar>(Resource.Id.toolbar);


SetActionBar(toolbar);
ActionBar.Title = "My Toolbar";

Este código busca Toolbar y llama a SetActionBar para que el Toolbar asuma las características de la barra de
acciones predeterminadas. El título de la barra de herramientas se cambia a mi barra de herramientas. Como se
puede observar en este ejemplo de ToolBar código, se puede hacer referencia directamente a la misma como
barra de acción. Compilar y ejecutar – esta aplicación Toolbar el personalizado se muestra en lugar de la barra de
acciones predeterminada:

Tenga en cuenta Toolbar que tiene un estilo independiente Theme.Material.Light.DarkActionBar del tema que se
aplica al resto de la aplicación.
Si se produce una excepción durante la ejecución de la aplicación, consulte la sección de solución de problemas a
continuación.

Agregar elementos de menú


En esta sección, los Toolbar menús se agregan a. El área superior derecha de ToolBar se reserva para los
elementos – de menú cada elemento de menú (también denominado elemento de acción) puede realizar una
acción dentro de la actividad actual o puede realizar una acción en nombre de toda la aplicación.
Para agregar menús a Toolbar :
1. Agregue iconos de menú (si es necesario) mipmap- a las carpetas del proyecto de la aplicación. Google
proporciona un conjunto de iconos de menú gratuitos en la página iconos de materiales .
2. Defina el contenido de los elementos de menú agregando un nuevo archivo de recursos de menú en
recursos/menú.
3. Implemente OnCreateOptionsMenu el método de la – actividad que este método infla los elementos de menú.
4. Implemente OnOptionsItemSelected el método de la – actividad. este método realiza una acción cuando se
puntea un elemento de menú.
En las secciones siguientes se muestra este proceso en detalle mediante la adición de elementos de menú de
Toolbar edición y guardado al personalizado.

Iconos del menú instalar


Continuando con ToolbarFun la aplicación de ejemplo, agregue iconos de menú al proyecto de la aplicación.
Descargue los iconos de la barra de herramientas, descomprima y copie el contenido de las carpetas mipmap -
extraídas en el proyecto MIP - folders en ToolbarFun/ Resources e incluya cada archivo de icono agregado en el
proyecto.
Definir un recurso de menú
Cree un nuevo subdirectorio de menú en recursos. En el subdirectorio Menu , cree un nuevo archivo de recursos
de menú llamado top_menus. XML y reemplace su contenido por el siguiente código XML:

<?xml version="1.0" encoding="utf-8" ?>


<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/menu_edit"
android:icon="@mipmap/ic_action_content_create"
android:showAsAction="ifRoom"
android:title="Edit" />
<item
android:id="@+id/menu_save"
android:icon="@mipmap/ic_action_content_save"
android:showAsAction="ifRoom"
android:title="Save" />
<item
android:id="@+id/menu_preferences"
android:showAsAction="never"
android:title="Preferences" />
</menu>

Este XML crea tres elementos de menú:


Un elemento de menú de edición que ic_action_content_create.png usa el icono (un lápiz).
Un elemento de menú Guardar que usa ic_action_content_save.png el icono (un disquete).
Un elemento de menú de preferencias que no tiene un icono.
Los showAsAction atributos de los elementos de menú Editar y Guardar se establecen ifRoom en – esta
configuración hace que estos elementos de menú aparezcan en Toolbar si hay espacio suficiente para que se
muestren. El elemento de menú Preferencias showAsAction establece never – en esto hace que el menú
preferencias aparezca en el menú de desbordamiento (tres puntos verticales).
Implementación de OnCreateOptionsMenu
Agregue el método siguiente a MainActivity.CS:

public override bool OnCreateOptionsMenu(IMenu menu)


{
MenuInflater.Inflate(Resource.Menu.top_menus, menu);
return base.OnCreateOptionsMenu(menu);
}
Android llama al OnCreateOptionsMenu método para que la aplicación pueda especificar el recurso de menú para
una actividad. En este método, el recurso top_menus. XML se infla en el pasado menu . Este código hace que los
nuevos elementos de menú Editar, Guardary preferencias aparezcan en Toolbar el.
Implementación de OnOptionsItemSelected
Agregue el método siguiente a MainActivity.CS:

public override bool OnOptionsItemSelected(IMenuItem item)


{
Toast.MakeText(this, "Action selected: " + item.TitleFormatted,
ToastLength.Short).Show();
return base.OnOptionsItemSelected(item);
}

Cuando un usuario pulsa un elemento de menú, Android llama OnOptionsItemSelected al método y pasa el
elemento de menú seleccionado. En este ejemplo, la implementación solo muestra una notificación del sistema
para indicar qué elemento de menú se ha punteado.
Compile y ejecute ToolbarFun para ver los nuevos elementos de menú en la barra de herramientas. Toolbar
Ahora se muestran tres iconos de menú, tal como se muestra en esta captura de pantalla:

Cuando un usuario pulsa el elemento de menú Editar , se muestra una notificación del sistema para
OnOptionsItemSelected indicar que se ha llamado al método:
Cuando un usuario pulsa el menú de desbordamiento, se muestra el elemento de menú preferencias .
Normalmente, las acciones menos comunes se deben colocar – en el menú de desbordamiento. en este ejemplo se
usa el menú de desbordamiento para las preferencias porque no se usa tan a menudo como Editar y Guardar:

Para obtener más información sobre los menús de Android, consulte el tema sobre los menús del desarrollador de
Android.

Solución de problemas
Las siguientes sugerencias pueden ayudarle a depurar problemas que pueden producirse al reemplazar la barra de
acciones por una barra de herramientas.
La actividad ya tiene una Barra de acciones
Si la aplicación no está configurada correctamente para usar un tema personalizado, tal y como se explica en
aplicar el tema personalizado, se puede producir la siguiente excepción al ejecutar la aplicación:
Además, se puede producir un mensaje de error como el siguiente: Java.Lang.IllegalStateException: Esta actividad
ya tiene una barra de acciones proporcionada por la ventana Décor.
Para corregir este error, compruebe que se android:theme <application> ha agregado el atributo para el tema
personalizado (en Properties/archivo AndroidManifest. XML ) como se describió anteriormente en aplicar el
tema personalizado. Además, este error puede producirse si el diseño Toolbar o el tema personalizado no están
configurados correctamente.

Vínculos relacionados
Barra de herramientas de círculo (ejemplo)
Barra de herramientas AppCompat (ejemplo)
Adición de una segunda barra de herramientas
16/08/2019 • 8 minutes to read • Edit Online

Información general
Puede hacer más que reemplazar la barra – de acción que se puede usar varias veces dentro de una actividad, se
puede personalizar para colocarla en cualquier parte de la pantalla y se puede configurar para que abarque solo un
ancho parcial de la pantalla. Toolbar Los ejemplos siguientes muestran cómo crear un segundo Toolbar y
colocarlo en la parte inferior de la pantalla. Esto Toolbar implementa los elementos de menú de copiar, cortary
pegar .

Definir la segunda barra de herramientas


Edite el archivo de diseño Main. axml y reemplace su contenido con por el siguiente código XML:

<?xml version="1.0" encoding="utf-8"?>


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
android:id="@+id/toolbar"
layout="@layout/toolbar" />
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/main_content"
android:layout_below="@id/toolbar">
<ImageView
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<Toolbar
android:id="@+id/edit_toolbar"
android:minHeight="?android:attr/actionBarSize"
android:background="?android:attr/colorAccent"
android:theme="@android:style/ThemeOverlay.Material.Dark.ActionBar"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</RelativeLayout>

Este XML agrega una segunda Toolbar a la parte inferior de la pantalla con un ImageView vacío que llena el
centro de la pantalla. El alto de este Toolbar valor se establece en el alto de una barra de acciones:

android:minHeight="?android:attr/actionBarSize"

El color de fondo de Toolbar este valor se establece en un color de énfasis que se definirá a continuación:

android:background="?android:attr/colorAccent

Tenga en cuenta Toolbar que esto se basa en un tema diferente (ThemeOverlay. material. Dark. barra) que el
utilizado Toolbar por el creado al reemplazar el barra de acciones – no está enlazado a la ventana de la actividad
Décor o a el tema que se usa en Toolbar el primer.
Edite Resources /Values/Styles. XML y agregue el color de énfasis siguiente a la definición de estilo:

<item name="android:colorAccent">#C7A935</item>

Esto proporciona a la barra de herramientas inferior un color ámbar oscuro. Al compilar y ejecutar la aplicación, se
muestra una segunda barra de herramientas en blanco en la parte inferior de la pantalla:

Agregar elementos del menú Edición


En esta sección se explica cómo agregar elementos de menú de edición Toolbar a la parte inferior.
Para agregar elementos de menú a un Toolbar elemento secundario:
1. Agregue iconos de menú a mipmap- las carpetas del proyecto de la aplicación (si es necesario).
2. Defina el contenido de los elementos de menú agregando un archivo de recursos de menú adicional a los
recursos o el menú.
3. En el método de OnCreate la actividad, Toolbar busque (llamando a FindViewById ) e inflar los Toolbar
menús.
4. Implemente un controlador de OnCreate clics en para los nuevos elementos de menú.
En las secciones siguientes se muestra este proceso en detalle: Los elementos de menú cortar, copiary pegar se
agregan a Toolbar la parte inferior.
Definir el recurso del menú Edición
En el subdirectorio Resources /Menu , cree un nuevo archivo XML denominado edit_menus. XML y reemplace el
contenido por el siguiente código XML:

<?xml version="1.0" encoding="utf-8" ?>


<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/menu_cut"
android:icon="@mipmap/ic_menu_cut_holo_dark"
android:showAsAction="ifRoom"
android:title="Cut" />
<item
android:id="@+id/menu_copy"
android:icon="@mipmap/ic_menu_copy_holo_dark"
android:showAsAction="ifRoom"
android:title="Copy" />
<item
android:id="@+id/menu_paste"
android:icon="@mipmap/ic_menu_paste_holo_dark"
android:showAsAction="ifRoom"
android:title="Paste" />
</menu>

Este XML crea los elementos de menú cortar, copiary pegar (mediante los iconos que se agregaron mipmap- a
las carpetas al reemplazar el barra de acciones).
Inflar los menús
Al final del OnCreate método de MainActivity.CS, agregue las siguientes líneas de código:

var editToolbar = FindViewById<Toolbar>(Resource.Id.edit_toolbar);


editToolbar.Title = "Editing";
editToolbar.InflateMenu (Resource.Menu.edit_menus);
editToolbar.MenuItemClick += (sender, e) => {
Toast.MakeText(this, "Bottom toolbar tapped: " + e.Item.TitleFormatted, ToastLength.Short).Show();
};

Este edit_toolbar código localiza la vista definida en Main. axml, establece su título en Editingy aumenta sus
elementos de menú (definidos en edit_menus. XML ). Define un controlador de clic de menú que muestra una
notificación del sistema para indicar el icono de edición que se ha punteado.
Compile y ejecute la aplicación. Cuando se ejecute la aplicación, el texto y los iconos agregados anteriormente
aparecerán como se muestra aquí:
Al pulsar el icono del menú cortar , se muestra el siguiente aviso:

Al puntear en los elementos de menú de cualquier barra de herramientas se muestra la notificación del sistema
resultante:
Botón subir
La mayoría de las aplicaciones de Android se basan en el botón atrás para navegar por la aplicación. al presionar
el botón atrás , el usuario se ejecuta en la pantalla anterior. Sin embargo, es posible que también quiera
proporcionar un botón arriba que facilite a los usuarios la navegación por la pantalla principal de la aplicación.
Cuando el usuario selecciona el botón subir , el usuario se mueve hasta un nivel superior en la jerarquía – de la
aplicación, es decir, la aplicación vuelve a hacer que el usuario realice varias actividades en la pila de retroceso, en
lugar de volver a la actividad visitada previamente.
Para habilitar el botón subir en una segunda actividad Toolbar que usa como barra de acción, llame a los
SetDisplayHomeAsUpEnabled métodos y SetHomeButtonEnabled en el método de OnCreate la segunda actividad:

SetActionBar (toolbar);
...
ActionBar.SetDisplayHomeAsUpEnabled (true);
ActionBar.SetHomeButtonEnabled (true);

El ejemplo de código de la barra de herramientas de support V7 muestra el botón subir en acción. Este ejemplo
(que utiliza la biblioteca AppCompat que se describe a continuación) implementa una segunda actividad que usa el
botón de la barra de herramientas arriba para la navegación jerárquica de vuelta a la actividad anterior. En este
ejemplo, el DetailActivity botón Inicio habilita el botón subir realizando las siguientes SupportActionBar
llamadas al método:

SetSupportActionBar (toolbar);
...
SupportActionBar.SetDisplayHomeAsUpEnabled (true);
SupportActionBar.SetHomeButtonEnabled (true);

Cuando el usuario navega MainActivity de a DetailActivity , DetailActivity muestra un botón arriba (flecha
hacia la izquierda) como se muestra en la captura de pantalla:
Al pulsar este botón arriba , la aplicación vuelve a MainActivity . En una aplicación más compleja con varios
niveles de jerarquía, al pulsar este botón, se devolvería al usuario al siguiente nivel superior de la aplicación, en
lugar de a la pantalla anterior.

Vínculos relacionados
Barra de herramientas de círculo (ejemplo)
Barra de herramientas AppCompat (ejemplo)
Compatibilidad de barra de herramientas
16/08/2019 • 11 minutes to read • Edit Online

Información general
En esta sección se explica cómo Toolbar usar en versiones de Android anteriores a Android 5,0 Lollipop. Si la
aplicación no admite versiones de Android anteriores a Android 5,0, puede omitir esta sección.
Dado Toolbar que forma parte de la biblioteca de compatibilidad de Android V7, se puede usar en dispositivos
que ejecutan Android 2,1 (nivel de API 7) y versiones posteriores. Sin embargo, se debe instalar la biblioteca de
compatibilidad de Android V7 de NuGet y el código modificado para que Toolbar use la implementación
proporcionada en esta biblioteca. En esta sección se explica cómo instalar este NuGet y modificar la aplicación
ToolbarFun desde la adición de una segunda barra de herramientas para que se ejecute en versiones de Android
anteriores al círculo 5,0.
Para modificar una aplicación para que use la versión AppCompat de la barra de herramientas:
1. Establezca las versiones de Android mínima y de destino para la aplicación.
2. Instale el paquete de NuGet de AppCompat.
3. Use un tema AppCompat en lugar de un tema integrado de Android.
4. Modifique MainActivity para que sea AppCompatActivity subclases en lugar Activity de.
Cada uno de estos pasos se explica en detalle en las secciones siguientes.

Establecimiento de la versión de Android mínima y de destino


La plataforma de destino de la aplicación debe establecerse en el nivel de API 21 o superior, o bien la aplicación no
se implementará correctamente. Si se detecta un error, como no se encontró ningún identificador de recursos
para el atributo ' tileModeX ' en el paquete ' Android ' durante la implementación de la aplicación, esto se
debe a que la plataforma de destino no está establecida en Android 5,0 (nivel de API 21-Lollipop) o superior.
Establezca el nivel de plataforma de destino en el nivel de API 21 o superior y establezca la configuración de
proyecto de nivel de API de Android en la versión de Android mínima que la aplicación admite. Para obtener más
información sobre cómo establecer los niveles de la API de Android, consulte Descripción de los niveles de API de
Android. En el ToolbarFun ejemplo, la versión mínima de Android se establece en KitKat (nivel de API 4,4).

Instalación del paquete de NuGet de AppCompat


A continuación, agregue el paquete de la biblioteca de compatibilidad de Android V7 en el proyecto. En Visual
Studio, haga clic con el botón derecho en referencias y seleccione administrar paquetes NuGet. ... Haga clic en
examinar y busque biblioteca de compatibilidad de Android V7 AppCompat. Seleccione Xamarin.
Android. support. V7. AppCompat y haga clic en instalar:
Cuando se instala este NuGet, también se instalan otros paquetes NuGet si aún no están presentes (como
Xamarin. Android. support. Animated. Vector. drawable, Xamarin. Android. support. V4y Xamarin.
Android. support. Vector. drawable). Para obtener más información sobre la instalación de paquetes NuGet,
consulte Tutorial: Incluir un NuGet en el proyecto.

Usar un tema y una barra de herramientas de AppCompat


La biblioteca AppCompat incluye varios Theme.AppCompat temas que se pueden usar en cualquier versión de
Android compatible con la biblioteca AppCompat. El ToolbarFun tema de la aplicación de ejemplo
Theme.Material.Light.DarkActionBar se deriva de, que no está disponible en las versiones de Android anteriores al
círculo. Por lo ToolbarFun tanto, se debe adaptar para usar el homólogo de AppCompat para
Theme.AppCompat.Light.DarkActionBar este tema,. Además, dado Toolbar que no está disponible en las versiones de
Android anteriores a Lollipop, se debe usar la versión Toolbar AppCompat de. Por lo tanto, los diseños
android.support.v7.widget.Toolbar deben usar en Toolbar lugar de.

Actualizar diseños
Edite Resources /layout/main. axml y reemplace el Toolbar elemento por el siguiente código XML:

<android.support.v7.widget.Toolbar
android:id="@+id/edit_toolbar"
android:minHeight="?attr/actionBarSize"
android:background="?attr/colorAccent"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

Edite Resources /layout/Toolbar. XML y reemplace su contenido por el siguiente código XML:

<?xml version="1.0" encoding="utf-8"?>


<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>

Tenga en ?attr android: cuenta que los valores ya no tienen el prefijo (Recuerde ? que la notación hace
referencia a un recurso en el tema actual). Si ?android:attr todavía se usaba aquí, Android haría referencia al
valor de atributo desde la plataforma que se está ejecutando actualmente en lugar de desde la biblioteca
AppCompat. Dado que en este ejemplo actionBarSize se usa el definido por la biblioteca android: AppCompat,
se quita el prefijo. Del mismo @android:style modo, se @style cambia a para android:theme que el atributo se
establezca en un tema de la – biblioteca ThemeOverlay.AppCompat.Dark.ActionBar AppCompat, el tema se usa
ThemeOverlay.Material.Dark.ActionBar aquí en lugar de.

Actualizar el estilo
Edite Resources /Values/Styles. XML y reemplace su contenido por el siguiente código XML:

<?xml version="1.0" encoding="utf-8" ?>


<resources>
<style name="MyTheme" parent="MyTheme.Base"> </style>
<style name="MyTheme.Base" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="windowNoTitle">true</item>
<item name="windowActionBar">false</item>
<item name="colorPrimary">#5A8622</item>
<item name="colorAccent">#A88F2D</item>
</style>
</resources>

Los nombres de elemento y el tema primario en este ejemplo ya no tienen el android: prefijo porque se usa la
biblioteca AppCompat. Además, el tema primario cambia a la versión AppCompat de Light.DarkActionBar .
Actualizar menús
Para admitir versiones anteriores de Android, la biblioteca AppCompat usa atributos personalizados que reflejan
los atributos del android: espacio de nombres. Sin embargo, algunos atributos (como el showAsAction atributo
que se usa <menu> en la etiqueta) no existen en el marco de Android en – dispositivos showAsAction antiguos se
presentó en Android API 11, pero no está disponible en Android API 7. Por esta razón, se debe usar un espacio de
nombres personalizado para prefijar todos los atributos definidos por la biblioteca de compatibilidad. En los
archivos de recursos de menú, se local define un espacio de nombres denominado showAsAction para prefijar el
atributo.
Edite Resources /Menu/top_menus. XML y reemplace su contenido por el siguiente código XML:

<?xml version="1.0" encoding="utf-8" ?>


<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/menu_edit"
android:icon="@mipmap/ic_action_content_create"
local:showAsAction="ifRoom"
android:title="Edit" />
<item
android:id="@+id/menu_save"
android:icon="@mipmap/ic_action_content_save"
local:showAsAction="ifRoom"
android:title="Save" />
<item
android:id="@+id/menu_preferences"
local:showAsAction="never"
android:title="Preferences" />
</menu>

El local espacio de nombres se agrega con esta línea:

xmlns:local="http://schemas.android.com/apk/res-auto">

El showAsAction atributo está precedido por este local: espacio de nombres en lugar de android:
local:showAsAction="ifRoom"

Del mismo modo, edite Resources /Menu/edit_menus. XML y reemplace su contenido por el siguiente código
XML:

<?xml version="1.0" encoding="utf-8" ?>


<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/menu_cut"
android:icon="@mipmap/ic_menu_cut_holo_dark"
local:showAsAction="ifRoom"
android:title="Cut" />
<item
android:id="@+id/menu_copy"
android:icon="@mipmap/ic_menu_copy_holo_dark"
local:showAsAction="ifRoom"
android:title="Copy" />
<item
android:id="@+id/menu_paste"
android:icon="@mipmap/ic_menu_paste_holo_dark"
local:showAsAction="ifRoom"
android:title="Paste" />
</menu>

¿Cómo ofrece este modificador de espacio de showAsAction nombres compatibilidad con el atributo en versiones
de Android anteriores al nivel de API 11? El atributo showAsAction personalizado y todos sus valores posibles se
incluyen en la aplicación cuando se instala el NuGet de AppCompat.

Subclase AppCompatActivity
El último paso de la conversión es modificar MainActivity para que sea una subclase de. AppCompactActivity
Edite MainActivity.CS y agregue las using siguientes instrucciones:

using Android.Support.V7.App;
using Toolbar = Android.Support.V7.Widget.Toolbar;

Declara Toolbar como la versión AppCompat de Toolbar . A continuación, cambie la definición de MainActivity
clase de:

public class MainActivity : AppCompatActivity

Para establecer la barra de acciones en la versión AppCompat Toolbar de, sustituya la SetActionBar llamada
SetSupportActionBar a por. En este ejemplo, el título también se cambia para indicar que se está usando la Toolbar
versión AppCompat de:

SetSupportActionBar (toolbar);
SupportActionBar.Title = "My AppCompat Toolbar";

Por último, cambie el nivel mínimo de Android al valor anterior al círculo que se va a admitir (por ejemplo, API
19).
Compilar la aplicación y ejecutarla en un dispositivo o emulador Android. En la captura de pantalla siguiente se
muestra la versión AppCompat de ToolbarFun en un nexo 4 con KitKat (API 19):
Cuando se usa la biblioteca AppCompat, no es necesario cambiar los temas en función de la versión – de Android.
la biblioteca AppCompat permite proporcionar una experiencia de usuario coherente en todas las versiones
compatibles de Android.

Vínculos relacionados
Barra de herramientas de círculo (ejemplo)
Barra de herramientas AppCompat (ejemplo)
ViewPager
16/08/2019 • 7 minutes to read • Edit Online

ViewPager es un administrador de diseño que le permite implementar la navegación de gestural. La navegación


Gestural permite al usuario desplazarse a la izquierda y a la derecha para recorrer las páginas de datos. En esta
guía se explica cómo implementar la navegación gestural con ViewPager, con y sin fragmentos. También se
describe cómo agregar indicadores de página mediante PagerTitleStrip y PagerTabStrip.

Información general
Un escenario común en el desarrollo de aplicaciones es la necesidad de proporcionar a los usuarios la navegación
gestural entre las vistas del mismo nivel. En este enfoque, el usuario se desliza hacia la izquierda o la derecha para
tener acceso a las páginas de contenido (por ejemplo, en un asistente para la instalación o en una presentación).
Puede crear estas vistas de deslizamiento mediante el ViewPager widget, disponible en la biblioteca de
compatibilidad de Android V4. ViewPager Es un widget de diseño compuesto por varias vistas secundarias donde
cada vista secundaria constituye una página en el diseño:

Normalmente, ViewPager se usa junto con fragmentos; sin embargo, hay algunas situaciones en las que podría
querer usar ViewPager sin la complejidad agregada de Fragment s.
ViewPager utiliza un patrón de adaptador para proporcionarle las vistas que se van a mostrar. El adaptador que se
usa aquí es conceptualmente similar al que se usa en RecyclerView – se proporciona PagerAdapter una
implementación de para generar las ViewPager páginas que muestra al usuario. Las páginas mostradas
ViewPager por pueden View ser s Fragment o s. Cuando View se muestran s, el adaptador subclases de la
PagerAdapter clase base de Android. Si Fragment se muestran s, el adaptador subclases de FragmentPagerAdapter
Android. La biblioteca de compatibilidad de Android FragmentPagerAdapter también incluye (una subclase de
PagerAdapter ) para ayudarle con los Fragment detalles de la conexión a los datos.

En esta guía se muestran ambos enfoques:


En Viewpager con vistas, se desarrolla una aplicación de TreePager para mostrar cómo usar ViewPager
para mostrar vistas de un catálogo de árbol (una galería de imágenes de árboles de deciduous y perenne).
PagerTabStrip y PagerTitleStrip se usan para mostrar los títulos que ayudan en la navegación de páginas.

En Viewpager con fragmentos, se desarrolla una aplicación de FlashCardPager ligeramente más compleja
para demostrar cómo se ViewPager usa Fragment con para crear una aplicación que presenta problemas
matemáticos como tarjetas flash y responde a los datos proporcionados por el usuario.

Requisitos
Para usar ViewPager en el proyecto de la aplicación, debe instalar el paquete de la biblioteca de compatibilidad de
Android V4 . Para obtener más información sobre la instalación de paquetes NuGet, consulte Tutorial: Incluir un
NuGet en el proyecto.

Arquitectura
Se usan tres componentes para implementar la navegación gestural ViewPager con:
ViewPager
Adaptador
Indicador de buscapersonas
A continuación se resume cada uno de estos componentes.
ViewPager
ViewPager es un administrador de diseño que muestra una colección View de uno en uno. Su trabajo es detectar
el gesto de deslizar rápidamente del usuario y navegar a la vista siguiente o anterior según corresponda. Por
ejemplo, en la captura de pantalla ViewPager siguiente se muestra cómo realizar la transición de una imagen a la
siguiente en respuesta a un gesto del usuario:
Adaptador
ViewPager extrae sus datos de un adaptador. El trabajo del adaptador es crear los View s mostrados ViewPager
por, proporcionándoles según sea necesario. En el diagrama siguiente se muestra este – concepto que el
adaptador crea y View rellena s y los ViewPager proporciona al. Como detecta los gestos de deslizamiento del
usuario, pide al adaptador que proporcione el adecuado View para mostrar: ViewPager
En este ejemplo concreto, cada View se construye ViewPager a partir de una imagen de árbol y un nombre de
árbol antes de pasarse a.
Indicador de buscapersonas
ViewPager se puede usar para mostrar un conjunto de datos grande (por ejemplo, una galería de imágenes puede
contener cientos de imágenes). Para ayudar al usuario a navegar en conjuntos de ViewPager datos grandes, a
menudo viene acompañado de un indicador de buscapersonas que muestra una cadena. La cadena puede ser el
título de la imagen, un título o simplemente la posición de la vista actual dentro del conjunto de datos.
Hay dos vistas que pueden generar esta información de navegación PagerTabStrip : y PagerTitleStrip. cada una
muestra una cadena en la parte superior de un ViewPager , ViewPager y cada una de ellas extrae sus datos del
adaptador de para que siempre permanezcan sincronizados con el que se muestra View actualmente. La
diferencia entre ellos es que PagerTabStrip incluye un indicador visual para la cadena "actual" mientras
PagerTitleStrip que no (como se muestra en estas capturas de pantallas):

En esta guía se muestra cómo ViewPager immplement, adaptadores e indicadores de los componentes de la
aplicación e integrarlos para admitir la navegación gestural.
Vínculos relacionados
TreePager (ejemplo)
FlashCardPager (ejemplo)
ViewPager con vistas
16/08/2019 • 21 minutes to read • Edit Online

ViewPager es un administrador de diseño que le permite implementar la navegación de gestural. La navegación


Gestural permite al usuario desplazarse a la izquierda y a la derecha para recorrer las páginas de datos. En esta
guía se explica cómo implementar una interfaz de usuario que se pueda deslizar con ViewPager y PagerTabStrip
mediante las vistas como páginas de datos (en una guía posterior se explica cómo usar los fragmentos de las
páginas).

Información general
Esta guía es un tutorial que proporciona una demostración paso a paso sobre cómo usar ViewPager para
implementar una galería de imágenes de árboles deciduous y perennes. En esta aplicación, el usuario se desliza a
la izquierda y a la derecha a través de un "Catálogo de árboles" para ver las imágenes de árbol. En la parte
superior de cada página del catálogo, el nombre del árbol se muestra en un PagerTabStrip y se muestra una
imagen del árbol ImageView en. Un adaptador se utiliza para interactuar ViewPager con el modelo de datos
subyacente. Esta aplicación implementa un adaptador derivado de PagerAdapter .
Aunque ViewPager las aplicaciones basadas en suelen implementarse Fragment con s, hay algunos casos de uso
relativamente sencillos en los que Fragment no es necesaria la complejidad adicional de s. Por ejemplo, la
aplicación de la galería de imágenes básica que se ilustra en este tutorial no Fragment requiere el uso de s. Dado
que el contenido es estático y el usuario solo se desliza hacia atrás y hacia delante entre distintas imágenes, la
implementación se puede simplificar mediante el uso de vistas y diseños estándar de Android.

Iniciar un proyecto de aplicación


Cree un nuevo proyecto de Android denominado TreePager (vea Hola, Android para obtener más información
sobre la creación de nuevos proyectos de Android). A continuación, inicie el administrador de paquetes NuGet.
(Para obtener más información sobre la instalación de paquetes NuGet, consulte Tutorial: Incluir un NuGet en el
proyecto). Buscar e instalar la biblioteca de compatibilidad de Android V4:

También se instalarán los paquetes adicionales reaquired de la biblioteca de compatibilidad de Android V4.

Agregar un origen de datos de ejemplo


En este ejemplo, el origen de datos del catálogo de árbol ( TreeCatalog representado por la clase ViewPager )
proporciona el objeto con el contenido del elemento. TreeCatalog contiene una colección lista para la creación de
imágenes de árbol y títulos de árbol que el adaptador usará View para crear s. El TreeCatalog constructor no
requiere ningún argumento:

TreeCatalog treeCatalog = new TreeCatalog();

La colección de imágenes en TreeCatalog se organiza de tal forma que un indexador puede tener acceso a cada
imagen. Por ejemplo, la siguiente línea de código recupera el identificador de recurso de imagen para la tercera
imagen de la colección:

int imageId = treeCatalog[2].imageId;

Dado que los detalles de TreeCatalog implementación de no son relevantes ViewPager para comprender
TreeCatalog , el código no se muestra aquí. El código fuente de TreeCatalog está disponible en TreeCatalog.CS.
Descargue este archivo de código fuente (o copie y pegue el código en un nuevo archivo TreeCatalog.CS ) y
agréguelo al proyecto. Además, descargue y descomprima los archivos de imagen en la carpeta Resources
/drawable e inclúyalo en el proyecto.

Crear un diseño de ViewPager


Abra Resources/layout/main. axml y reemplace su contenido por el siguiente código XML:

<?xml version="1.0" encoding="utf-8"?>


<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent" >

</android.support.v4.view.ViewPager>

```csharp
This XML defines a `ViewPager` that occupies the entire screen. Note that
you must use the fully-qualified name **android.support.v4.view.ViewPager**
because `ViewPager` is packaged in a support library. `ViewPager` is
available only from
[Android Support Library v4](https://www.nuget.org/packages/Xamarin.Android.Support.v4/);
it is not available in the Android SDK.

## Set up ViewPager

Edit **MainActivity.cs** and add the following `using` statement:

```csharp
using Android.Support.V4.View;

Reemplace el método OnCreate con el código siguiente:

protected override void OnCreate(Bundle bundle)


{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
ViewPager viewPager = FindViewById<ViewPager>(Resource.Id.viewpager);
TreeCatalog treeCatalog = new TreeCatalog();
}
Este código hace lo siguiente:
1. Establece la vista a partir del recurso de diseño Main. axml .
2. Recupera una referencia a ViewPager del diseño.
3. Crea una instancia de TreeCatalog un nuevo como el origen de datos.

Al compilar y ejecutar este código, debería ver una pantalla similar a la siguiente captura de pantalla:

En este punto, ViewPager está vacío porque no tiene un adaptador para tener acceso al contenido de
TreeCatalog. En la sección siguiente, se crea un PagerAdapter para conectar el ViewPager a TreeCatalog.

Crear el adaptador
ViewPager utiliza un objeto de controlador de adaptador que se ViewPager encuentra entre y el origen de datos
(vea la ilustración del adaptador). Para tener acceso a estos datos, ViewPager es necesario proporcionar un
adaptador personalizado derivado de. PagerAdapter Este adaptador rellena cada ViewPager página con el
contenido del origen de datos. Dado que este origen de datos es específico de la aplicación, el adaptador
personalizado es el código que entiende cómo obtener acceso a los datos. A medida que el usuario desliza el dedo
por ViewPager las páginas del, el adaptador extrae información del origen de datos y la carga en ViewPager las
páginas para que la muestre.
Al implementar un PagerAdapter , debe invalidar lo siguiente:
InstantiateItem Crea la página ( View ) para una posición determinada y la agrega a la ViewPager
colección de vistas de. –
DestroyItem – Quita una página de una posición determinada.
Recuento – Propiedad de solo lectura que devuelve el número de vistas (páginas) disponibles.
IsViewFromObject – Determina si una página está asociada a un objeto de clave concreto. (El
InstantiateItem método crea este objeto). En este ejemplo, el objeto de clave es TreeCatalog el objeto de
datos.
Agregue un nuevo archivo denominado TreePagerAdapter.CS y reemplace su contenido por el código siguiente:

using System;
using Android.App;
using Android.Runtime;
using Android.Content;
using Android.Views;
using Android.Widget;
using Android.Support.V4.View;
using Java.Lang;

namespace TreePager
{
class TreePagerAdapter : PagerAdapter
{
public override int Count
{
get { throw new NotImplementedException(); }
}

public override bool IsViewFromObject(View view, Java.Lang.Object obj)


{
throw new NotImplementedException();
}

public override Java.Lang.Object InstantiateItem (View container, int position)


{
throw new NotImplementedException();
}

public override void DestroyItem(View container, int position, Java.Lang.Object view)


{
throw new NotImplementedException();
}
}
}

Este código codifica como código auxiliar PagerAdapter la implementación esencial. En las secciones siguientes,
cada uno de estos métodos se reemplaza por código de trabajo.
Implementar el constructor
Cuando la aplicación crea una instancia TreePagerAdapter de, proporciona un contexto MainActivity (
TreeCatalog ) y una instancia de. Agregue las siguientes variables de miembro y constructor a la parte superior
TreePagerAdapter de la clase en TreePagerAdapter.CS:

Context context;
TreeCatalog treeCatalog;

public TreePagerAdapter (Context context, TreeCatalog treeCatalog)


{
this.context = context;
this.treeCatalog = treeCatalog;
}

El propósito de este constructor es almacenar el contexto y TreeCatalog la instancia TreePagerAdapter que


utilizará.
Recuento de implementaciones
La Count implementación es relativamente simple: devuelve el número de árboles del catálogo de árbol.
Reemplaza Count por el código siguiente:

public override int Count


{
get { return treeCatalog.NumTrees; }
}

La NumTrees propiedad de TreeCatalog devuelve el número de árboles (número de páginas) del conjunto de
datos.
Implementación de InstantiateItem
El InstantiateItem método crea la página para una posición determinada. También debe agregar la vista recién
creada a la ViewPager colección de vistas de. Para que esto sea posible, ViewPager se pasa como el parámetro del
contenedor.
Reemplace el método InstantiateItem con el código siguiente:

public override Java.Lang.Object InstantiateItem (View container, int position)


{
var imageView = new ImageView (context);
imageView.SetImageResource (treeCatalog[position].imageId);
var viewPager = container.JavaCast<ViewPager>();
viewPager.AddView (imageView);
return imageView;
}

Este código hace lo siguiente:


1. Crea una instancia de ImageView un nuevo para mostrar la imagen de árbol en la posición especificada. La
aplicación MainActivity es el contexto que se pasará ImageView al constructor.
2. Establece el ImageView recurso TreeCatalog en el identificador de recurso de imagen en la posición
especificada.
3. Convierte el contenedor View pasado en una ViewPager referencia. Tenga en cuenta que debe
JavaCast<ViewPager>() usar para realizar correctamente esta conversión (esto es necesario para que
Android realice una conversión de tipos comprobada en tiempo de ejecución).
4. Agrega la instancia ImageView de ViewPager a y devuelve ImageView al llamador.
Cuando muestra la imagen en position , se muestra ImageView . ViewPager Inicialmente, InstantiateItem se
llama dos veces para rellenar las dos primeras páginas con vistas. A medida que el usuario se desplaza, se vuelve
a llamar para mantener las vistas justo detrás y por adelante del elemento mostrado actualmente.
Implementación de DestroyItem
El DestroyItem método quita una página de la posición especificada. En las aplicaciones en las que puede cambiar
la vista en cualquier ViewPager posición determinada, debe tener alguna manera de quitar una vista obsoleta en
esa posición antes de reemplazarla por una nueva vista. En el TreeCatalog ejemplo, la vista en cada posición no
cambia, por lo que una vista que DestroyItem Quite simplemente se volverá a agregar cuando InstantiateItem
se llame a para esa posición. (Para obtener una mayor eficacia, puede implementar un grupo para reciclar View
que se volverá a mostrar en la misma posición).
Reemplace el método DestroyItem con el código siguiente:
public override void DestroyItem(View container, int position, Java.Lang.Object view)
{
var viewPager = container.JavaCast<ViewPager>();
viewPager.RemoveView(view as View);
}

Este código hace lo siguiente:


1. Convierte el contenedor View pasado en una ViewPager referencia.
2. Convierte el view objeto Java pasado () en un C# View ( view as View );
3. Quita la vista de ViewPager .
Implementación de IsViewFromObject
A medida que el usuario se desliza hacia la izquierda y la ViewPager derecha IsViewFromObject a través de las
páginas View de contenido, llama a para comprobar que el elemento secundario en la posición especificada está
asociado al objeto del adaptador para la misma posición (por lo tanto, el objeto del adaptador se denomina clave
de objeto). En el caso de las aplicaciones relativamente sencillas, la Asociación – es una de las identidades que la
clave de objeto del adaptador en esa instancia es ViewPager la InstantiateItem vista que se devolvió previamente
a Via. Sin embargo, para otras aplicaciones, la clave de objeto puede ser alguna otra instancia de clase específica
del adaptador que esté asociada a la vista secundaria, pero no a ViewPager la misma, que se muestra en esa
posición. Solo el adaptador sabe si la vista y la clave de objeto que se han pasado están asociadas.
IsViewFromObject debe implementarse para PagerAdapter que funcione correctamente. Si IsViewFromObject
ViewPager devuelve false para una posición determinada, no mostrará la vista en esa posición. En la TreePager
aplicación, la clave de objeto devuelta InstantiateItem por es la página View de un árbol, por lo que el código
solo tiene que comprobar la identidad (es decir, la clave de objeto y la vista son una y la misma). Reemplaza
IsViewFromObject por el código siguiente:

public override bool IsViewFromObject(View view, Java.Lang.Object obj)


{
return view == obj;
}

Agregar el adaptador a ViewPager


Ahora que TreePagerAdapter está implementado, es el momento de agregarlo ViewPager al. En MainActivity.CS,
agregue la siguiente línea de código al final del OnCreate método:

viewPager.Adapter = new TreePagerAdapter(this, treeCatalog);

Este código crea una instancia TreePagerAdapter de, pasando MainActivity como el contexto ( this ). La instancia
TreeCatalog de se pasa al segundo argumento del constructor. La ViewPager propiedad Adapter de se
TreePagerAdapter estableceen ViewPager el objeto al que se ha creado una instancia; de esta forma, se conecta a.
TreePagerAdapter

La implementación básica ahora se ha – completado compilar y ejecutar la aplicación. Debería ver que la primera
imagen del catálogo de árbol aparece en la pantalla, como se muestra a la izquierda en la siguiente captura de
pantalla. Deslice el dedo hacia la izquierda para ver más vistas de árbol y deslice el dedo hacia la derecha para
retroceder por el catálogo de árbol:
Agregar un indicador de buscapersonas
Esta implementación ViewPager mínima muestra las imágenes del catálogo de árbol, pero no proporciona
ninguna indicación de dónde se encuentra el usuario en el catálogo. El siguiente paso consiste en agregar un
PagerTabStrip . PagerTabStrip Informa al usuario de la página que se muestra y proporciona el contexto de
navegación al mostrar una sugerencia de las páginas anteriores y siguientes. PagerTabStrip está pensado para
usarse como un indicador de la página actual de un ViewPager ; se desplaza y se actualiza a medida que el usuario
desliza el dedo por cada página.
Abra Resources/layout/main. axml y PagerTabStrip agregue un al diseño:

<?xml version="1.0" encoding="utf-8"?>


<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<android.support.v4.view.PagerTabStrip
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:paddingBottom="10dp"
android:paddingTop="10dp"
android:textColor="#fff" />

</android.support.v4.view.ViewPager>

ViewPager y PagerTabStripestán diseñados para funcionar conjuntamente. Al declarar un PagerTabStrip dentro


de un ViewPager diseño, el ViewPager buscará automáticamente el PagerTabStrip y lo conectará al adaptador. Al
compilar y ejecutar la aplicación, debería ver el vacío PagerTabStrip mostrado en la parte superior de cada
pantalla:
Mostrar un título
Para agregar un título a cada pestaña de página, implemente el GetPageTitleFormatted método en la
PagerAdapter clase derivada de. ViewPager llama GetPageTitleFormatted a (si está implementado) para obtener la
cadena de título que describe la página en la posición especificada. Agregue el método siguiente a la
TreePagerAdapter clase en TreePagerAdapter.CS:

public override Java.Lang.ICharSequence GetPageTitleFormatted(int position)


{
return new Java.Lang.String(treeCatalog[position].caption);
}

Este código recupera la cadena de título de árbol de la página (posición) especificada en el catálogo de árbol, la
convierte en un String Java y la ViewPager devuelve a. Al ejecutar la aplicación con este nuevo método, cada
página muestra el título del árbol en PagerTabStrip . Debería ver el nombre del árbol en la parte superior de la
pantalla sin subrayado:

Puede deslizar el dedo hacia atrás y hacia delante para ver cada imagen de árbol con título en el catálogo.
Variación de PagerTitleStrip
PagerTitleStrip es muy similar a PagerTabStrip , salvo PagerTabStrip que agrega un subrayado para la pestaña
seleccionada actualmente. Puede reemplazar PagerTabStrip por PagerTitleStrip en el diseño anterior y volver a
ejecutar la aplicación para ver su aspecto con PagerTitleStrip :

Tenga en cuenta que el subrayado se quita PagerTitleStrip al convertir a.

Resumen
En este tutorial se proporciona un ejemplo paso a paso de cómo compilar una ViewPager aplicación basada en
Basic sin Fragment usar s. Se presentó un ejemplo de origen de datos que contiene cadenas de imágenes
ViewPager y leyendas, un diseño para mostrar las PagerAdapter imágenes y una subclase ViewPager que conecta
con el origen de datos. Para ayudar al usuario a navegar por el conjunto de datos, se incluyeron instrucciones que
explican cómo PagerTabStrip agregar PagerTitleStrip un o para mostrar el título de la imagen en la parte
superior de cada página.

Vínculos relacionados
TreePager (ejemplo)
ViewPager con fragmentos
16/08/2019 • 24 minutes to read • Edit Online

ViewPager es un administrador de diseño que le permite implementar la navegación de gestural. La navegación


Gestural permite al usuario desplazarse a la izquierda y a la derecha para recorrer las páginas de datos. En esta
guía se explica cómo implementar una interfaz de usuario que se pueda deslizar con ViewPager, usando
fragmentos como páginas de datos.

Información general
ViewPager a menudo se usa junto con fragmentos para que sea más fácil administrar el ciclo de vida de cada
página en ViewPager . En este tutorial, ViewPager se usa para crear una aplicación llamada FlashCardPager que
presenta una serie de problemas matemáticos en tarjetas flash. Cada tarjeta flash se implementa como un
fragmento. El usuario se desliza rápidamente a la izquierda y a la derecha a través de las tarjetas flash y se pulsa
un problema matemático para revelar su respuesta. Esta aplicación crea una Fragment instancia de para cada
tarjeta flash e implementa un adaptador derivado de FragmentPagerAdapter . En Viewpager y vistas, la mayor parte
del trabajo se realizó MainActivity en los métodos del ciclo de vida. En FlashCardPager, la mayor parte del
trabajo lo realizará un Fragment en uno de sus métodos de ciclo de vida.
En esta guía no se tratan los conceptos básicos de – los fragmentos si aún no está familiarizado con los
fragmentos de Xamarin. Android, consulte fragmentos para ayudarle a empezar a trabajar con fragmentos.

Iniciar un proyecto de aplicación


Cree un nuevo proyecto de Android llamado FlashCardPager. A continuación, inicie el administrador de paquetes
Nuget (para obtener más información sobre la instalación de paquetes Nuget, consulte Tutorial: Incluir un NuGet
en el proyecto). Busque e instale el paquete Xamarin. Android. support. V4 tal y como se explica en Viewpager y
vistas.

Agregar un origen de datos de ejemplo


En FlashCardPager, el origen de datos es una baraja de tarjetas flash representadas por la FlashCardDeck clase;
este origen de datos proporciona el elemento con el contenido del ViewPager elemento. FlashCardDeck contiene
una colección preparada de problemas y respuestas matemáticas. El FlashCardDeck constructor no requiere
ningún argumento:

FlashCardDeck flashCards = new FlashCardDeck();

La colección de tarjetas flash de FlashCardDeck se organiza de forma que un indexador puede acceder a cada
tarjeta flash. Por ejemplo, la siguiente línea de código recupera el cuarto problema de la tarjeta flash en la baraja:

string problem = flashCardDeck[3].Problem;

Esta línea de código recupera la respuesta correspondiente al problema anterior:

string answer = flashCardDeck[3].Answer;

Dado que los detalles de FlashCardDeck implementación de no son relevantes ViewPager para comprender
FlashCardDeck, el código no se muestra aquí. El código fuente de FlashCardDeck está disponible en
FlashCardDeck.CS. Descargue este archivo de código fuente (o copie y pegue el código en un nuevo archivo
FlashCardDeck.CS ) y agréguelo al proyecto.

Crear un diseño de ViewPager


Abra Resources/layout/main. axml y reemplace su contenido por el siguiente código XML:

<?xml version="1.0" encoding="utf-8"?>


<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent" >

</android.support.v4.view.ViewPager>

Este XML define un ViewPager que ocupa toda la pantalla. Tenga en cuenta que debe usar el nombre completo
Android. support. V4. View. ViewPager porque ViewPager está empaquetado en una biblioteca de soporte
técnico. ViewPager solo está disponible desde la biblioteca de compatibilidad de Android V4; no está disponible en
el Android SDK.

Configuración de ViewPager
Edite MainActivity.CS y agregue las using siguientes instrucciones:

using Android.Support.V4.View;
using Android.Support.V4.App;

Cambie la MainActivity declaración de clase para que se derive de FragmentActivity :

public class MainActivity : FragmentActivity

MainActivity se deriva de FragmentActivity (en lugar Activity de) FragmentActivity porque sabe cómo
administrar la compatibilidad de los fragmentos. Reemplace el método OnCreate con el código siguiente:

protected override void OnCreate(Bundle bundle)


{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
ViewPager viewPager = FindViewById<ViewPager>(Resource.Id.viewpager);
FlashCardDeck flashCards = new FlashCardDeck();
}

Este código hace lo siguiente:


1. Establece la vista a partir del recurso de diseño Main. axml .
2. Recupera una referencia a ViewPager del diseño.
3. Crea una instancia de FlashCardDeck un nuevo como el origen de datos.

Al compilar y ejecutar este código, debería ver una pantalla similar a la siguiente captura de pantalla:
Llegados a este punto ViewPager , el está vacío porque no hay los fragmentos que se usan para rellenar el
ViewPager , y carece de un adaptador para crear estos fragmentos a partir de los datos de FlashCardDeck.

En las secciones siguientes, se FlashCardFragment crea un para implementar la funcionalidad de cada tarjeta flash y
se crea FragmentPagerAdapter un para conectar el ViewPager FlashCardDeck a los fragmentos creados a partir de
los datos de.

Crear el fragmento
Cada tarjeta flash se administrará mediante un fragmento de IU FlashCardFragment denominado.
FlashCardFragment la vista de mostrará la información contenida en una sola tarjeta flash. Cada instancia de
FlashCardFragment se hospedará ViewPager en. FlashCardFragment la vista de se compone de TextView un que
muestra el texto del problema de la tarjeta flash. Esta vista implementará un controlador de eventos que utiliza
Toast un para mostrar la respuesta cuando el usuario puntea la pregunta de la tarjeta flash.

Crear el diseño de FlashCardFragment


Antes FlashCardFragment de que se pueda implementar, debe definirse su diseño. Este diseño es un diseño de
contenedor de fragmentos para un único fragmento. Agregue un nuevo diseño de Android a recursos/diseño
denominado flashcard_layout. axml. Abra Resources/layout/flashcard_layout. axml y reemplace su
contenido por el código siguiente:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/flash_card_question"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:textAppearance="@android:style/TextAppearance.Large"
android:textSize="100sp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="Question goes here" />
</RelativeLayout>

Este diseño define un único fragmento de la tarjeta flash; cada fragmento está formado por un TextView que
muestra un problema matemático mediante una fuente grande (100SP ). Este texto se centra vertical y
horizontalmente en la tarjeta flash.
Crear la clase FlashCardFragment inicial
Agregue un nuevo archivo denominado FlashCardFragment.CS y reemplace su contenido por el código
siguiente:

using System;
using Android.OS;
using Android.Views;
using Android.Widget;
using Android.Support.V4.App;

namespace FlashCardPager
{
public class FlashCardFragment : Android.Support.V4.App.Fragment
{
public FlashCardFragment() { }

public static FlashCardFragment newInstance(String question, String answer)


{
FlashCardFragment fragment = new FlashCardFragment();
return fragment;
}
public override View OnCreateView (
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View view = inflater.Inflate (Resource.Layout.flashcard_layout, container, false);
TextView questionBox = (TextView)view.FindViewById (Resource.Id.flash_card_question);
return view;
}
}
}

Este código procesa el código auxiliar Fragment de la definición esencial que se usará para mostrar una tarjeta
flash. Tenga en FlashCardFragment cuenta que se deriva de la versión de Fragment la biblioteca
Android.Support.V4.App.Fragment de soporte de definida en. El constructor está vacío, por lo newInstance que el
Factory Method se usa para crear FlashCardFragment un nuevo en lugar de un constructor.
El OnCreateView método de ciclo de vida crea y configura TextView . Aumenta el diseño del fragmento TextView y
devuelve el TextView inflado al autor de la llamada. LayoutInflater y ViewGroup se pasan a OnCreateView para
que pueda aumentar el diseño. La savedInstanceState agrupación contiene datos OnCreateView que TextView
utiliza para volver a crear a partir de un estado guardado.
La vista del fragmento se infla explícitamente mediante la llamada a inflater.Inflate . El container argumento
es el elemento primario de la vista y false la marca indica al informador que no agregue la vista inplana al
elemento primario de la vista (se agregará cuando ViewPager se llame al método del GetItem adaptador más
adelante en este objeto). tutorial).
Agregar código de estado a FlashCardFragment
Al igual que una actividad, un fragmento Bundle tiene un que usa para guardar y recuperar su estado. En
FlashCardPager, Bundle se usa para guardar el texto de la pregunta y la respuesta de la tarjeta flash asociada. En
FlashCardFragment.CS, agregue las claves Bundle siguientes a la parte superior de FlashCardFragment la
definición de clase:

private static string FLASH_CARD_QUESTION = "card_question";


private static string FLASH_CARD_ANSWER = "card_answer";

Modifique el newInstance Factory Method para que cree un Bundle objeto y utilice las teclas anteriores para
almacenar la pregunta y el texto de respuesta que se han pasado en el fragmento una vez creada su instancia:

public static FlashCardFragment newInstance(String question, String answer)


{
FlashCardFragment fragment = new FlashCardFragment();

Bundle args = new Bundle();


args.PutString(FLASH_CARD_QUESTION, question);
args.PutString(FLASH_CARD_ANSWER, answer);
fragment.Arguments = args;

return fragment;
}

Modifique el método OnCreateView de ciclo de vida de los fragmentos para recuperar esta información de la
agrupación pasada y cargar el TextBox texto de la pregunta en el:

public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)


{
string question = Arguments.GetString(FLASH_CARD_QUESTION, "");
string answer = Arguments.GetString(FLASH_CARD_ANSWER, "");

View view = inflater.Inflate(Resource.Layout.flashcard_layout, container, false);


TextView questionBox = (TextView)view.FindViewById(Resource.Id.flash_card_question);
questionBox.Text = question;

return view;
}

La answer variable no se usa aquí, pero se utilizará más adelante cuando se agregue código de controlador de
eventos a este archivo.

Crear el adaptador
ViewPager utiliza un objeto de controlador de adaptador que se ViewPager encuentra entre y el origen de datos
(vea la ilustración del artículo adaptador de ViewPager). Para tener acceso a estos ViewPager datos, es necesario
proporcionar un adaptador personalizado derivado PagerAdapter de. Dado que en este ejemplo se usan
fragmentos, FragmentPagerAdapter se usa un PagerAdapter – FragmentPagerAdapter derivado de.
FragmentPagerAdapter representa cada página como Fragment que se mantiene de forma persistente en el
administrador de fragmentos durante el tiempo que el usuario puede volver a la página. A medida que el usuario
desliza el dedo por ViewPager las páginas FragmentPagerAdapter del, extrae información del origen de datos y la
Fragment usa para crear ViewPager s para que la muestre.

Al implementar un FragmentPagerAdapter , debe invalidar lo siguiente:


Recuento – Propiedad de solo lectura que devuelve el número de vistas (páginas) disponibles.
GetItem – Devuelve el fragmento que se va a mostrar para la página especificada.
Agregue un nuevo archivo denominado FlashCardDeckAdapter.CS y reemplace su contenido por el código
siguiente:

using System;
using Android.Views;
using Android.Widget;
using Android.Support.V4.App;

namespace FlashCardPager
{
class FlashCardDeckAdapter : FragmentPagerAdapter
{
public FlashCardDeckAdapter (Android.Support.V4.App.FragmentManager fm, FlashCardDeck flashCards)
: base(fm)
{
}

public override int Count


{
get { throw new NotImplementedException(); }
}

public override Android.Support.V4.App.Fragment GetItem(int position)


{
throw new NotImplementedException();
}
}
}

Este código codifica como código auxiliar FragmentPagerAdapter la implementación esencial. En las secciones
siguientes, cada uno de estos métodos se reemplaza por código de trabajo. El propósito del constructor es pasar el
administrador de fragmentos al constructor de FlashCardDeckAdapter la clase base.
Implementar el constructor de adaptador
Cuando la aplicación crea una instancia FlashCardDeckAdapter de, proporciona una referencia al administrador de
fragmentos y una FlashCardDeck instancia de. Agregue la siguiente variable miembro a la parte superior de
FlashCardDeckAdapter la clase en FlashCardDeckAdapter.CS:

public FlashCardDeck flashCardDeck;

Agregue la siguiente línea de código al FlashCardDeckAdapter constructor:

this.flashCardDeck = flashCards;

Esta línea de código almacena la FlashCardDeck instancia de FlashCardDeckAdapter que utilizará.


Recuento de implementaciones
La Count implementación es relativamente simple: devuelve el número de tarjetas flash de la baraja de tarjetas
flash. Reemplaza Count por el código siguiente:
public override int Count
{
get { return flashCardDeck.NumCards; }
}

La NumCards propiedad de FlashCardDeck devuelve el número de tarjetas flash (número de fragmentos) del
conjunto de datos.
Implementar GetItem
El GetItem método devuelve el fragmento asociado a la posición especificada. Cuando GetItem se llama a para
una posición en la baraja de la tarjeta flash, FlashCardFragment devuelve un configurado para mostrar el problema
de la tarjeta flash en esa posición. Reemplace el método GetItem con el código siguiente:

public override Android.Support.V4.App.Fragment GetItem(int position)


{
return (Android.Support.V4.App.Fragment)
FlashCardFragment.newInstance (
flashCardDeck[position].Problem, flashCardDeck[position].Answer);
}

Este código hace lo siguiente:


1. Busca la cadena de problema matemático en la FlashCardDeck baraja para la posición especificada.
2. Busca la cadena de respuesta en la FlashCardDeck baraja para la posición especificada.
3. Llama al FlashCardFragment Factory Method newInstance , pasando el problema de la tarjeta flash y las
cadenas de respuesta.
4. Crea y devuelve una nueva tarjeta Fragment Flash que contiene la pregunta y el texto de respuesta de esa
posición.
Fragment TextBoxCuando representa el position en position , muestra el que contiene la cadena de problema
matemático que reside en en la baraja de tarjetas flash. ViewPager

Agregar el adaptador a ViewPager


Ahora que FlashCardDeckAdapter está implementado, es el momento de agregarlo ViewPager al. En
MainActivity.CS, agregue la siguiente línea de código al final del OnCreate método:

FlashCardDeckAdapter adapter =
new FlashCardDeckAdapter(SupportFragmentManager, flashCards);
viewPager.Adapter = adapter;

Este código crea una instancia FlashCardDeckAdapter de, pasando SupportFragmentManager en el primer argumento.
(La SupportFragmentManager propiedad de FragmentActivity se usa para obtener una referencia – FragmentManager
a para obtener más información sobre FragmentManager , vea administrar fragmentos).
La implementación básica ahora se ha – completado compilar y ejecutar la aplicación. Debería ver que la primera
imagen de la baraja de la tarjeta flash aparece en la pantalla, como se muestra a la izquierda en la siguiente
captura de pantalla. Deslice el dedo hacia la izquierda para ver más tarjetas flash y luego deslice el dedo hacia la
derecha para retroceder a través de la baraja de tarjetas flash:
Agregar un indicador de buscapersonas
Esta implementación ViewPager mínima muestra cada tarjeta flash en la baraja, pero no proporciona ninguna
indicación de dónde se encuentra el usuario dentro de la baraja. El siguiente paso consiste en agregar un
PagerTabStrip . PagerTabStrip Informa al usuario sobre el número de problema que se muestra y proporciona el
contexto de navegación al mostrar una sugerencia de las tarjetas flash anteriores y siguientes.
Abra Resources/layout/main. axml y PagerTabStrip agregue un al diseño:

<?xml version="1.0" encoding="utf-8"?>


<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<android.support.v4.view.PagerTabStrip
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:paddingBottom="10dp"
android:paddingTop="10dp"
android:textColor="#fff" />

</android.support.v4.view.ViewPager>

Al compilar y ejecutar la aplicación, debería ver el vacío PagerTabStrip mostrado en la parte superior de cada
tarjeta flash:
Mostrar un título
Para agregar un título a cada pestaña de página, implemente el GetPageTitleFormatted método en el adaptador.
ViewPager llama GetPageTitleFormatted a (si está implementado) para obtener la cadena de título que describe la
página en la posición especificada. Agregue el método siguiente a la FlashCardDeckAdapter clase en
FlashCardDeckAdapter.CS:

public override Java.Lang.ICharSequence GetPageTitleFormatted(int position)


{
return new Java.Lang.String("Problem " + (position + 1));
}

Este código convierte la posición en la baraja de la tarjeta flash en un número de problema. La cadena resultante
se convierte en una Java String que se devuelve ViewPager a. Al ejecutar la aplicación con este nuevo método,
cada página muestra el número del problema en el PagerTabStrip :
Puede deslizarse hacia atrás y hacia delante para ver el número del problema en la baraja de la tarjeta flash que se
muestra en la parte superior de cada tarjeta flash.

Controlar los datos proporcionados por el usuario


FlashCardPager presenta una serie de tarjetas flash basadas en fragmentos en un ViewPager , pero aún no tiene
una manera de revelar la respuesta para cada problema. En esta sección, se agrega un controlador de eventos a
FlashCardFragment para mostrar la respuesta cuando el usuario puntea en el texto del problema de la tarjeta flash.

Abra FlashCardFragment.CS y agregue el código siguiente al final del OnCreateView método justo antes de que
la vista se devuelva al autor de la llamada:

questionBox.Click += delegate
{
Toast.MakeText(Activity.ApplicationContext,
"Answer: " + answer, ToastLength.Short).Show();
};

Este Clickcontrolador de eventos muestra la respuesta en una notificación de sistema que aparece cuando el
TextBox usuario pulsa el. La answer variable se inicializó anteriormente cuando se leyó información de estado de
la agrupación que se OnCreateView pasó a. Compile y ejecute la aplicación y, a continuación, puntee en el texto del
problema en cada tarjeta flash para ver la respuesta:

En el FlashCardPager presentado en este tutorial se MainActivity usa un FragmentActivity derivado de, pero
también se MainActivity puede AppCompatActivity derivar de (que también proporciona compatibilidad para
administrar fragmentos). Para ver un AppCompatActivity ejemplo, consulte FlashCardPager en la galería de
ejemplos.

Resumen
En este tutorial se proporciona un ejemplo paso a paso de cómo compilar una ViewPager aplicación basada en
Basic Fragment mediante s. Se presentó un ejemplo de origen de datos que contiene preguntas y respuestas sobre
ViewPager tarjetas flash, un diseño para mostrar las tarjetas FragmentPagerAdapter Flash y una subclase
ViewPager que conecta con el origen de datos. Para ayudar al usuario a desplazarse por las tarjetas flash, se
incluyeron instrucciones que explican PagerTabStrip cómo agregar un para mostrar el número del problema en la
parte superior de cada página. Por último, se ha agregado código de control de eventos para mostrar la respuesta
cuando el usuario pulsa un problema con la tarjeta flash.

Vínculos relacionados
FlashCardPager (ejemplo)
Vista Web de Xamarin. Android
27/07/2019 • 5 minutes to read • Edit Online

WebView permite crear su propia ventana para ver páginas web (o incluso desarrollar un explorador completo). En
este tutorial, creará un sencillo Activity que puede ver y navegar por las páginas Web.
Cree un nuevo proyecto denominado HelloWebView.
Abra Resources/layout/main. axml e inserte lo siguiente:

<?xml version="1.0" encoding="utf-8"?>


<WebView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/webview"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />

Dado que esta aplicación tendrá acceso a Internet, debe agregar los permisos adecuados al archivo de manifiesto
de Android. Abra las propiedades del proyecto para especificar los permisos que la aplicación necesita para
funcionar. Habilite el INTERNET permiso como se muestra a continuación:

Ahora Abra MainActivity.CS y agregue una directiva using para WebKit:

using Android.Webkit;

En la parte superior de MainActivity la clase, declare un WebView objeto:

WebView web_view;

Cuando se pide a la vista web que cargue una dirección URL, delegará de forma predeterminada la solicitud en el
explorador predeterminado. Para hacer que la vista web cargue la dirección URL (en lugar del explorador
predeterminado), debe subclase Android.Webkit.WebViewClient e invalidar el ShouldOverriderUrlLoading método.
Se proporciona una instancia de WebViewClient este personalizado WebView al. Para ello, agregue la siguiente
HelloWebViewClient clase anidada en: MainActivity

public class HelloWebViewClient : WebViewClient


{
public override bool ShouldOverrideUrlLoading (WebView view, string url)
{
view.LoadUrl(url);
return false;
}
}

Cuando ShouldOverrideUrlLoading WebView devuelve false , indica a Android que la instancia actual ha
controlado la solicitud y que no es necesaria ninguna otra acción.
Si tiene como destino el nivel de API 24 o posterior, use la sobrecarga ShouldOverrideUrlLoading de que toma
IWebResourceRequest un para el segundo argumento en lugar de string un:

public class HelloWebViewClient : WebViewClient


{
// For API level 24 and later
public override bool ShouldOverrideUrlLoading (WebView view, IWebResourceRequest request)
{
view.LoadUrl(request.Url.ToString());
return false;
}
}

A continuación, use el siguiente código para OnCreate() el método):

protected override void OnCreate (Bundle bundle)


{
base.OnCreate (bundle);

// Set our view from the "main" layout resource


SetContentView (Resource.Layout.Main);

web_view = FindViewById<WebView> (Resource.Id.webview);


web_view.Settings.JavaScriptEnabled = true;
web_view.SetWebViewClient(new HelloWebViewClient());
web_view.LoadUrl ("https://www.xamarin.com/university");
}

Esto inicializa el miembro con el Activity del diseño y habilita JavaScript para el WebView con = true
WebView
(
JavaScriptEnabled vea la llamada C# desde JavaScript receta para obtener información sobre cómo llamar a#
funciones de C desde JavaScript). Por último, se carga una página web inicial LoadUrl(String) con.
Compile y ejecute la aplicación. Debería ver una aplicación sencilla de visor de páginas web como la que se ve en la
siguiente captura de pantalla:
Para controlar la pulsación de tecla del botón atrás , agregue la siguiente instrucción using:

using Android.Views;

A continuación, agregue el método siguiente dentro HelloWebView de la actividad:


public override bool OnKeyDown (Android.Views.Keycode keyCode, Android.Views.KeyEvent e)
{
if (keyCode == Keycode.Back && web_view.CanGoBack ())
{
web_view.GoBack ();
return true;
}
return base.OnKeyDown (keyCode, e);
}

El OnKeyDown(int, KeyEvent) se llamará al método de devolución de llamada siempre que se presione un botón
mientras la actividad se está ejecutando. La condición dentro de usa KeyEvent el para comprobar si la tecla
presionada es el WebView botón atrás y si es realmente capaz de desplazarse hacia atrás (si tiene un historial). Si
ambos son true, se llama GoBack() al método, que navegará hacia atrás un paso en el WebView historial. La true
devolución indica que el evento se ha controlado. Si no se cumple esta condición, el evento se devuelve al sistema.
Vuelva a ejecutar la aplicación. Ahora debería poder seguir los vínculos y navegar hacia atrás por el historial de
páginas:

Algunas partes de esta página son modificaciones basadas en el trabajo creado y compartido por el proyecto de
código abierto de Android y que se usan según los términos descritos en la licencia de atribución deCreative
Commons 2,5.

Vínculos relacionados
Call C# from JavaScript (Llamada a C# desde JavaScript)
Android.Webkit.WebView
KeyEvent
Características de la plataforma
13/07/2019 • 8 minutes to read • Edit Online

Los documentos de esta sección tratan características específicas de Android. Aquí encontrará temas sobre
fragmentos, trabajo con mapas y encapsulamiento de datos con los proveedores de contenido.

Android Beam
Haz de Android es una nueva tecnología de cerca de campo Communication (NFC ) en Android 4 que permite
compartir información a través de NFC en cerca de las aplicaciones.

Working with Files (Trabajo con archivos)


En esta sección se describe cómo tener acceso a archivos en Xamarin.Android.

Autenticación de huella digital


Esta sección describe cómo usar la autenticación con huella digital, por primera vez en Android 6.0 a una aplicación
de Xamarin.Android.

Distribuidor de trabajo de Firebase


Esta guía aborda el distribuidor de trabajo de Firebase y cómo usarlo para simplificar los trabajos en segundo
plano en ejecución en una aplicación de Xamarin.Android.

Fragmentos
Android 3.0 presentó fragmentos, que muestra cómo admitir diseños más flexibles de los muchas diferentes
tamaños de pantalla que se encuentra en teléfonos y tabletas. En este artículo tratará cómo usar fragmentos para
desarrollar aplicaciones de Xamarin.Android y también cómo admitir fragmentos en Android dispositivos (API
nivel 11) 3.0.

App-Linking
Esta guía describirá cómo es compatible con Android 6.0 aplicación vinculación, una técnica que permite que las
aplicaciones móviles responder a las direcciones URL en los sitios Web. Trataremos cómo implementar la
vinculación a la aplicación en una aplicación de Android 6.0 y cómo configurar un sitio Web para conceder
permisos a la aplicación móvil para administrar vínculos de la aplicación para el dominio.

Android circular 9
En este artículo se proporciona un esquema de las nuevas características de Android circular, se explica cómo
preparar Xamarin.Android para el desarrollo de Android circular y proporciona una aplicación de ejemplo que
ilustra cómo usar las nuevas Android circular para mostrar recorte y notificación de características de Aplicaciones
de Xamarin.Android.

Android 8 Oreo
En este artículo se proporciona un resumen de las nuevas características de Android Oreo, se explica cómo
preparar Xamarin.Android para el desarrollo de Android Oreo y proporciona vínculos a aplicaciones de ejemplo
que muestran cómo usar las características de Android Oreo en aplicaciones de Xamarin.Android.

Android 7 Nougat
En este artículo se proporciona una descripción general de las nuevas características introducidas en Android
Nougat 7.0.

Android 6 Marshmallow
En este artículo se proporciona una descripción general de las nuevas características introducidas en Android
Marshmallow 6.0.

Android 5 Lollipop
Esta guía proporciona información general sobre las nuevas características de Android 5.0 Lollipop como tema de
Material, CardView, RecyclerView y cabezales de notificaciones, e incluye vínculos a detallados artículos que le
ayudarán a usan estas nuevas características en la aplicación.

Android 4.4 KitKat


Android 4.4 (KitKat) viene equipada con gran cantidad de características para los usuarios y desarrolladores. Esta
guía destaca algunas de estas características y proporciona ejemplos de código y los detalles de implementación
que le ayudarán a sacar el máximo provecho KitKat.

Android 4.1 Jelly Bean


Este documento proporcionará una descripción general de las nuevas características para desarrolladores que se
introdujeron en Android 4.1. Estas características incluyen: mejorada de las notificaciones, las actualizaciones a
Android carretera para compartir archivos de gran tamaño, las actualizaciones de detección de redes de
multimedia, peer-to-peer, animaciones, nuevos permisos.

Android 4.0 Ice Cream Sandwich


En este artículo se describe algunas de las nuevas características disponibles para los desarrolladores de
aplicaciones con el API de Android 4 - Ice Cream Sandwich. Se tratan varias tecnologías nuevas de interfaz de
usuario y, a continuación, examina una variedad de nuevas capacidades que ofrece Android 4 para compartir datos
entre aplicaciones y dispositivos.

Trabajar con el manifiesto de Android


Este artículo presentan el archivo AndroidManifest.xml, y cómo lo puede usar para controlar la funcionalidad y
describir los requisitos de un Mono para la aplicación de Android.

Introducción a los proveedores de contenido


Un ContentProvider encapsula un repositorio de datos y proporciona una API para acceder a ella. El proveedor
existe como parte de una aplicación Android que también proporciona una interfaz de usuario para mostrar y
administrar los datos. La principal ventaja de usar un proveedor de contenido es permitir que otras aplicaciones
acceder fácilmente a los datos encapsulados con un objeto de cliente de proveedor (denominado un
ContentResolver). Juntos, un proveedor de contenido y el Solucionador de contenido ofrecen una API coherente
entre aplicaciones de acceso a datos que sea fácil de crear y consumir. Este documento muestra cómo obtener
acceso y generar ContentProviders con Xamarin.Android.
Mapas y ubicación
En esta sección se explica cómo usar mapas y ubicación con Xamarin.Android. Abarca todo, desde el
aprovechamiento de la aplicación como mapas integrados para utilizar el v2 de la API de Google asigna Android
directamente. Además, explica cómo usar una única API para trabajar con servicios de ubicación, que usan la
triangulación de telefonía móvil para permitir que una aplicación obtener correcciones de ubicación, ubicación de
Wi-Fi y GPS.

Voz de Android
Esta sección describe cómo usar el Android texto a voz y voz a las instalaciones de texto. También cubre la
instalación de paquetes de idioma y la interpretación del texto hablado con el dispositivo.

Enlace de una biblioteca Java


Esta guía explica cómo incorporar bibliotecas de Java en aplicaciones de Xamarin.Android mediante la creación de
una biblioteca de enlaces.

Integración con Java


En este artículo se proporciona información general de las formas en que los desarrolladores pueden reutilizar los
componentes de Java existentes en aplicaciones de Xamarin.Android.

Renderscript
Esta guía aborda Renderscript.
Android Beam
16/08/2019 • 4 minutes to read • Edit Online

El rayo de Android es una tecnología de transmisión de datos en proximidad (NFC ) introducida en Android 4,0
que permite a las aplicaciones compartir información a través de NFC en estrecha proximidad.

El rayo de Android funciona insertando mensajes sobre NFC cuando dos dispositivos están dentro del alcance.
Los dispositivos de 4cm entre sí pueden compartir datos con el rayo de Android. Una actividad en un dispositivo
crea un mensaje y especifica una actividad (o actividades) que puede controlar la inserción. Cuando la actividad
especificada está en primer plano y los dispositivos están dentro del alcance, el rayo de Android enviará el mensaje
al segundo dispositivo. En el dispositivo receptor, se invoca una intención que contiene los datos del mensaje.
Android admite dos maneras de configurar mensajes con el rayo de Android:
SetNdefPushMessage -Antes de que se inicie el rayo de Android, una aplicación puede llamar a
SetNdefPushMessage para especificar un NdefMessage para insertarlo sobre NFC y la actividad que lo
está insertando. Este mecanismo se utiliza mejor cuando un mensaje no cambia mientras una aplicación
está en uso.
SetNdefPushMessageCallback-Cuando se inicia el rayo de Android, una aplicación puede controlar una
devolución de llamada para crear un NdefMessage. Este mecanismo permite que se retrase la creación de
mensajes hasta que los dispositivos se encuentren dentro del alcance. Admite escenarios en los que el
mensaje puede variar en función de lo que sucede en la aplicación.
En cualquier caso, para enviar datos con el rayo de Android, una aplicación NdefMessage envía un y empaqueta los
datos NdefRecords en varios. Echemos un vistazo a los puntos clave que deben abordarse antes de que podamos
desencadenar el haz de Android. En primer lugar, trabajaremos con el estilo de devolución de NdefMessage llamada
de creación de.

Crear un mensaje
Podemos registrar devoluciones de llamada NfcAdapter con un en el OnCreate método de la actividad. Por
ejemplo, suponiendo que NfcAdapter un mNfcAdapter nombre se declara como una variable de clase en la
actividad, podemos escribir el código siguiente para crear la devolución de llamada que construirá el mensaje:

mNfcAdapter = NfcAdapter.GetDefaultAdapter (this);


mNfcAdapter.SetNdefPushMessageCallback (this, this);

La actividad, que implementa NfcAdapter.ICreateNdefMessageCallback , se pasa SetNdefPushMessageCallback al


método anterior. Cuando se inicia el rayo de Android, el sistema CreateNdefMessage llamará a, desde el que la
NdefMessage actividad puede construir un, como se muestra a continuación:

public NdefMessage CreateNdefMessage (NfcEvent evt)


{
DateTime time = DateTime.Now;
var text = ("Beam me up!\n\n" + "Beam Time: " +
time.ToString ("HH:mm:ss"));
NdefMessage msg = new NdefMessage (
new NdefRecord[]{ CreateMimeRecord (
"application/com.example.android.beam",
Encoding.UTF8.GetBytes (text)) });
} };
return msg;
}

public NdefRecord CreateMimeRecord (String mimeType, byte [] payload)


{
byte [] mimeBytes = Encoding.UTF8.GetBytes (mimeType);
NdefRecord mimeRecord = new NdefRecord (
NdefRecord.TnfMimeMedia, mimeBytes, new byte [0], payload);
return mimeRecord;
}

Recibir un mensaje
En el lado receptor, el sistema invoca una intención con la ActionNdefDiscovered acción, desde la que se puede
extraer el NdefMessage como se indica a continuación:

IParcelable [] rawMsgs = intent.GetParcelableArrayExtra (NfcAdapter.ExtraNdefMessages);


NdefMessage msg = (NdefMessage) rawMsgs [0];

Para obtener un ejemplo de código completo que usa el rayo de Android, que se muestra en la siguiente captura
de pantalla, vea la demostración de rayos de Android en la galería de ejemplo.
Vínculos relacionados
Demo de rayos de Android (ejemplo)
Presentación del bocadillo de helado
Plataforma Android 4,0
Trabajar con el manifiesto de Android
16/08/2019 • 13 minutes to read • Edit Online

Archivo AndroidManifest. XML es un archivo eficaz de la plataforma Android que le permite describir la
funcionalidad y los requisitos de la aplicación para Android. Sin embargo, no es fácil trabajar con él. Xamarin.
Android ayuda a minimizar esta dificultad al permitirle agregar atributos personalizados a las clases, que se
usarán para generar automáticamente el manifiesto. Nuestro objetivo es que el 99% de nuestros usuarios nunca
deben modificar manualmente archivo AndroidManifest. XML.
Archivo AndroidManifest. XML se genera como parte del proceso de compilación y el XML que se encuentra
en las propiedades/archivo AndroidManifest. XML se combina con el XML que se genera a partir de los
atributos personalizados. El archivo AndroidManifest. XML combinado resultante se encuentra en el
subdirectorio obj ; por ejemplo, reside en obj/Debug/Android/archivo AndroidManifest. XML para las
compilaciones de depuración. El proceso de combinación es trivial: usa atributos personalizados en el código
para generar elementos XML e inserta esos elementos en archivo AndroidManifest. XML.

Conceptos básicos
En tiempo de compilación, los ensamblados se examinan abstract en busca de clases que no son de [Activity]
la actividad y tienen el atributo declarado en ellos. A continuación, usa estas clases y atributos para generar el
manifiesto. Por ejemplo, considere el siguiente código:

namespace Demo
{
public class MyActivity : Activity
{
}
}

Esto hace que no se genere nada en archivo AndroidManifest. XML. Si desea que se <activity/> genere un
elemento, debe utilizar el [Activity] atributo personalizado:

namespace Demo
{
[Activity]
public class MyActivity : Activity
{
}
}

Este ejemplo hace que se agregue el siguiente fragmento XML a archivo AndroidManifest. XML:

<activity android:name="md5a7a3c803e481ad8926683588c7e9031b.MainActivity" />

El [Activity] atributo no tiene ningún efecto abstract en los tipos; abstract los tipos se omiten.
Nombre de actividad
A partir de Xamarin. Android 5,1, el nombre de tipo de una actividad se basa en el MD5SUM del nombre
calificado con el ensamblado del tipo que se va a exportar. Esto permite proporcionar el mismo nombre
completo a partir de dos ensamblados diferentes y no obtener un error de empaquetado. (Antes de Xamarin.
Android 5,1, el nombre de tipo predeterminado de la actividad se creó a partir del espacio de nombres en
minúsculas y el nombre de clase).
Si desea invalidar este valor predeterminado y especificar explícitamente el nombre de la actividad, use Name la
propiedad:

[Activity (Name="awesome.demo.activity")]
public class MyActivity : Activity
{
}

Este ejemplo genera el siguiente fragmento XML:

<activity android:name="awesome.demo.activity" />

Nota: debe usar la Name propiedad solo por motivos de compatibilidad con versiones anteriores, ya que este
cambio de nombre puede ralentizar la búsqueda de tipos en tiempo de ejecución. Si tiene código heredado que
espera que el nombre de tipo predeterminado de la actividad se base en el espacio de nombres en minúsculas y
el nombre de clase, consulte nombres de contenedor de Android Callable para obtener sugerencias sobre el
mantenimiento de la compatibilidad.
Barra de título de actividad
De forma predeterminada, Android proporciona una barra de título a la aplicación cuando se ejecuta. El valor
utilizado para este es /manifest/application/activity/@android:label . En la mayoría de los casos, este valor será
diferente del nombre de clase. Para especificar la etiqueta de la aplicación en la barra de título, Label use la
propiedad. Por ejemplo:

[Activity (Label="Awesome Demo App")]


public class MyActivity : Activity
{
}

Este ejemplo genera el siguiente fragmento XML:

<activity android:label="Awesome Demo App"


android:name="md5a7a3c803e481ad8926683588c7e9031b.MainActivity" />

Iniciable desde Application selector


De forma predeterminada, la actividad no se mostrará en la pantalla del iniciador de aplicaciones de Android.
Esto se debe a que es probable que haya muchas actividades en la aplicación y no desea un icono para cada una
de ellas. Para especificar la que se debe iniciar desde el iniciador de la aplicación, MainLauncher use la propiedad.
Por ejemplo:

[Activity (Label="Awesome Demo App", MainLauncher=true)]


public class MyActivity : Activity
{
}

Este ejemplo genera el siguiente fragmento XML:


<activity android:label="Awesome Demo App"
android:name="md5a7a3c803e481ad8926683588c7e9031b.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

Icono de actividad
De forma predeterminada, se proporcionará a la actividad el icono del iniciador predeterminado proporcionado
por el sistema. Para usar un icono personalizado, agregue primero el . png a Resources/drawable, establezca
su acción de compilación en AndroidResourcey Icon , a continuación, use la propiedad para especificar el
icono que se va a usar. Por ejemplo:

[Activity (Label="Awesome Demo App", MainLauncher=true, Icon="@drawable/myicon")]


public class MyActivity : Activity
{
}

Este ejemplo genera el siguiente fragmento XML:

<activity android:icon="@drawable/myicon" android:label="Awesome Demo App"


android:name="md5a7a3c803e481ad8926683588c7e9031b.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

Permisos
Al agregar permisos al manifiesto de Android (como se describe en Agregar permisos para el manifiesto de
Android), estos permisos se registran en Properties/archivo AndroidManifest. XML. Por ejemplo, si
establece el INTERNET permiso, se agrega el elemento siguiente a Properties/archivo AndroidManifest. XML:

<uses-permission android:name="android.permission.INTERNET" />

Las compilaciones de depuración establecen automáticamente algunos permisos para INTERNET facilitar la –
depuración (como y READ_EXTERNAL_STORAGE ). esta configuración solo se establece en el archivo
OBJ/Debug/Android/archivo AndroidManifest. XML generado y no se muestra como habilitado en el
Configuración de permisos necesarios .
Por ejemplo, si examina el archivo de manifiesto generado en obj/Debug/Android/archivo
AndroidManifest. XML, es posible que vea los siguientes elementos de permiso agregados:

<uses-permission android:name="android.permission.INTERNET" />


<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

En la versión de compilación de lanzamiento del manifiesto (en obj/Debug/Android/archivo


AndroidManifest. XML ), estos permisos no se configuran automáticamente. Si observa que el cambio a una
compilación de versión hace que la aplicación pierda un permiso que estaba disponible en la compilación de
depuración, compruebe que ha establecido explícitamente este permiso en la configuración de permisos
necesarios para la aplicación (consulte compilación > Android Aplicación en Visual Studio para Mac;
consulte propiedades > manifiesto de Android en Visual Studio).
Características avanzadas
Acciones y características de intención
El manifiesto de Android proporciona una manera de describir las funcionalidades de su actividad. Esto se hace a
través de las intenciones y el [IntentFilter] atributo personalizado. Puede especificar qué acciones son
adecuadas para su actividad con el IntentFilter constructor y qué categorías son adecuadas con el Categories
propiedad. Se debe proporcionar al menos una actividad (que es el motivo por el que se proporcionan las
actividades en el constructor). [IntentFilter] se puede proporcionar varias veces y cada una de ellas tiene como
resultado <intent-filter/> un elemento independiente <activity/> dentro de. Por ejemplo:

[Activity (Label="Awesome Demo App", MainLauncher=true, Icon="@drawable/myicon")]


[IntentFilter (new[]{Intent.ActionView},
Categories=new[]{Intent.CategorySampleCode, "my.custom.category"})]
public class MyActivity : Activity
{
}

Este ejemplo genera el siguiente fragmento XML:

<activity android:icon="@drawable/myicon" android:label="Awesome Demo App"


android:name="md5a7a3c803e481ad8926683588c7e9031b.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.SAMPLE_CODE" />
<category android:name="my.custom.category" />
</intent-filter>
</activity>

Elemento Application
El manifiesto de Android también proporciona una manera de declarar las propiedades de toda la aplicación.
Esto se hace a través <application> del elemento y su homólogo, el atributo personalizado de la aplicación .
Tenga en cuenta que se trata de una configuración de toda la aplicación (en todo el ensamblado) en lugar de la
configuración por actividad. Normalmente, se declaran <application> las propiedades de toda la aplicación y, a
continuación, se invalidan estas opciones (según sea necesario) en función de cada actividad.
Por ejemplo, se agrega Application el atributo siguiente a AssemblyInfo.CS para indicar que se puede
depurar la aplicación, que su nombre legible para el usuario es mi aplicacióny que usa el Theme.Light estilo
como tema predeterminado para todos los operaciones

[assembly: Application (Debuggable=true,


Label="My App",
Theme="@android:style/Theme.Light")]

Esta declaración hace que se genere el siguiente fragmento XML en obj/Debug/Android/archivo


AndroidManifest. XML:

<application android:label="My App"


android:debuggable="true"
android:theme="@android:style/Theme.Light"
... />
En este ejemplo, todas las actividades de la aplicación tendrán como valor Theme.Light predeterminado el estilo.
Si establece el tema de una actividad en Theme.Dialog , solo esa actividad usará el Theme.Dialog estilo, mientras
que todas las demás actividades de la aplicación tendrán como Theme.Light valor predeterminado el estilo
establecido <application> en el elemento.
El Application elemento no es la única manera de configurar <application> atributos. Como alternativa, puede
insertar atributos directamente en el <application> elemento de Properties/archivo AndroidManifest. XML.
Estos valores se combinan en el último <application> elemento que reside en obj/Debug/Android/archivo
AndroidManifest. XML. Tenga en cuenta que el contenido de las propiedades/archivo AndroidManifest.
XML siempre invalida los datos proporcionados por los atributos personalizados.
Hay muchos atributos de toda la aplicación que se pueden configurar en el <application> elemento. para
obtener más información sobre esta configuración, vea la sección propiedades públicas de ApplicationAttribute.

Lista de atributos personalizados


Android. app. ActivityAttribute : Genera un fragmento de XML de /manifest/Application/Activity
Android. app. ApplicationAttribute : Genera un fragmento de XML de /manifest/Application
Android. app. InstrumentationAttribute : Genera un fragmento de XML de /manifest/Instrumentation
Android. app. IntentFilterAttribute : Genera un fragmento de XML de //Intent-Filter
Android. app. MetaDataAttribute : Genera un fragmento de XML de //meta-data
Android. app. PermissionAttribute : Genera un fragmento de XML de //Permission
Android. app. PermissionGroupAttribute : Genera un fragmento de XML de //Permission-Group
Android. app. PermissionTreeAttribute : Genera un fragmento de XML de //Permission-Tree
Android. app. ServiceAttribute : Genera un fragmento de XML de /manifest/Application/Service
Android.App.UsesLibraryAttribute : Genera un fragmento de XML de /manifest/Application/uses-Library
Android.App.UsesPermissionAttribute : Genera un fragmento de XML de /manifest/uses-Permission
Android. Content. BroadcastReceiverAttribute : Genera un fragmento de XML de
/manifest/Application/Receiver
Android. Content. ContentProviderAttribute : Genera un fragmento de XML de
/manifest/Application/Provider
Android. Content. GrantUriPermissionAttribute : Genera un fragmento de XML de
/manifest/Application/Provider/Grant-URI-Permission
Almacenamiento de archivos y acceso con
Xamarin.Android
11/07/2019 • 15 minutes to read • Edit Online

Es un requisito común para aplicaciones Android manipular archivos – guardado de imágenes, descarga de
documentos o exportar datos para compartir con otros programas. Android (que se basa en Linux) es compatible
con esto proporcionando espacio para almacenamiento de archivos. Android agrupa el sistema de archivos en dos
tipos diferentes de almacenamiento:
Almacenamiento interno – se trata de una parte del sistema de archivos que solo puede tener acceso la
aplicación o el sistema operativo.
Almacenamiento externo – se trata de una partición para el almacenamiento de archivos que sea accesible
por todas las aplicaciones, el usuario y, posiblemente, otros dispositivos. En algunos dispositivos,
almacenamiento externo puede ser extraíble (por ejemplo, una tarjeta SD ).
Estas agrupaciones son conceptuales sólo y necesariamente no hacen referencia a una sola partición o el directorio
en el dispositivo. Un dispositivo Android siempre proporcionará la partición para almacenamiento interno y
externo. Es posible que algunos dispositivos pueden tener varias particiones que se consideran almacenamiento
externo. Independientemente de la partición de las API para leer, escribir o creación de archivos es el mismo. Hay
dos conjuntos de API que puede usar una aplicación de Xamarin.Android para el acceso de archivo:
1. Las API de .NET (proporcionado por Mono y ajustado por Xamarin.Android) – entre ellos se incluyen la
aplicaciones auxiliares de sistema de archivos proporcionada por Xamarin.Essentials. Las API de .NET
proporcionan la mejor compatibilidad multiplataforma y por lo tanto se incluirá el objetivo de esta guía en estas
API.
2. El acceso a archivos de Java native API (proporcionado por Java y ajustado por Xamarin.Android) –
Java proporciona sus propias API para leer y escribir archivos. Estas son una alternativa a las API. NET,
completamente aceptable, pero son específicas de Android y no son adecuadas para las aplicaciones que están
diseñadas para ser multiplataforma.
Leer y escribir en archivos son casi idéntico en Xamarin.Android y sirve para cualquier otra aplicación. NET. La
aplicación de Xamarin.Android determina la ruta de acceso al archivo que se manipulará, a continuación, usa
estándar .NET expresiones de acceso a archivos. Dado que las rutas de acceso reales a almacenamiento interno y
externo pueden variar de un dispositivo a otro o desde la versión de Android para la versión de Android, no se
recomienda codificar de forma rígida la ruta de acceso a los archivos. En su lugar, utilice las APIs Xamarin.Android
para determinar la ruta de acceso a archivos. De este modo, las API de .NET para leer y escribir archivos expone las
API nativas de Android que le ayudarán a determinar la ruta de acceso a los archivos de almacenamiento interno y
externo.
Antes de tratar las API implicadas con acceso de archivo, es importante comprender algunos de los detalles
relacionados con el almacenamiento interno y externo. Esto se explicará en la sección siguiente.

Almacenamiento externo de vs interno


Conceptualmente, el almacenamiento interno y externo son muy similares – son ambos lugares en que una
aplicación de Xamarin.Android puede guardar archivos. Esta similitud puede resultar confusa para los
desarrolladores que no están familiarizados con Android ya no está claro cuando una aplicación debe usar el
almacenamiento externo de vs de almacenamiento interno.
Almacenamiento interno que hace referencia a la memoria no volátil Android asigna al sistema operativo, el Apk y
para las aplicaciones individuales. Este espacio no es accesible, excepto por el sistema operativo o las aplicaciones.
Android asignará un directorio en la partición del almacenamiento interno para cada aplicación. Cuando se
desinstala la aplicación, también se eliminarán todos los archivos que se mantienen en almacenamiento interno en
ese directorio. Almacenamiento interno es ideal para los archivos que solo son accesibles para la aplicación y que
no se comparta con otras aplicaciones o tendrá muy poco valor una vez que la aplicación se desinstala. En Android
6.0 o posterior, copia archivos de almacenamiento interno pueden ser automáticamente mediante el uso de Google
el característica de copia de seguridad automática de Android 6.0. Almacenamiento interno tiene las siguientes
desventajas:
No se puede compartir archivos.
Los archivos se eliminarán cuando se desinstala la aplicación.
El espacio disponible en almacenamiento interno quizás limitado.
Almacenamiento externo hace referencia al almacenamiento de archivos que no es de almacenamiento interno y
no está accesible a una aplicación de forma exclusiva. Es el propósito principal de almacenamiento externo
proporcionar un lugar para colocar los archivos que están diseñados para compartirse entre aplicaciones o que
son demasiado grandes para caber en el almacenamiento interno. La ventaja de almacenamiento externo es que
normalmente tiene mucho más espacio para los archivos que el almacenamiento interno. Sin embargo, el
almacenamiento externo no se garantiza que siempre estén presentes en un dispositivo y puede requerir un
permiso especial del usuario para acceder a él.

NOTE
Para los dispositivos que admiten varios usuarios, Android proporciona a cada usuario su propio directorio de
almacenamiento interno y externo. Este directorio no es accesible a otros usuarios en el dispositivo. Esta separación es
invisible para las aplicaciones siempre y cuando lo hacen no codificar las rutas de acceso a los archivos de almacenamiento
interno o externo.

Como regla general, las aplicaciones de Xamarin.Android deben prefiere guardar los archivos en almacenamiento
interno cuando resulta razonable y se basan en un almacenamiento externo cuando es necesario compartir con
otras aplicaciones, son muy grandes o deberían conservarse, incluso si la aplicación se desinstala los archivos. Por
ejemplo, un archivo de configuración es más adecuado para un almacenamiento interno porque no tiene ninguna
importancia, excepto para la aplicación que lo crea. En cambio, las fotos son buenos candidatos para el
almacenamiento externo. Pueden ser muy grandes y en muchos casos el usuario desee compartirlos o acceder a
ellos incluso si se desinstala la aplicación.
Esta guía se centra en el almacenamiento interno. Consulte la guía almacenamiento externo para obtener más
información sobre el uso de almacenamiento externo en una aplicación de Xamarin.Android.

Trabajar con el almacenamiento interno


El directorio de almacenamiento interno para una aplicación viene determinada por el sistema operativo y se
expone a aplicaciones de Android mediante el Android.Content.Context.FilesDir propiedad. Esto devolverá un
Java.IO.File objeto que representa el directorio que ha dedicado Android exclusivamente para la aplicación. Por
ejemplo, una aplicación con el nombre del paquete com.companyname el directorio de almacenamiento interno
podría ser:

/data/user/0/com.companyname/files

Este documento se hará referencia en el directorio de almacenamiento interno como interno_almacenamiento.


IMPORTANT
La ruta de acceso exacta en el directorio de almacenamiento interno puede variar de dispositivo a dispositivo y entre las
versiones de Android. Por este motivo, las aplicaciones deben no estricta la ruta de acceso en el directorio de
almacenamiento interno de los archivos de código y en su lugar, use las APIs Xamarin.Android, como
System.Environment.GetFolderPath() .

Para maximizar el uso compartido de código, deben usar las aplicaciones de Xamarin.Android (o aplicaciones de
Xamarin.Forms para Xamarin.Android) la System.Environment.GetFolderPath() método. En Xamarin.Android, este
método devolverá una cadena para un directorio que es la misma ubicación que Android.Content.Context.FilesDir
. Este método toma una enumeración, System.Environment.SpecialFolder , que se usa para identificar un conjunto
de constantes enumeradas que representan las rutas de acceso de carpetas especiales usadas por el sistema
operativo. No todos los System.Environment.SpecialFolder asignarán valores a un directorio válido en
Xamarin.Android. La siguiente tabla describe qué ruta de acceso se puede esperar un determinado valor de
System.Environment.SpecialFolder :

SYSTEM.ENVIRONMENT.SPECIALFOLDER RUTA DE ACCESO

ApplicationData INTERNAL_STORAGE/.config

Desktop INTERNAL_STORAGE/Desktop

LocalApplicationData INTERNAL_STORAGE/.local/share

MyDocuments INTERNAL_STORAGE

MyMusic INTERNAL_STORAGE/Music

MyPictures INTERNAL_STORAGE/Pictures

MyVideos INTERNAL_STORAGE/Videos

Personal INTERNAL_STORAGE

Leer o escribir en archivos en almacenamiento interno


Cualquiera de los C# API para escribir en él a un archivo son suficientes; todo lo necesario es obtener la ruta de
acceso al archivo que se encuentra en el directorio asignado a la aplicación. Se recomienda encarecidamente que
async se usan versiones de las API de .NET para minimizar los problemas que pueden asociar a bloquear el
subproceso principal de acceso de archivo.
Este fragmento de código es un ejemplo de escritura de un entero en un archivo de texto UTF -8 en el directorio de
almacenamiento interno de una aplicación:

public async Task SaveCountAsync(int count)


{
var backingFile =
Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), "count.txt");
using (var writer = File.CreateText(backingFile))
{
await writer.WriteLineAsync(count.ToString());
}
}
El siguiente fragmento de código proporciona una manera de leer un valor entero que se almacenó en un archivo
de texto:

public async Task<int> ReadCountAsync()


{
var backingFile =
Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), "count.txt");

if (backingFile == null || !File.Exists(backingFile))


{
return 0;
}

var count = 0;
using (var reader = new StreamReader(backingFile, true))
{
string line;
while ((line = await reader.ReadLineAsync()) != null)
{
if (int.TryParse(line, out var newcount))
{
count = newcount;
}
}
}

return count;
}

Usar Xamarin.Essentials – aplicaciones auxiliares de sistema de archivos


Xamarin.Essentials es un conjunto de API para escribir código compatible entre plataformas. El aplicaciones
auxiliares de sistema de archivos es una clase que contiene una serie de aplicaciones auxiliares para simplificar la
búsqueda de los directorios de caché y los datos de la aplicación. Este fragmento de código proporciona un
ejemplo de cómo encontrar el directorio de almacenamiento interno y el directorio de caché para una aplicación:

// Get the path to a file on internal storage


var backingFile = Path.Combine(Xamarin.Essentials.FileSystem.AppDataDirectory, "count.txt");

// Get the path to a file in the cache directory


var cacheFile = Path.Combine(Xamarin.Essentials.FileSystem.CacheDirectory, "count.txt");

Ocultar archivos desde el MediaStore


El MediaStore es un componente de Android que recopila metadatos acerca de los archivos multimedia (como
vídeos, música, imágenes) en un dispositivo Android. Su objetivo es simplificar el uso compartido de estos
archivos en todas las aplicaciones Android en el dispositivo.
Archivos privados no se mostrarán como un medio que se pueda compartir. Por ejemplo, si una aplicación guarda
una imagen para su almacenamiento externo privada, a continuación, ese archivo no seleccionará el analizador de
medios ( MediaStore ).
Archivos públicos se recogerán mediante MediaStore . Directorios que tienen un nombre de archivo cero bytes .
NOMEDIA no se examinarán por MediaStore .

Vínculos relacionados
Almacenamiento externo
Guardar archivos en el almacenamiento del dispositivo
Aplicaciones auxiliares de sistema de archivos Xamarin.Essentials
Datos de usuario de copia de seguridad con copia de seguridad automática
Almacenamiento de forma
Almacenamiento externo
11/07/2019 • 19 minutes to read • Edit Online

Almacenamiento externo hace referencia al almacenamiento de archivos que no en el almacenamiento interno y


no exclusivamente accesible para la aplicación que se encarga del archivo. Es el propósito principal de
almacenamiento externo proporcionar un lugar para colocar los archivos que están diseñados para compartirse
entre aplicaciones o que son demasiado grandes para caber en el almacenamiento interno.
Históricamente en términos de almacenamiento externo hace referencia a una partición de disco en un medio
extraíble, como una tarjeta SD (también conocido como almacenamiento portátil). Esta distinción ya no es tan
relevante como dispositivos Android han evolucionado y muchos dispositivos Android ya no admiten el
almacenamiento extraíble. En su lugar, algunos dispositivos asignará algunas de su memoria no volátil interna que
Android para llevar a cabo los mismos medios extraíbles de función. Esto se conoce como emulado
almacenamiento y todavía se considera un almacenamiento externo. Como alternativa, algunos dispositivos
Android pueden tener varias particiones de almacenamiento externo. Por ejemplo, un Android Tablet PC (además
de su almacenamiento interno) es posible que haya emula almacenamiento y ranuras de uno o más de una tarjeta
SD. Android todas estas particiones se tratan como almacenamiento externo.
En los dispositivos que tienen varios usuarios, cada usuario tendrá un directorio dedicado en la partición principal
de almacenamiento externo para su almacenamiento externo. Aplicaciones que se ejecutan como un usuario no
tendrá acceso a los archivos de otro usuario en el dispositivo. Los archivos de todos los usuarios están todavía de
lectura y escritura mundo; Sin embargo, Android superará el espacio aislado de cada perfil de usuario de los
demás.
Leer y escribir en archivos son casi idéntico en Xamarin.Android y sirve para cualquier otra aplicación. NET. La
aplicación de Xamarin.Android determina la ruta de acceso al archivo que se manipulará, a continuación, usa
estándar .NET expresiones de acceso a archivos. Dado que las rutas de acceso reales a almacenamiento interno y
externo pueden variar de un dispositivo a otro o desde la versión de Android para la versión de Android, no se
recomienda codificar de forma rígida la ruta de acceso a los archivos. En su lugar, Xamarin.Android expone las API
nativas de Android que le ayudarán a determinar la ruta de acceso a los archivos de almacenamiento interno y
externo.
Esta guía tratan los conceptos y las API de Android que son específicos de almacenamiento externo.

Archivos pública y privada en un almacenamiento externo


Hay dos tipos diferentes de los archivos que es posible que tenga una aplicación en un almacenamiento externo:
Privada archivos – archivos privados son archivos que son específicos de la aplicación (pero son todavía de
lectura y escritura). Android espera que los archivos privados se almacenan en un directorio específico en
un almacenamiento externo. Aunque los archivos se denominan "privados", son aún visibles y accesibles
para otras aplicaciones en el dispositivo, no ofrezcan una protección especial por Android.
Pública archivos – son archivos que no se consideran específico para la aplicación y están diseñados para
compartirse libremente.
Las diferencias entre estos archivos sea principalmente conceptual. Archivos privados son privados en el sentido
de que se consideran como parte de la aplicación, mientras que los archivos públicos son los otros archivos que
existen en un almacenamiento externo. Android proporciona dos API distintas para resolver las rutas de acceso a
los archivos públicos y privados, pero en caso contrario, se usan las mismas API de .NET para leer y escribir en
estos archivos. Estas son las mismas API que se describen en la sección en leer y escribir.
Archivos externos privados
Privada archivos externos se consideran específicos para una aplicación (similar a los archivos internos), pero se
están realizando en un almacenamiento externo para una serie de motivos (por ejemplo, era demasiado grande
para el almacenamiento interno). Al igual que los archivos internos, estos archivos se eliminarán cuando se
desinstala la aplicación por el usuario.
Se encuentra la ubicación principal para archivos externos privadas llamando al método
Android.Content.Context.GetExternalFilesDir(string type) . Este método devolverá un Java.IO.File objeto que
representa el directorio de almacenamiento externa privada para la aplicación. Pasar null a este método
devolverá la ruta de acceso al directorio de almacenamiento del usuario para la aplicación. Por ejemplo, para una
aplicación con el nombre del paquete com.companyname.app , sería el directorio "raíz" de los archivos externos
privados:

/storage/emulated/0/Android/data/com.companyname.app/files/

Este documento se hará referencia en el directorio de almacenamiento para archivos privados en un


almacenamiento externo como privada_externo_almacenamiento.
El parámetro GetExternalFilesDir() es una cadena que especifica un directorio de la aplicación. Este es un
directorio diseñado para proporcionar una ubicación estándar para una organización lógica de archivos. Los
valores de cadena están disponibles a través de las constantes en el Android.OS.Environment clase:

ANDROID.OS.ENVIRONMENT DIRECTORIO

DirectoryAlarms PRIVATE_EXTERNAL_STORAGE/Alarms

DirectoryDcim PRIVATE_EXTERNAL_STORAGE/DCIM

DirectoryDownloads PRIVATE_EXTERNAL_STORAGE/Download

DirectoryDocuments PRIVATE_EXTERNAL_STORAGE/Documents

DirectoryMovies PRIVATE_EXTERNAL_STORAGE/Movies

DirectoryMusic PRIVATE_EXTERNAL_STORAGE/Music

DirectoryNotifications PRIVATE_EXTERNAL_STORAGE/Notifications

DirectoryPodcasts PRIVATE_EXTERNAL_STORAGE/Podcasts

DirectoryRingtones PRIVATE_EXTERNAL_STORAGE/Ringtones

DirectoryPictures PRIVATE_EXTERNAL_STORAGE/Pictures

Para dispositivos que tienen varias particiones de almacenamiento externo, cada partición tendrá un directorio
que está pensado para archivos privados. El método Android.Content.Context.GetExternalFilesDirs(string type)
devolverá una matriz de Java.IO.Files . Cada objeto representa un directorio específico de la aplicación privado
en todos los dispositivos de almacenamiento compartido y externos en la aplicación puede colocar los archivos
posee.
IMPORTANT
La ruta de acceso exacta en el directorio de almacenamiento externa privada puede variar de dispositivo a dispositivo y entre
las versiones de Android. Por este motivo, las aplicaciones deben duro no la ruta de acceso a este directorio de código y en
su lugar, use las APIs Xamarin.Android, como Android.Content.Context.GetExternalFilesDir() .

Archivos externos públicos


Archivos públicos son archivos que existen en un almacenamiento externo que no se almacenan en el directorio
de Android que se asigna para archivos privados. Archivos públicos no se eliminarán cuando se desinstala la
aplicación. Aplicaciones de Android deben tener el permiso antes de que pueden leer o escribir los archivos
públicos. Es posible que los archivos públicos que exista en cualquier lugar en un almacenamiento externo, pero
por convención Android espera archivos públicos que existe en el directorio identificado por la propiedad
Android.OS.Environment.ExternalStorageDirectory . Esta propiedad devolverá un Java.IO.File objeto que
representa el directorio principal de almacenamiento externo. Por ejemplo,
Android.OS.Environment.ExternalStorageDirectory puede hacer referencia al directorio siguiente:

/storage/emulated/0/

Este documento se hará referencia en el directorio de almacenamiento para archivos públicos en un


almacenamiento externo como pública_externo_almacenamiento.
Android admite también el concepto de directorios de la aplicación en pública_externo_almacenamiento. Estos
directorios son exactamente iguales que los directorios de aplicación para _PRIVATE\_EXTERNAL\_STORAGE_ y se
describen en la tabla en la sección anterior. El método
Android.OS.Environment.GetExternalStoragePublicDirectory(string directoryType) devolverá un Java.IO.File
objetos que corresponden a un directorio de aplicaciones pública. El directoryType parámetro es un parámetro
obligatorio y no puede ser null .
Por ejemplo, al llamar a
Environment.GetExternalStoragePublicDirectory(Environment.DirectoryDocuments).AbsolutePath devolverá una
cadena que será similar:

/storage/emulated/0/Documents

IMPORTANT
La ruta de acceso exacta en el directorio de almacenamiento externo público puede variar de dispositivo a dispositivo y entre
las versiones de Android. Por este motivo, las aplicaciones deben duro no la ruta de acceso a este directorio de código y en
su lugar, use las APIs Xamarin.Android, como Android.OS.Environment.ExternalStorageDirectory .

Trabajar con almacenamiento externo


Una vez que una aplicación de Xamarin.Android ha obtenido la ruta de acceso completa a un archivo, debe utilizar
cualquiera de las API estándar de .NET para crear, leer, escribir o eliminar archivos. Esto maximiza la cantidad de
entre el código de plataforma compatible para una aplicación. Sin embargo, antes de intentar tener acceso a un
archivo de una aplicación de Xamarin.Android debe asegurarse de que es posible tener acceso a ese archivo.
1. Comprobar el almacenamiento externo – según la naturaleza del almacenamiento externo, es posible que
no se puede montar y puede usar la aplicación. Todas las aplicaciones deben comprobar el estado de
almacenamiento externo antes de intentar utilizarlo.
2. Realizar una comprobación de permisos en tiempo de ejecución – An Android app debe solicitar
permiso al usuario para tener acceso a almacenamiento externo. Esto significa que una solicitud de permiso
debe realizarse antes de cualquier acceso a los archivos de tiempo de ejecución. La Guía de permisos en
Xamarin.Android contiene más detalles sobre los permisos de Android.
Cada una de estas dos tareas se describen a continuación.
Comprobando que el almacenamiento externo está disponible
Es el primer paso antes de escribir en un almacenamiento externo comprobar que es leer o escribir. El
Android.OS.Environment.ExternalStorageState propiedad contiene una cadena que identifica el estado de
almacenamiento externo. Esta propiedad devolverá una cadena que representa el estado. Esta tabla es una lista de
los ExternalStorageState valores que pueden devolver Environment.ExternalStorageState :

EX TERNALSTORAGESTATE DESCRIPCIÓN

MediaBadRemoval Los medios repentinamente se haya quitado sin que se


desmontó correctamente.

MediaChecking El medio está presente pero está llevando a cabo un disco a


comprobar.

MediaEjecting Medio está en el proceso que se va a desmontar y expulsado.

MediaMounted Media está montado y se puede leer o escribir en.

MediaMountedReadOnly Media está montado, pero solo se puede leer desde.

MediaNofs Media está presente pero no contiene un sistema de archivos


adecuado para Android.

MediaRemoved No hay ningún medio presente.

MediaShared Media está presente, pero no está montada. Que se


comparten a través de USB con otro dispositivo.

MediaUnknown Android no reconoce el estado de los medios.

MediaUnmountable El medio está presente pero no se puede montar en Android.

MediaUnmounted El medio está presente pero no está montado.

La mayoría de las aplicaciones Android solo necesitará comprobar si se monta almacenamiento externo. El
fragmento de código siguiente muestra cómo comprobar que el almacenamiento externo está montado para
acceso de solo lectura o acceso de lectura y escritura:

bool isReadonly = Environment.MediaMountedReadOnly.Equals(Environment.ExternalStorageState);


bool isWriteable = Environment.MediaMounted.Equals(Environment.ExternalStorageState);

Permisos de almacenamiento externo


Android tiene en cuenta al acceder al almacenamiento externo para que sea un permiso peligroso, que
normalmente requiere que el usuario conceder su permiso para acceder al recurso. El usuario puede revocar este
permiso en cualquier momento. Esto significa que una solicitud de permiso debe realizarse antes de cualquier
acceso a los archivos de tiempo de ejecución. Las aplicaciones se conceden automáticamente permisos para leer y
escribir sus propios archivos privados. Es posible que las aplicaciones leer y escribir los archivos privados que
pertenecen a otras aplicaciones después de que se va a permiso por el usuario.
Todas las aplicaciones de Android deben declarar uno de los dos permisos para el almacenamiento externo en el
AndroidManifest.xml . Para identificar los permisos, uno de los dos siguientes uses-permission se debe agregar
elementos a AndroidManifest.xml:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />


<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

NOTE
Si el usuario concede WRITE_EXTERNAL_STORAGE , a continuación, READ_EXTERNAL_STORAGE también es implícitamente
concedido. No es necesario solicitar ambos permisos en AndroidManifest.xml.

Visual Studio
Visual Studio para Mac
También se pueden agregar los permisos mediante la manifiesto de Android pestaña de la propiedades de la
solución:
Por lo general, todos los permisos peligrosos deben ser aprobados por el usuario. Los permisos para el
almacenamiento externo son una anomalía en que existen excepciones a esta regla, según la versión de Android
que se ejecuta la aplicación:
Para obtener más información sobre la realización de las solicitudes de permiso en tiempo de ejecución, consulte
la guía permisos en Xamarin.Android. El monodroid ejemplo archivosLocales también muestra una manera de
llevar a cabo comprobaciones de permisos en tiempo de ejecución.
Conceder y revocar permisos con ADB
Durante el desarrollo de una aplicación de Android, puede ser necesario conceder y revocar permisos a los
distintos flujos de trabajo relacionados con las comprobaciones de permisos en tiempo de ejecución de pruebas.
Es posible hacer esto en el símbolo del sistema ADB de uso. Los siguientes fragmentos de línea de comandos
muestran cómo conceder o revocar permisos con ADB para una aplicación Android cuyo nombre del paquete es
com.companyname.app:

$ adb shell pm grant com.companyname.app android.permission.WRITE_EXTERNAL_STORAGE

$ adb shell pm revoke com.companyname.app android.permission.WRITE_EXTERNAL_STORAGE

Eliminación de archivos
Cualquiera de las API de C# puede usarse para eliminar un archivo de almacenamiento externo, como el estándar
de System.IO.File.Delete . También es posible usar las API de Java a costa de la portabilidad del código. Por
ejemplo:

System.IO.File.Delete("/storage/emulated/0/Android/data/com.companyname.app/files/count.txt");

Vínculos relacionados
Archivos locales de Xamarin.Android de ejemplo en monodroid-samples
Permisos de Xamarin.Android
Autenticación de huella digital
31/07/2019 • 5 minutes to read • Edit Online

En esta guía se describe cómo agregar la autenticación mediante huella digital, introducida en Android 6,0, a una
aplicación de Xamarin. Android.

Introducción a la autenticación mediante huellas digitales


La llegada de escáneres de huellas digitales en dispositivos Android proporciona a las aplicaciones una alternativa
al método tradicional de nombre de usuario y contraseña de autenticación de usuarios. El uso de huellas digitales
para autenticar a un usuario permite que una aplicación incorpore seguridad menos intrusiva que un nombre de
usuario y una contraseña.
Las API de FingerprintManager tienen como destino dispositivos con un escáner de huellas digitales y ejecutan el
nivel de API 23 (Android 6,0) o una versión posterior. Las API se encuentran en el Android.Hardware.Fingerprints
espacio de nombres. La biblioteca de compatibilidad de Android V4 proporciona versiones de las API de huellas
digitales diseñadas para versiones anteriores de Android. Las API de compatibilidad se encuentran en
Android.Support.v4.Hardware.Fingerprint el espacio de nombres, se distribuyen mediante el paquete NuGet
Xamarin. Android. support. V4.
FingerprintManager (y su homólogo de la biblioteca de compatibilidad, FingerprintManagerCompat) es la clase
principal para usar el hardware de análisis de huellas digitales. Esta clase es un contenedor de Android SDK
alrededor del servicio de nivel de sistema que administra las interacciones con el propio hardware. Es responsable
de iniciar el escáner de huellas digitales y de responder a los comentarios del escáner. Esta clase tiene una interfaz
bastante sencilla con solo tres miembros:
Authenticate – Este método inicializará el explorador de hardware e iniciará el servicio en segundo plano,
esperando a que el usuario digitalice su huella digital.
EnrolledFingerprints Esta propiedad devolverá true si el usuario ha registrado una o varias huellas digitales
con el dispositivo. –
HardwareDetected – Esta propiedad se usa para determinar si el dispositivo admite el análisis de huellas
digitales.
Una FingerprintManager.Authenticate aplicación de Android usa el método para iniciar el escáner de huellas
digitales. El siguiente fragmento de código es un ejemplo de cómo invocarlo mediante las API de compatibilidad
de la biblioteca de soporte:

// context is any Android.Content.Context instance, typically the Activity


FingerprintManagerCompat fingerprintManager = FingerprintManagerCompat.From(context);
fingerprintManager.Authenticate(FingerprintManager.CryptoObject crypto,
int flags,
CancellationSignal cancel,
FingerprintManagerCompat.AuthenticationCallback callback,
Handler handler
);

En esta guía se explica cómo usar las FingerprintManager API para mejorar una aplicación de Android con
autenticación mediante huellas digitales. Se explica cómo crear una instancia de y crear un CryptoObject para
ayudar a proteger los resultados del escáner de huellas digitales. Examinaremos el modo en que una aplicación
debe FingerprintManager.AuthenticationCallback subclase y responder a los comentarios del escáner de huellas
digitales. Por último, veremos cómo inscribir una huella digital en un emulador o dispositivo Android y cómo usar
ADB para simular un análisis de huellas digitales.

Requisitos
La autenticación mediante huella digital requiere Android 6,0 (nivel de API 23) o superior y un dispositivo con un
escáner de huellas digitales.
Una huella digital ya debe estar inscrita en el dispositivo para cada usuario que se va a autenticar. Esto implica la
configuración de un bloqueo de pantalla que utiliza una contraseña, un PIN, un patrón de deslizamiento o
reconocimiento facial. Es posible simular parte de la funcionalidad de autenticación mediante huella digital en un
Android Emulator. Para obtener más información sobre estos dos temas, consulte la sección inscripción de una
huella digital .

Vínculos relacionados
Aplicación de ejemplo de guía de huellas digitales
Ejemplo de cuadro de diálogo de huellas digitales
Solicitar permisos en tiempo de ejecución
android.hardware.fingerprint
android.support.v4.hardware.fingerprint
Android.Content.Context
API de huellas digitales y pagos (vídeo)
Introducción con autenticación mediante huellas
digitales
27/07/2019 • 6 minutes to read • Edit Online

Para empezar, vamos a explicar primero cómo configurar un proyecto de Xamarin. Android para que la aplicación
pueda usar la autenticación mediante huella digital:
1. Actualice archivo AndroidManifest. XML para declarar los permisos que requieren las API de huellas
digitales.
2. Obtenga una referencia a FingerprintManager .
3. Compruebe que el dispositivo es capaz de detectar huellas digitales.

Solicitar permisos en el manifiesto de aplicación


Visual Studio
Visual Studio para Mac
Una aplicación de Android debe solicitar USE_FINGERPRINT el permiso en el manifiesto. En la captura de pantalla
siguiente se muestra cómo agregar este permiso a la aplicación en Visual Studio:

Obtener una instancia de FingerprintManager


A continuación, la aplicación debe obtener una instancia de FingerprintManager la FingerprintManagerCompat clase
o. Para ser compatible con versiones anteriores de Android, una aplicación de Android debe usar la API de
compatibilidad que se encuentra en el paquete NuGet de compatibilidad de Android V4. En el siguiente fragmento
de código se muestra cómo obtener el objeto adecuado del sistema operativo:
// Using the Android Support Library v4
FingerprintManagerCompat fingerprintManager = FingerprintManagerCompat.From(context);

// Using API level 23:


FingerprintManager fingerprintManager = context.GetSystemService(Context.FingerprintService) as
FingerprintManager;

En el fragmento de código anterior context , es cualquier Android.Content.Context Android. Normalmente, se


trata de la actividad que realiza la autenticación.

Comprobando elegibilidad
Una aplicación debe realizar varias comprobaciones para asegurarse de que es posible usar la autenticación con
huellas digitales. En total, hay cinco condiciones que la aplicación usa para comprobar la idoneidad:
Nivel de API 23 – Las API de huellas digitales requieren el nivel de API 23 o superior. La
FingerprintManagerCompat clase ajustará la comprobación de nivel de API. Por esta razón, se recomienda usar la
biblioteca de compatibilidad de Android V4 y FingerprintManagerCompat ; esto tendrá en cuenta la de estas
comprobaciones.
Hardware de – Cuando la aplicación se inicia por primera vez, debe comprobar la presencia de un escáner de
huellas digitales:

FingerprintManagerCompat fingerprintManager = FingerprintManagerCompat.From(context);


if (!fingerprintManager.IsHardwareDetected)
{
// Code omitted
}

El dispositivo está protegido – El usuario debe tener el dispositivo protegido con un bloqueo de pantalla. Si el
usuario no ha protegido el dispositivo con un bloqueo de pantalla y la seguridad es importante para la aplicación,
se debe notificar al usuario que debe configurarse un bloqueo de pantalla. En el fragmento de código siguiente se
muestra cómo comprobar este requiste:

KeyguardManager keyguardManager = (KeyguardManager) GetSystemService(KeyguardService);


if (!keyguardManager.IsKeyguardSecure)
{
}

Huellas digitales inscritos – El usuario debe tener al menos una huella digital registrada en el sistema operativo.
Esta comprobación de permisos debe realizarse antes de cada intento de autenticación:

FingerprintManagerCompat fingerprintManager = FingerprintManagerCompat.From(context);


if (!fingerprintManager.HasEnrolledFingerprints)
{
// Can't use fingerprint authentication - notify the user that they need to
// enroll at least one fingerprint with the device.
}

Permisos de – La aplicación debe solicitar permiso al usuario antes de usar la aplicación. Para Android 5,0 y
versiones anteriores, el usuario concede el permiso como una condición de instalación de la aplicación. Android 6,0
presentó un nuevo modelo de permiso que comprueba los permisos en tiempo de ejecución. Este fragmento de
código es un ejemplo de cómo comprobar los permisos en Android 6,0:
// The context is typically a reference to the current activity.
Android.Content.PM.Permission permissionResult = ContextCompat.CheckSelfPermission(context,
Manifest.Permission.UseFingerprint);
if (permissionResult == Android.Content.PM.Permission.Granted)
{
// Permission granted - go ahead and start the fingerprint scanner.
}
else
{
// No permission. Go and ask for permissions and don't start the scanner. See
// https://developer.android.com/training/permissions/requesting.html
}

La comprobación de todas estas condiciones cada vez que la aplicación ofrece opciones de autenticación
garantizará que el usuario obtiene la mejor experiencia de usuario. Los cambios o las actualizaciones de su
dispositivo o sistema operativo pueden afectar a la disponibilidad de la autenticación mediante huella digital. Si
decide almacenar en caché los resultados de cualquiera de estas comprobaciones, asegúrese de cumplir los
escenarios de actualización.
Para obtener más información sobre cómo solicitar permisos en Android 6,0, consulte la guía de Android que
solicita permisos en tiempo de ejecución.

Vínculos relacionados
Contexto
KeyguardManager
ContextCompat
FingerprintManager
FingerprintManagerCompat
Solicitar permisos en tiempo de ejecución
Examen de huellas digitales
11/07/2019 • 6 minutes to read • Edit Online

Ahora que hemos visto cómo preparar una aplicación de Xamarin.Android para usar la autenticación con huella
digital, vamos a volver a la FingerprintManager.Authenticate método y analizar su lugar en la autenticación de
huella digital de Android 6.0. Información general del flujo de trabajo de autenticación con huella digital se
describe en esta lista:
1. Invocar FingerprintManager.Authenticate , pasando un CryptoObject y un
FingerprintManager.AuthenticationCallback instancia. El CryptoObject se utiliza para garantizar que no se ha
alterado el resultado de la autenticación de huella digital.
2. Subclase la FingerprintManager.AuthenticationCallback clase. Una instancia de esta clase se ofrecerá en
FingerprintManager cuando se inicia la autenticación de huella digital. Cuando finalice el escáner de huella
digital, invocará uno de los métodos de devolución de llamada en esta clase.
3. Escribir código para actualizar la interfaz de usuario para que el usuario sepa que el dispositivo ha iniciado el
escáner de huellas digitales y está esperando la interacción del usuario.
4. Cuando se realiza el escáner de huella digital, Android devolverá resultados a la aplicación mediante la
invocación de un método en el FingerprintManager.AuthenticationCallback instancia que se proporcionó en el
paso anterior.
5. La aplicación de informar al usuario de los resultados de la autenticación de huella digital y reaccionar a los
resultados según corresponda.
El fragmento de código siguiente es un ejemplo de un método en una actividad que se iniciará el examen de
huellas digitales:

protected void FingerPrintAuthenticationExample()


{
const int flags = 0; /* always zero (0) */

// CryptoObjectHelper is described in the previous section.


CryptoObjectHelper cryptoHelper = new CryptoObjectHelper();

// cancellationSignal can be used to manually stop the fingerprint scanner.


cancellationSignal = new Android.Support.V4.OS.CancellationSignal();

FingerprintManagerCompat fingerprintManager = FingerprintManagerCompat.From(this);

// AuthenticationCallback is a base class that will be covered later on in this guide.


FingerprintManagerCompat.AuthenticationCallback authenticationCallback = new MyAuthCallbackSample(this);

// Start the fingerprint scanner.


fingerprintManager.Authenticate(cryptoHelper.BuildCryptoObject(), flags, cancellationSignal,
authenticationCallback, null);
}

Tratemos cada uno de estos parámetros en el Authenticate método un poco más detalladamente:
El primer parámetro es un crypto que usará el escáner de huellas digitales para autenticar a los resultados de un
examen de huellas digitales de objeto. Este objeto puede ser null , en cuyo caso en que la aplicación tiene que
confían ciegamente en la que nada ha alterado los resultados de la huella digital. Se recomienda que un
CryptoObject se crea una instancia y se proporcionan para el FingerprintManager en lugar de null. Creación de
un CryptObject se explica detalladamente cómo crear una instancia de un CryptoObject según un Cipher .
El segundo parámetro siempre es cero. La documentación de Android lo identifica como conjunto de marcas y
es más probable es que se reserva para uso futuro.
El tercer parámetro, cancellationSignal es un objeto utilizado para desactivar el escáner de huellas digitales y
cancelar la solicitud actual. Se trata de un CancellationSignal Androidy no es un tipo de .NET framework.
El cuarto parámetro es obligatorio y es una clase que cree subclases el AuthenticationCallback clase abstracta.
Los métodos de esta clase se invocará para indicar a los clientes cuando el FingerprintManager ha finalizado y
cuáles son los resultados. Como hay mucho que comprender acerca de cómo implementar la
AuthenticationCallback , se explicará en es propia sección.
El quinto parámetro es opcional Handler instancia. Si un Handler se proporciona el objeto, el
FingerprintManager usará el Looper desde ese objeto al procesar los mensajes desde el hardware de huella
digital. Normalmente, no es necesario proporcionar un Handler , usará el FingerprintManager el Looper desde
la aplicación.

Al cancelar un examen de huellas digitales


Podría ser necesario para el usuario (o la aplicación) cancelar el examen de huellas digitales después de que se ha
iniciado. En esta situación, invocar el IsCancelled método en el CancellationSignal que proporcionó
FingerprintManager.Authenticate cuando se invoca para iniciar el examen de huellas digitales.

Ahora que hemos visto la Authenticate método, vamos a examinar algunos de los parámetros más importantes
con más detalle. En primer lugar, examinaremos responde a las devoluciones de llamada de autenticación, que se
describe cómo crear subclases de la FingerprintManager.AuthenticationCallback, habilitando una aplicación
Android para reaccionar a la resultados proporcionados por el escáner de huella digital.

Vínculos relacionados
CancellationSignal
FingerprintManager.AuthenticationCallback
FingerprintManager.CryptoObject
FingerprintManagerCompat.CryptoObject
FingerprintManager
FingerprintManagerCompat
Creación de un CryptoObject
27/07/2019 • 7 minutes to read • Edit Online

La integridad de los resultados de la autenticación mediante huellas digitales es – importante para una aplicación,
es cómo la aplicación conoce la identidad del usuario. Teóricamente, es posible que un malware de terceros
intercepte y manipule los resultados devueltos por el escáner de huellas digitales. En esta sección se describe una
técnica para conservar la validez de los resultados de la huella digital.
Es un contenedor alrededor de las API de criptografía de Java y lo usa FingerprintManager para proteger la
integridad de la solicitud de autenticación. FingerprintManager.CryptoObject Normalmente, un
Javax.Crypto.Cipher objeto es el mecanismo de cifrado de los resultados del escáner de huellas digitales. El
Cipher propio objeto usará una clave creada por la aplicación mediante las API de almacén de claves de Android.

Para comprender cómo funcionan conjuntamente estas clases, echemos un CryptoObject vistazo primero al
código siguiente, que muestra cómo crear y, a continuación, explicar con más detalle:

public class CryptoObjectHelper


{
// This can be key name you want. Should be unique for the app.
static readonly string KEY_NAME = "com.xamarin.android.sample.fingerprint_authentication_key";

// We always use this keystore on Android.


static readonly string KEYSTORE_NAME = "AndroidKeyStore";

// Should be no need to change these values.


static readonly string KEY_ALGORITHM = KeyProperties.KeyAlgorithmAes;
static readonly string BLOCK_MODE = KeyProperties.BlockModeCbc;
static readonly string ENCRYPTION_PADDING = KeyProperties.EncryptionPaddingPkcs7;
static readonly string TRANSFORMATION = KEY_ALGORITHM + "/" +
BLOCK_MODE + "/" +
ENCRYPTION_PADDING;
readonly KeyStore _keystore;

public CryptoObjectHelper()
{
_keystore = KeyStore.GetInstance(KEYSTORE_NAME);
_keystore.Load(null);
}

public FingerprintManagerCompat.CryptoObject BuildCryptoObject()


{
Cipher cipher = CreateCipher();
return new FingerprintManagerCompat.CryptoObject(cipher);
}

Cipher CreateCipher(bool retry = true)


{
IKey key = GetKey();
Cipher cipher = Cipher.GetInstance(TRANSFORMATION);
try
{
cipher.Init(CipherMode.EncryptMode | CipherMode.DecryptMode, key);
} catch(KeyPermanentlyInvalidatedException e)
{
_keystore.DeleteEntry(KEY_NAME);
if(retry)
{
CreateCipher(false);
} else
{
{
throw new Exception("Could not create the cipher for fingerprint authentication.", e);
}
}
return cipher;
}

IKey GetKey()
{
IKey secretKey;
if(!_keystore.IsKeyEntry(KEY_NAME))
{
CreateKey();
}

secretKey = _keystore.GetKey(KEY_NAME, null);


return secretKey;
}

void CreateKey()
{
KeyGenerator keyGen = KeyGenerator.GetInstance(KeyProperties.KeyAlgorithmAes, KEYSTORE_NAME);
KeyGenParameterSpec keyGenSpec =
new KeyGenParameterSpec.Builder(KEY_NAME, KeyStorePurpose.Encrypt | KeyStorePurpose.Decrypt)
.SetBlockModes(BLOCK_MODE)
.SetEncryptionPaddings(ENCRYPTION_PADDING)
.SetUserAuthenticationRequired(true)
.Build();
keyGen.Init(keyGenSpec);
keyGen.GenerateKey();
}
}

El código de ejemplo creará un Cipher nuevo para CryptoObject cada, mediante una clave creada por la
aplicación. La clave se identifica mediante la KEY_NAME variable que se estableció al principio de la
CryptoObjectHelper clase. El método GetKey probará y recuperará la clave mediante las API de almacén de claves
de Android. Si la clave no existe, el método CreateKey creará una nueva clave para la aplicación.
Se crea una instancia del cifrado con una Cipher.GetInstance llamada a, tomando una transformación (valor de
cadena que indica al cifrado cómo cifrar y descifrar los datos). La llamada a Cipher.Init completará la
inicialización del cifrado proporcionando una clave de la aplicación.
Es importante saber que hay algunas situaciones en las que Android puede invalidar la clave:
Se ha inscrito una nueva huella digital con el dispositivo.
No hay huellas digitales inscritas con el dispositivo.
El usuario ha deshabilitado el bloqueo de pantalla.
El usuario ha cambiado el bloqueo de pantalla (el tipo de screenlock o el PIN o patrón usado).
Cuando esto sucede, Cipher.Init producirá una KeyPermanentlyInvalidatedException excepción. En el código de
ejemplo anterior se detectará esa excepción, se eliminará la clave y, a continuación, se creará una nueva.
En la siguiente sección se explica cómo crear la clave y almacenarla en el dispositivo.

Creación de una clave secreta


La CryptoObjectHelperclase usa Android KeyGenerator para crear una clave y almacenarla en el dispositivo. La
KeyGenerator clase puede crear la clave, pero necesita algunos metadatos sobre el tipo de clave que se va a crear.
Esta información la proporciona una instancia de la KeyGenParameterSpec clase.
Se KeyGenerator crea una instancia de mediante GetInstance el Factory Method. El código de ejemplo utiliza el
estándar de cifrado avanzado (AES ) como algoritmo de cifrado. AES dividirá los datos en bloques de tamaño fijo
y cifrará cada uno de estos bloques.
A continuación, KeyGenParameterSpec se crea una con KeyGenParameterSpec.Builder el. KeyGenParameterSpec.Builder
Incluye la siguiente información sobre la clave que se va a crear:
Nombre de la clave.
La clave debe ser válida para el cifrado y el descifrado.
En el código BLOCK_MODE de ejemplo, se establece en encadenamiento de KeyProperties.BlockModeCbc bloques
de cifrado (), lo que significa que cada bloque es XORed con el bloque anterior (creando dependencias entre
cada bloque).
Usa CryptoObjectHelper el estándar de criptografía de clave pública #7 (pkcs7) para generar los bytes que
rellenarán los bloques para asegurarse de que tienen el mismo tamaño.
SetUserAuthenticationRequired(true) significa que se requiere la autenticación del usuario antes de que se
pueda usar la clave.
Una vez que KeyGenerator secrea,seusaparainicializar,quegeneraráunaclaveylaalmacenarádeformasegura
KeyGenParameterSpec en el dispositivo.

Usar CryptoObjectHelper
Ahora que el código de ejemplo ha encapsulado gran parte de la lógica para CryptoWrapper crear un
CryptoObjectHelper en la clase, vamos CryptoObjectHelper a revisar el código desde el inicio de esta guía y usar
para crear el cifrado e iniciar un escáner de huellas digitales:

protected void FingerPrintAuthenticationExample()


{
const int flags = 0; /* always zero (0) */

CryptoObjectHelper cryptoHelper = new CryptoObjectHelper();


cancellationSignal = new Android.Support.V4.OS.CancellationSignal();

// Using the Support Library classes for maximum reach


FingerprintManagerCompat fingerPrintManager = FingerprintManagerCompat.From(this);

// AuthCallbacks is a C# class defined elsewhere in code.


FingerprintManagerCompat.AuthenticationCallback authenticationCallback = new MyAuthCallbackSample(this);

// Here is where the CryptoObjectHelper builds the CryptoObject.


fingerprintManager.Authenticate(cryptohelper.BuildCryptoObject(), flags, cancellationSignal,
authenticationCallback, null);
}

Ahora que hemos aprendido a crear un CryptoObject , vamos a ver FingerprintManager.AuthenticationCallbacks


cómo se usan para transferir los resultados del servicio de análisis de huellas digitales a una aplicación de Android.

Vínculos relacionados
Cifra
FingerprintManager.CryptoObject
FingerprintManagerCompat.CryptoObject
KeyGenerator
KeyGenParameterSpec
KeyGenParameterSpec.Builder
KeyPermanentlyInvalidatedException
KeyProperties
AES
RFC 2315-PCKS #7
Respuesta a las devoluciones de llamada de
autenticación
16/08/2019 • 9 minutes to read • Edit Online

El escáner de huellas digitales se ejecuta en segundo plano en su propio subproceso y, cuando finaliza, informará
de los resultados del análisis al invocar FingerprintManager.AuthenticationCallback un método de en el
subproceso de la interfaz de usuario. Una aplicación de Android debe proporcionar su propio controlador, que
extiende esta clase abstracta, implementando todos los métodos siguientes:
OnAuthenticationError(int errorCode, ICharSequence errString) – Se llama cuando se produce un error
irrecuperable. No hay nada más que una aplicación o usuario puede hacer para corregir la situación, salvo que
es posible que vuelva a intentarlo.
OnAuthenticationFailed() – Este método se invoca cuando se detecta una huella digital, pero el dispositivo no
la reconoce.
OnAuthenticationHelp(int helpMsgId, ICharSequence helpString) – Se llama cuando se produce un error
recuperable, por ejemplo, el dedo se desliza rápidamente a través del escáner.
OnAuthenticationSucceeded(FingerprintManagerCompati.AuthenticationResult result) – Se llama a este método
cuando se reconoce una huella digital.
Si se CryptoObjectutilizó una al llamar Authenticate a, se recomienda llamar Cipher.DoFinal a en
OnAuthenticationSuccessful . DoFinal producirá una excepción si el cifrado se alteró o se inicializó
incorrectamente, lo que indica que el resultado del escáner de huellas digitales puede haberse alterado fuera de la
aplicación.

NOTE
Se recomienda mantener la clase de devolución de llamada relativamente ligera y liberar la lógica específica de la aplicación.
Las devoluciones de llamada deben actuar como un "COP de tráfico" entre la aplicación Android y los resultados del escáner
de huellas digitales.

Un controlador de devolución de llamada de autenticación de ejemplo


La clase siguiente es un ejemplo de una implementación FingerprintManager.AuthenticationCallback mínima:
class MyAuthCallbackSample : FingerprintManagerCompat.AuthenticationCallback
{
// Can be any byte array, keep unique to application.
static readonly byte[] SECRET_BYTES = {1, 2, 3, 4, 5, 6, 7, 8, 9};
// The TAG can be any string, this one is for demonstration.
static readonly string TAG = "X:" + typeof (SimpleAuthCallbacks).Name;

public MyAuthCallbackSample()
{
}

public override void OnAuthenticationSucceeded(FingerprintManagerCompat.AuthenticationResult result)


{
if (result.CryptoObject.Cipher != null)
{
try
{
// Calling DoFinal on the Cipher ensures that the encryption worked.
byte[] doFinalResult = result.CryptoObject.Cipher.DoFinal(SECRET_BYTES);

// No errors occurred, trust the results.


}
catch (BadPaddingException bpe)
{
// Can't really trust the results.
Log.Error(TAG, "Failed to encrypt the data with the generated key." + bpe);
}
catch (IllegalBlockSizeException ibse)
{
// Can't really trust the results.
Log.Error(TAG, "Failed to encrypt the data with the generated key." + ibse);
}
}
else
{
// No cipher used, assume that everything went well and trust the results.
}
}

public override void OnAuthenticationError(int errMsgId, ICharSequence errString)


{
// Report the error to the user. Note that if the user canceled the scan,
// this method will be called and the errMsgId will be FingerprintState.ErrorCanceled.
}

public override void OnAuthenticationFailed()


{
// Tell the user that the fingerprint was not recognized.
}

public override void OnAuthenticationHelp(int helpMsgId, ICharSequence helpString)


{
// Notify the user that the scan failed and display the provided hint.
}
}

OnAuthenticationSucceeded comprueba si Cipher se FingerprintManager proporcionó cuando Authentication se


invocó. Si es así, DoFinal se llama al método en el cifrado. Esto cierra Cipher y lo restaura a su estado original. Si
se produjo un problema con el cifrado, DoFinal se producirá una excepción y se debe considerar que el intento de
autenticación ha producido un error.
Cada una de las devolucionesdellamadarecibeunenteroqueindicaelproblema.
OnAuthenticationError
OnAuthenticationHelp En la siguiente sección se explica cada uno de los posibles códigos de ayuda o error. Las dos
devoluciones de llamada – sirven para informar a la aplicación de que se ha producido un error en la
autenticación mediante huella digital. La diferencia es la gravedad. OnAuthenticationHelp es un error recuperable
por el usuario, como el deslizamiento de la huella digital demasiado rápido; OnAuthenticationError es más un
error grave, como un escáner de huellas digitales dañado.
Tenga en OnAuthenticationError cuenta que se invocará cuando se cancele el análisis de
CancellationSignal.Cancel() huellas digitales a través del mensaje. El errMsgId parámetro tendrá el valor 5 (
FingerprintState.ErrorCanceled ). Dependiendo de los requisitos, una implementación de
AuthenticationCallbacks puede tratar esta situación de forma distinta a la de otros errores.

OnAuthenticationFailed se invoca cuando la huella digital se ha analizado correctamente, pero no coincide con
ninguna huella digital inscrito con el dispositivo.

Códigos de ayuda e ID. de mensaje de error


Puede encontrar una lista y una descripción de los códigos de error y los códigos de ayuda en la documentación
de Android SDK de la clase FingerprintManager. Xamarin. Android representa estos valores con la
Android.Hardware.Fingerprints.FingerprintState enumeración:

AcquiredGood – (valor 0) la imagen adquirida fue buena.


AcquiredImagerDirty – (valor 3) la imagen de huella digital era demasiado ruidosa debido a una suciedad
sospechosa o detectada en el sensor. Por ejemplo, es razonable devolverlo después AcquiredInsufficient
de la detección de la suciedad en el sensor (en píxeles, swaths, etc.). Se espera que el usuario tome medidas
para limpiar el sensor cuando se devuelva.
AcquiredInsufficient (valor 2) la imagen de huella digital era demasiado ruidosa para procesarse debido a
una condición detectada (es decir, una máscara seca) o un sensor posiblemente sucio (consulte
AcquiredImagerDirty . –

AcquiredPartial – (valor 1) se ha detectado solo una imagen de huella digital parcial. Durante la
inscripción, se debe informar al usuario sobre lo que debe ocurrir para resolver este problema, por ejemplo
“, al presionar firmemente en el sensor.”
AcquiredTooFast – (valor 5) la imagen de huella digital estaba incompleta debido al movimiento rápido.
Aunque lo más adecuado para los sensores de matriz lineal, esto también podría ocurrir si el dedo se
moviera durante la adquisición. Se debe solicitar al usuario que mueva el dedo más despacio (lineal) o deje
el dedo en el sensor más tiempo.
AcquiredToSlow – (valor 4) la imagen de huella digital no se pudo leer debido a la falta de movimiento. Esto
es lo más adecuado para los sensores de matriz lineal que requieren un movimiento de deslizamiento.
ErrorCanceled – (valor 5) la operación se canceló porque el sensor de huellas digitales no está disponible.
Por ejemplo, esto puede ocurrir cuando se cambia el usuario, el dispositivo está bloqueado u otra
operación pendiente lo impide o lo deshabilita.
ErrorHwUnavailable – (valor 1) el hardware no está disponible. Inténtelo de nuevo más tarde.
ErrorLockout – (valor 7) la operación se canceló porque la API está bloqueada debido a demasiados
intentos.
– (valor 4) estado de error devuelto para operaciones como la inscripción; la operación no se
ErrorNoSpace
puede completar porque no hay suficiente espacio de almacenamiento para completar la operación.
ErrorTimeout – (valor 3) estado de error devuelto cuando la solicitud actual se ha ejecutado demasiado
tiempo. Esto está pensado para evitar que los programas esperen el sensor de huellas digitales
indefinidamente. El tiempo de espera es específico de la plataforma y del sensor, pero suele ser de 30
segundos.
ErrorUnableToProcess – (valor 2) estado de error devuelto cuando el sensor no pudo procesar la imagen
actual.

Vínculos relacionados
Cifra
AuthenticationCallback
AuthenticationCallback
Guía de autenticación mediante huellas digitales
31/07/2019 • 4 minutes to read • Edit Online

Guía de autenticación mediante huellas digitales


Ahora que hemos detectado los conceptos y las API relacionados con la autenticación de huellas digitales de
Android 6,0, vamos a analizar algunos consejos generales sobre el uso de las API de huellas digitales.
1. Usar las API de compatibilidad de la biblioteca de compatibilidad de Android V4 – Esto simplificará
el código de aplicación al quitar la comprobación de la API del código y permitir que una aplicación tenga
como destino la mayoría de los dispositivos posibles.
2. Proporcionar alternativas a la autenticación mediante huellas digitales – La autenticación mediante
huella digital es una forma fantástica y rápida de que una aplicación autentique a un usuario, sin embargo,
no se puede suponer que siempre funcionará o estará disponible. Es posible que se produzca un error en el
escáner de huellas digitales, puede que la lente se haya modificado, que el usuario no haya configurado el
dispositivo para que use la autenticación mediante huella digital o que las huellas digitales no se hayan
perdido. También es posible que el usuario no quiera usar la autenticación mediante huella digital con la
aplicación. Por estos motivos, una aplicación Android debe proporcionar un proceso de autenticación
alternativo, como el nombre de usuario y la contraseña.
3. Usar el icono de huella digital de Google – Todas las aplicaciones deben usar el mismo icono de huella
digital proporcionado por Google. El uso de un icono estándar facilita que los usuarios de Android
reconozcan dónde se usa la autenticación mediante huella digital de aplicaciones:

4. Notificar al usuario – Una aplicación debe mostrar algún tipo de notificación al usuario de que el escáner
de huellas digitales esté activo y esperar a tocar o deslizar rápidamente.

Resumen
La autenticación mediante huella digital es una excelente manera de permitir que una aplicación de Xamarin.
Android Compruebe rápidamente a los usuarios, lo que facilita a los usuarios la interacción con características
confidenciales como las compras desde la aplicación. En esta guía se describen los conceptos y el código necesarios
para incorporar las API de huellas digitales de Android 6,0 en la aplicación Xamarin. Android.
En primer lugar, analizamos las propias API FingerprintManager de huellas FingerprintManagerCompat digitales, (y).
Hemos examinado cómo FingerprintManager.AuthenticationCallbacks una aplicación debe extender la clase
abstracta y utilizarla como intermediario entre el hardware de huella digital y la propia aplicación. Después, hemos
examinado cómo comprobar la integridad de los resultados del escáner de huellas Cipher digitales con un objeto
de Java. Por último, hemos retocado un poco en las pruebas describiendo cómo inscribir una huella digital en un
dispositivo y usar ADB para simular una huella digital en un emulador.
Si todavía no lo ha hecho, debe examinar la aplicación de ejemplo que acompaña a esta guía. El ejemplo de cuadro
de diálogo de huellas digitales se ha trasladado de Java a Xamarin. Android y proporciona otro ejemplo sobre
cómo agregar la autenticación mediante huellas digitales a una aplicación de Android.

Vínculos relacionados
Aplicación de ejemplo de guía de huellas digitales
Ejemplo de cuadro de diálogo de huellas digitales
Icono de huella digital
Inscripción de una huella digital
11/07/2019 • 4 minutes to read • Edit Online

Una huella digital de información general sobre la inscripción


Solo es posible que una aplicación de Android aprovechar la autenticación con huella digital si el dispositivo ya se
ha configurado con autenticación con huella digital. Esta guía describirá cómo inscribir una huella digital en un
emulador o dispositivo Android. Los emuladores no tiene el hardware real para realizar un examen de huellas
digitales pero es posible simular un examen de huellas digitales con la Ayuda de Android Debug Bridge (descrito a
continuación). Esta guía describirá cómo habilitar el bloqueo de pantalla en un dispositivo Android e inscriba una
huella digital para la autenticación.

Requisitos
Para inscribir una huella digital, debe tener un dispositivo Android o un emulador en funcionamiento el nivel de
API 23 (Android 6.0).
El uso de la Android Debug Bridge (ADB ) es necesario estar familiarizado con el símbolo del sistema y el adb
ejecutable debe estar en la ruta de acceso de Bash, PowerShell, o entorno de símbolo del sistema de comandos.

Configuración de un bloqueo de pantalla e inscripción de huella digital


Para configurar un bloqueo de pantalla, realice los pasos siguientes:
1. Vaya a configuración > seguridady seleccione bloqueo de pantalla:
2. La siguiente pantalla que aparece le permitirá seleccionar y configurar uno de los métodos de seguridad de
bloqueo de pantalla:
Seleccione y complete uno de los métodos de bloqueo de pantalla disponibles.
3. Una vez configurada la screenlock, volver a la configuración > seguridad página y seleccione huellas
digitales:
4. Desde allí, siga la secuencia para agregar una huella digital para el dispositivo:

5. En la pantalla final se le pedirá que colocar su dedo sobre el escáner de huella digital:
Si se usa un dispositivo Android, complete el proceso si toca un dedo al escáner.
Simulación de un examen de huellas digitales en el emulador
En un emulador de Android, es posible simular un examen de huellas digitales con Android Debug Bridge. En el
inicio de OS X una sesión de Terminal mientras se encuentra en Windows, inicie un símbolo del sistema o una
sesión de Powershell y ejecute adb :

$ adb -e emu finger touch 1

El valor de 1 es el dedo_id para el dedo que se "examinan". Es un entero único que asigne a cada huella virtual. En
el futuro cuando ejecuta la aplicación se puede ejecutar este mismo ADB comando cada vez que el emulador le
pide una huella digital, puede ejecutar el adb comando y pasarle el dedo_Id. de para simular el examen de huellas
digitales .
Una vez completado el examen de huellas digitales, Android le notificará que se ha agregado la huella digital:
Resumen
Esta guía trata sobre cómo configurar un bloqueo de pantalla e inscribir una huella digital en un dispositivo
Android o en un emulador de Android.
Programador de trabajos de Android
11/07/2019 • 21 minutes to read • Edit Online

Esta guía describe cómo programar el trabajo en segundo plano mediante la API de programador de trabajo
Android, que está disponible en dispositivos Android que ejecuten Android 5.0 (API nivel 21 ) y versiones
posteriores.

Información general
Una de las mejores formas para que una aplicación de Android siga respondiendo al usuario es para asegurarse de
que el trabajo complejo o de larga ejecución se realiza en segundo plano. Sin embargo, es importante que trabajo
en segundo plano no afectará negativamente la experiencia del usuario con el dispositivo.
Por ejemplo, un trabajo en segundo plano puede sondear un sitio Web cada tres o cuatro minutos para consultar
los cambios a un determinado conjunto de datos. Esto parece ser benigno, pero tendría un impacto desastroso en
duración de la batería. La aplicación se repetidamente el dispositivo de reactivación, elevar la CPU a un estado de
encendido, el radio de energía, hacer que las solicitudes de red y, a continuación, procesar los resultados. Lo
empeora porque el dispositivo se apague y se devolverá al estado inactivo de baja energía no inmediatamente.
Trabajo en segundo plano programado mal accidentalmente puede mantener el dispositivo en un estado con
requisitos de energía innecesaria y excesiva. Esta actividad aparentemente inofensivo (un sitio Web de sondeo)
representará el dispositivo inutilizable en un período de tiempo relativamente corto.
Android proporciona las siguientes API para ayudar a realizar el trabajo en segundo plano, pero por sí solos no
son suficientes para la programación de tareas inteligente.
Servicios de intención – servicios de intención son excelentes para llevar a cabo el trabajo, pero que no
ofrecen ninguna forma para programar el trabajo.
AlarmManager – estas API solo permiten que el trabajo puede programar pero no ofrecen ninguna forma
para llevar a cabo el trabajo. Además, el AlarmManager solo permite las restricciones en función del tiempo, lo
que significa que genera una alarma en un momento determinado o una vez transcurrido un período de tiempo
determinado.
Receptores de difusión – An Android app puede configurar receptores de difusión para llevar a cabo trabajo
en respuesta a eventos de todo el sistema o intenciones. Sin embargo, los receptores de difusión no
proporcionan ningún control sobre cuándo se debe ejecutar el trabajo. También se restringirán los cambios en
el sistema operativo Android cuando funcionará receptores de difusión o los tipos de trabajo que puede
responder.
Hay dos características clave para realizar eficazmente el trabajo en segundo plano (a veces se denomina un
trabajo en segundo plano o un trabajo):
1. Programar el trabajo de forma inteligente – es importante que cuando una aplicación está realizando
trabajo en segundo plano que lo hace como un buen ciudadano. Idealmente, la aplicación no debería exigir que
se ejecute un trabajo. En su lugar, la aplicación debe especificar las condiciones que deben cumplirse para
cuando el trabajo puede ejecutar y, a continuación, programar que el trabajo con el sistema operativo que se
llevará a cabo el trabajo cuando se cumplen las condiciones. Esto permite a ejecutar el trabajo para garantizar la
máxima eficacia en el dispositivo Android. Por ejemplo, las solicitudes de red se pueden procesar por lotes para
ejecutar todas al mismo tiempo para hacer un uso máximo de sobrecarga relacionados con las redes.
2. Que encapsula el trabajo – se debe encapsular el código para realizar el trabajo en segundo plano en un
componente discreto que se puede ejecutar independientemente de la interfaz de usuario y será relativamente
fácil volver a programar si no se puede completar el trabajo por algún motivo.
El programador de trabajos de Android es un marco integrado en el sistema operativo Android que proporciona
una API fluida para simplificar el trabajo de programación en segundo plano. El programador de trabajos de
Android consta de los siguientes tipos:
El Android.App.Job.JobScheduler es un servicio de sistema que se usa para programar, ejecutar y, si es necesario
cancelar, trabajos en el nombre de una aplicación de Android.
Un Android.App.Job.JobService es una clase abstracta que debe ampliarse con la lógica que se ejecutará el
trabajo en el subproceso principal de la aplicación. Esto significa que el JobService es responsable de cómo es
el trabajo se realiza de forma asincrónica.
Un Android.App.Job.JobInfo objeto contiene los criterios para guiar Android cuándo se debe ejecutar el trabajo.
Para programar el trabajo con el programador de trabajos de Android, una aplicación de Xamarin.Android debe
encapsular el código en una clase que extiende el JobService clase. JobService tiene tres métodos de ciclo de vida
que se pueden llamar durante la duración del trabajo:
BOOL (parámetros JobParameters) OnStartJob – llama a este método la JobScheduler para realizar el
trabajo y se ejecuta en el subproceso principal de la aplicación. Es responsabilidad de la JobService para
realizar el trabajo de forma asincrónica y true si hay trabajo restante, o false si se realiza el trabajo.
Cuando el JobScheduler llama a este método, solicitará y conservar una wakelock de Android para la
duración del trabajo. Cuando finalice el trabajo, es responsabilidad de la JobService para indicar el
JobScheduler de este hecho por llamada la JobFinished método (que se describe a continuación).

JobFinished (parámetros JobParameters, bool needsReschedule) – este método debe llamarse


mediante el JobService para indicar el JobScheduler que se realiza el trabajo. Si JobFinished no se llama,
el JobScheduler no quitará el wakelock, provocando la purga de la batería innecesarios.
BOOL (parámetros JobParameters) OnStopJob – se llama cuando el trabajo se detiene antes de tiempo
por Android. Debe devolver true si se debe volver a programar el trabajo según los criterios de reintento
(descritos a continuación con más detalle).

Es posible especificar restricciones o desencadenadores controlará cuándo un trabajo puede o debe ejecutarse. Por
ejemplo, es posible restringir un trabajo para que solo se ejecutará cuando el dispositivo se está cargando o se
toma iniciar un trabajo cuando una imagen.
Esta guía describirá en detalle cómo implementar un JobService clase y programarlo con el JobScheduler .

Requisitos
El programador de trabajos Android requiere Android API nivel 21 (Android 5.0) o superior.

Usar al programador de trabajos de Android


Hay tres pasos para usar la API de Android JobScheduler:
1. Implementar un tipo JobService para encapsular el trabajo.
2. Use un JobInfo.Builder objeto va a crear el JobInfo objeto que va a contener los criterios para la
JobScheduler para ejecutar el trabajo.
3. Programar el trabajo mediante JobScheduler.Schedule .
Implementar un JobService
Todo el trabajo realizado por la biblioteca del programador de trabajo Android debe realizarse en un tipo que
extiende el Android.App.Job.JobService clase abstracta. Creación de un JobService es muy similar a la creación de
un Service con el marco de trabajo Android:
1. Ampliar la JobService clase.
2. Decorar la subclase con el ServiceAttribute y establezca el Name parámetro en una cadena que está formada
por el nombre del paquete y el nombre de la clase (vea el ejemplo siguiente).
3. Establecer el Permission propiedad en el ServiceAttribute a la cadena android.permission.BIND_JOB_SERVICE .
4. Invalidar el OnStartJob método, agregue el código para realizar el trabajo. Android invocará este método en el
subproceso principal de la aplicación para ejecutar el trabajo. Trabajo que tarda más que unos pocos
milisegundos deben realizarse en un subproceso para evitar el bloqueo de la aplicación.
5. Cuando se realiza el trabajo, el JobService debe llamar a la JobFinished método. Este método es cómo
JobService indica la JobScheduler que se realiza el trabajo. Error al llamar a JobFinished dará como resultado
la JobService colocar las demandas innecesarias en el dispositivo, lo que reduce la duración de la batería.
6. Es una buena idea para invalidar también el OnStopJob método. Android llama a este método cuando el trabajo
se está cerrando antes de que haya finalizado y proporciona el JobService una oportunidad para desechar
correctamente todos los recursos. Este método debe devolver true si es necesario volver a programar el
trabajo, o false si no es desborde sea deseable para volver a ejecutar el trabajo.
El código siguiente es un ejemplo de las más sencillas JobService para una aplicación, usando la biblioteca TPL
para realizar algún trabajo de forma asincrónica:

[Service(Name = "com.xamarin.samples.downloadscheduler.DownloadJob",
Permission = "android.permission.BIND_JOB_SERVICE")]
public class DownloadJob : JobService
{
public override bool OnStartJob(JobParameters jobParams)
{
Task.Run(() =>
{
// Work is happening asynchronously

// Have to tell the JobScheduler the work is done.


JobFinished(jobParams, false);
});

// Return true because of the asynchronous work


return true;
}

public override bool OnStopJob(JobParameters jobParams)


{
// we don't want to reschedule the job if it is stopped or cancelled.
return false;
}
}

Creación de un elemento JobInfo para programar un trabajo


No cree instancias de las aplicaciones de Xamarin.Android un JobService directamente, en su lugar, pasará un
JobInfo de objeto para el JobScheduler . El JobScheduler creará instancias solicitado JobService objeto,
programar y ejecutar la JobService según los metadatos en el JobInfo . Un JobInfo objeto debe contener la
siguiente información:
JobId – se trata de un int valor que se usa para identificar un trabajo para el JobScheduler . Volver a usar este
valor se actualizarán los trabajos existentes. El valor debe ser único para la aplicación.
JobService – este parámetro es un ComponentName que identifica de forma explícita el tipo que el JobScheduler
debe usar para ejecutar un trabajo.
Este método de extensión muestra cómo crear un JobInfo.Builder con Android Context , por ejemplo, una
actividad:
public static class JobSchedulerHelpers
{
public static JobInfo.Builder CreateJobBuilderUsingJobId<T>(this Context context, int jobId) where
T:JobService
{
var javaClass = Java.Lang.Class.FromType(typeof(T));
var componentName = new ComponentName(context, javaClass);
return new JobInfo.Builder(jobId, componentName);
}
}

// Sample usage - creates a JobBuilder for a DownloadJob and sets the Job ID to 1.
var jobBuilder = this.CreateJobBuilderUsingJobId<DownloadJob>(1);

var jobInfo = jobBuilder.Build(); // creates a JobInfo object.

Una característica eficaz de programador de trabajos de Android es la capacidad para controlar cuándo se ejecuta
un trabajo o en qué condiciones de un trabajo se pueden ejecutar. La tabla siguiente describen algunos de los
métodos en JobInfo.Builder que permitir que una aplicación influir en la que puede ejecutarse un trabajo:

MÉTODO DESCRIPCIÓN

SetMinimumLatency Especifica que se ejecuta un retraso (en milisegundos) que


debe tenerse en cuenta antes de un trabajo.

SetOverridingDeadline Declara que el trabajo debe ejecutarse antes de que haya


transcurrido este tiempo (en milisegundos).

SetRequiredNetworkType Especifica los requisitos de red para un trabajo.

SetRequiresBatteryNotLow El trabajo puede ejecutarse solo cuando el dispositivo no


muestra una advertencia "batería baja" al usuario.

SetRequiresCharging El trabajo puede ejecutarse solo cuando la batería se carga.

SetDeviceIdle El trabajo se ejecutará cuando el dispositivo está ocupado.

SetPeriodic Especifica que el trabajo se debe ejecutar con regularidad.

SetPersisted El trabajo debe perisist en los reinicios del dispositivo.

El SetBackoffCriteria proporciona algunas instrucciones acerca de cómo mientras el JobScheduler debe esperar
antes de intentar volver a ejecutar un trabajo. Los criterios de retroceso consta de dos partes: un retraso en
milisegundos (valor predeterminado de 30 segundos) y el tipo de rechazo que debe usarse (a veces se denomina el
directiva de retroceso o el directiva de reintentos) . Las dos directivas se encapsulan en el
Android.App.Job.BackoffPolicy enum:

BackoffPolicy.Exponential – Una directiva de retroceso exponencial aumentará el valor inicial de retroceso


exponencial después de cada error. La primera vez que se produce un error en un trabajo, la biblioteca esperará
el intervalo inicial que se ha especificado antes de volver a programar el trabajo: ejemplo de 30 segundos. La
segunda vez que se produce un error en el trabajo, la biblioteca de espera al menos 60 segundos antes de
intentar ejecutar el trabajo. Después de la tercera error del intento, la biblioteca de espera de 120 segundos y
así sucesivamente. Este es el valor predeterminado.
BackoffPolicy.Linear – Esta estrategia es un retroceso lineal que se debe volver a programar el trabajo para
ejecutarse a intervalos establecidos (hasta que se realiza correctamente). Retroceso lineal es más adecuado para
el trabajo que debe completarse tan pronto como sea posible o para resolver problemas que se resolverá
rápidamente a sí mismos.
Para obtener más detalles sobre, cree un JobInfo objeto, lea documentación de Google para la JobInfo.Builder
clase.
Pasar parámetros a un trabajo a través de la JobInfo
Los parámetros se pasan a un trabajo mediante la creación de un PersistableBundle que se pasa junto con el
Job.Builder.SetExtras método:

var jobParameters = new PersistableBundle();


jobParameters.PutInt("LoopCount", 11);

var jobBuilder = this.CreateJobBuilderUsingJobId<DownloadJob>(1)


.SetExtras(jobParameters)
.Build();

El PersistableBundlese obtiene acceso desde el Android.App.Job.JobParameters.Extras propiedad en el


OnStartJob método de un JobService :

public override bool OnStartJob(JobParameters jobParameters)


{
var loopCount = jobParams.Extras.GetInt("LoopCount", 10);

// rest of code omitted


}

Programar un trabajo
Para programar un trabajo, una aplicación de Xamarin.Android obtendrá una referencia a la JobScheduler servicio
del sistema y llamar a la JobScheduler.Schedule método con el JobInfo objeto que se creó en el paso anterior.
JobScheduler.Schedule devolverá inmediatamente con uno de dos valores enteros:

JobScheduler.ResultSuccess – el trabajo se programó correctamente.


JobScheduler.ResultFailure – no se puede programar el trabajo. Esto se debe normalmente a entrar en
conflicto JobInfo parámetros.

Este código es un ejemplo de programación de un trabajo y notificar al usuario de los resultados del intento de
programación:

var jobScheduler = (JobScheduler)GetSystemService(JobSchedulerService);


var scheduleResult = jobScheduler.Schedule(jobInfo);

if (JobScheduler.ResultSuccess == scheduleResult)
{
var snackBar = Snackbar.Make(FindViewById(Android.Resource.Id.Content),
Resource.String.jobscheduled_success, Snackbar.LengthShort);
snackBar.Show();
}
else
{
var snackBar = Snackbar.Make(FindViewById(Android.Resource.Id.Content),
Resource.String.jobscheduled_failure, Snackbar.LengthShort);
snackBar.Show();
}

Cancelar un trabajo
Es posible cancelar todos los trabajos que se han programado, o simplemente un único trabajo mediante el
JobsScheduler.CancelAll() método o la JobScheduler.Cancel(jobId) método:

// Cancel all jobs


jobScheduler.CancelAll();

// to cancel a job with jobID = 1


jobScheduler.Cancel(1)

Resumen
Esta guía describe cómo usar al programador de trabajos de Android para realizar el trabajo de forma inteligente
en segundo plano. También se han descrito cómo encapsular el trabajo debe realizarse como una JobService y
cómo usar el JobScheduler para programar ese trabajo, especificar los criterios con un JobTrigger y cómo se
deben controlar los errores con un RetryStrategy .

Vínculos relacionados
Programación de tareas inteligente
Referencia de API JobScheduler
Programación de trabajos como un profesional con JobScheduler
Android batería y optimizaciones de memoria: Google E/S 2016 (vídeo)
Android JobScheduler - René Ruppert
Distribuidor de trabajo de Firebase
11/07/2019 • 27 minutes to read • Edit Online

Esta guía describe cómo programar el trabajo en segundo plano mediante la biblioteca de distribuidor de trabajo
de Firebase de Google.

Información general
Una de las mejores formas para que una aplicación de Android siga respondiendo al usuario es para asegurarse
de que el trabajo complejo o de larga ejecución se realiza en segundo plano. Sin embargo, es importante que
trabajo en segundo plano no afectará negativamente la experiencia del usuario con el dispositivo.
Por ejemplo, un trabajo en segundo plano puede sondear un sitio Web cada tres o cuatro minutos para consultar
los cambios a un determinado conjunto de datos. Esto parece ser benigno, pero tendría un impacto desastroso en
duración de la batería. La aplicación se repetidamente el dispositivo de reactivación, elevar la CPU a un estado de
encendido, el radio de energía, hacer que las solicitudes de red y, a continuación, procesar los resultados. Lo
empeora porque el dispositivo se apague y se devolverá al estado inactivo de baja energía no inmediatamente.
Trabajo en segundo plano programado mal accidentalmente puede mantener el dispositivo en un estado con
requisitos de energía innecesaria y excesiva. Esta actividad aparentemente inofensivo (un sitio Web de sondeo)
representará el dispositivo inutilizable en un período de tiempo relativamente corto.
Android proporciona las siguientes API para ayudar a realizar el trabajo en segundo plano, pero por sí solos no
son suficientes para la programación de tareas inteligente.
Servicios de intención – servicios de intención son excelentes para llevar a cabo el trabajo, pero que no
ofrecen ninguna forma para programar el trabajo.
AlarmManager – estas API solo permiten que el trabajo puede programar pero no ofrecen ninguna forma
para llevar a cabo el trabajo. Además, el AlarmManager solo permite las restricciones en función del tiempo, lo
que significa que genera una alarma en un momento determinado o una vez transcurrido un período de
tiempo determinado.
JobScheduler – JobSchedule The es una API excelente que funciona con el sistema operativo para programar
trabajos. Sin embargo, solo está disponible para las aplicaciones de Android que tienen como destino el nivel
de API 21 o posterior.
Receptores de difusión – An Android app puede configurar receptores de difusión para llevar a cabo trabajo
en respuesta a eventos de todo el sistema o intenciones. Sin embargo, los receptores de difusión no
proporcionan ningún control sobre cuándo se debe ejecutar el trabajo. También se restringirán los cambios en
el sistema operativo Android cuando funcionará receptores de difusión o los tipos de trabajo que puede
responder.
Hay dos características clave para realizar eficazmente el trabajo en segundo plano (a veces se denomina un
trabajo en segundo plano o un trabajo):
1. Programar el trabajo de forma inteligente – es importante que cuando una aplicación está realizando
trabajo en segundo plano que lo hace como un buen ciudadano. Idealmente, la aplicación no debería exigir que
se ejecute un trabajo. En su lugar, la aplicación debe especificar las condiciones que deben cumplirse para
cuando el trabajo puede ejecutar y, a continuación, programar ese trabajo para ejecutarlo cuando se cumplen
las condiciones. Esto permite a Android realizar el trabajo de forma inteligente. Por ejemplo, las solicitudes de
red se pueden procesar por lotes para ejecutar todas al mismo tiempo para hacer un uso máximo de
sobrecarga relacionados con las redes.
2. Que encapsula el trabajo – se debe encapsular el código para realizar el trabajo en segundo plano en un
componente discreto que se puede ejecutar independientemente de la interfaz de usuario y será relativamente
fácil volver a programar si no se puede completar el trabajo por algún motivo.
El distribuidor de trabajo de Firebase es una biblioteca de Google que proporciona una API fluida para simplificar
el trabajo de programación en segundo plano. Se sirve de reemplazo para el Administrador de la nube de Google.
El distribuidor de trabajo de Firebase consta de las siguientes API:
Un Firebase.JobDispatcher.JobService es una clase abstracta que debe ampliarse con la lógica que se ejecutará
en el trabajo en segundo plano.
Un Firebase.JobDispatcher.JobTrigger declara cuando debe iniciarse el trabajo. Esto normalmente se expresa
como una ventana de tiempo, por ejemplo, espere al menos 30 segundos antes de iniciar el trabajo, pero
ejecutar el trabajo en 5 minutos.
Un Firebase.JobDispatcher.RetryStrategy contiene información sobre lo que debe realizarse cuando se
produce un error en un trabajo se ejecute correctamente. La estrategia de reintento especifica cuánto tiempo
debe esperar antes de intentar volver a ejecutar el trabajo.
Un Firebase.JobDispatcher.Constraint es un valor opcional que describe una condición que debe cumplirse
antes de poder ejecutar el trabajo, como el dispositivo está en una red unmetered o cargando.
El Firebase.JobDispatcher.Job es una API que unifica las API de anteriores en una unidad de trabajo que se
puede programar la JobDispatcher . El Job.Builder clase se utiliza para crear una instancia de un Job .
Un Firebase.JobDispatcher.JobDispatcher usa las tres API anteriores para programar el trabajo con el sistema
operativo y para proporcionar una manera de cancelar trabajos, si es necesario.
Para programar el trabajo con el distribuidor de trabajo de Firebase, una aplicación de Xamarin.Android debe
encapsular el código en un tipo que extiende el JobService clase. JobService tiene tres métodos de ciclo de vida
que se pueden llamar durante la duración del trabajo:
bool OnStartJob(IJobParameters parameters) – Este método es donde el trabajo se realizará y siempre se debe
implementar. Se ejecuta en el subproceso principal. Este método devolverá true si hay trabajo restante, o
false si se realiza el trabajo.
bool OnStopJob(IJobParameters parameters) – Se llama cuando el trabajo se ha detenido por alguna razón.
Debe devolver true si se debe volver a programar el trabajo para su uso posterior.
JobFinished(IJobParameters parameters, bool needsReschedule) – Este método se llama cuando el JobService
ha finalizado el trabajo asincrónico.
Para programar un trabajo, creará una instancia de la aplicación un JobDispatcher objeto. A continuación,
Job.Builder se utiliza para crear un Job objeto, que se proporciona para el JobDispatcher que pruebe y
programar la ejecución del trabajo.
Esta guía describirá cómo agregar el distribuidor de trabajo de Firebase a una aplicación de Xamarin.Android y
usarla para programar trabajo en segundo plano.

Requisitos
El distribuidor de trabajo de Firebase requiere el nivel de API de Android 9 o superior. La biblioteca de
distribuidor de trabajo de Firebase depende de algunos componentes de Google Play Services; el dispositivo debe
tener instalados los servicios de Google Play.

Uso de la biblioteca de distribuidor de trabajo de Firebase en


Xamarin.Android
Para empezar a trabajar con el distribuidor de trabajo de Firebase, agregue primero el paquete
Xamarin.Firebase.JobDispatcher NuGet al proyecto de Xamarin.Android. Buscar el Administrador de paquetes de
NuGet para la Xamarin.Firebase.JobDispatcher paquete (que todavía está en versión preliminar).
Después de agregar la biblioteca de distribuidor de trabajo de Firebase, cree un JobService clase y, a
continuación, programarlo para ejecutarlo con una instancia de la FirebaseJobDispatcher .
Creación de un JobService
Todo el trabajo realizado por la biblioteca de distribuidor de trabajo de Firebase debe realizarse en un tipo que
extiende el Firebase.JobDispatcher.JobService clase abstracta. Creación de un JobService es muy similar a la
creación de un Service con el marco de trabajo Android:
1. Ampliar la JobService clase
2. Decorar la subclase con el ServiceAttribute . Aunque no es estrictamente necesario, se recomienda establecer
explícitamente el Name parámetro para ayudar con la depuración el JobService .
3. Agregar un IntentFilter para declarar el JobService en el AndroidManifest.xml. Esto también ayudará a la
biblioteca de distribuidor de trabajo de Firebase localizar e invocar el JobService .
El código siguiente es un ejemplo de las más sencillas JobService para una aplicación, usando la biblioteca TPL
para realizar algún trabajo de forma asincrónica:

[Service(Name = "com.xamarin.fjdtestapp.DemoJob")]
[IntentFilter(new[] {FirebaseJobServiceIntent.Action})]
public class DemoJob : JobService
{
static readonly string TAG = "X:DemoService";

public override bool OnStartJob(IJobParameters jobParameters)


{
Task.Run(() =>
{
// Work is happening asynchronously (code omitted)

});

// Return true because of the asynchronous work


return true;
}

public override bool OnStopJob(IJobParameters jobParameters)


{
Log.Debug(TAG, "DemoJob::OnStartJob");
// nothing to do.
return false;
}
}

Creación de un FirebaseJobDispatcher
Antes de que se puede programar cualquier trabajo, es necesario crear un
Firebase.JobDispatcher.FirebaseJobDispatcher objeto. El FirebaseJobDispatcher es responsable de programar un
JobService . El siguiente fragmento de código es una forma de crear una instancia de la FirebaseJobDispatcher :

// This is the "Java" way to create a FirebaseJobDispatcher object


IDriver driver = new GooglePlayDriver(context);
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(driver);

En el fragmento de código anterior, el GooglePlayDriver es la clase que ayuda a los FirebaseJobDispatcher


interactúan algunas de las API de programación en Google Play Services en el dispositivo. El parámetro context
es cualquier Android Context , por ejemplo, una actividad. Actualmente la GooglePlayDriver es el único IDriver
implementación en la biblioteca de distribuidor de trabajo de Firebase.
El enlace de Xamarin.Android para el distribuidor de trabajo de Firebase proporciona un método de extensión
para crear un FirebaseJobDispatcher desde el Context :

FirebaseJobDispatcher dispatcher = context.CreateJobDispatcher();

Una vez el FirebaseJobDispatcher ha sido de instancias, es posible crear un Job y ejecutar el código de la
JobService clase. El Job creado por un Job.Builder de objeto y se describe en la sección siguiente.
Creación de un Firebase.JobDispatcher.Job con el Job.Builder
El Firebase.JobDispatcher.Job clase es responsable de que encapsula los metadatos necesarios para ejecutar un
JobService . Un Job contiene información como cualquier restricción que debe cumplirse antes de poder ejecutar
el trabajo, si la Job es periódico, o todos los desencadenadores que hará que el trabajo que se ejecutará. Como
mínimo, un Job debe tener un etiqueta (una cadena única que identifica el trabajo para el FirebaseJobDispatcher
) y el tipo de la JobService que se debe ejecutar. Creará una instancia del distribuidor de trabajo de Firebase el
JobService cuando llega el momento para ejecutar el trabajo. Un Job se crea mediante el uso de una instancia de
la Firebase.JobDispatcher.Job.JobBuilder clase.
El siguiente fragmento de código es el ejemplo más sencillo de cómo crear un Job utilizando el enlace de
Xamarin.Android:

Job myJob = dispatcher.NewJobBuilder()


.SetService<DemoJob>("demo-job-tag")
.Build();

El Job.Builder llevará a cabo algunas comprobaciones de validación básicas en los valores de entrada para el
trabajo. Se producirá una excepción si no es posible para el Job.Builder para crear un Job . El Job.Builder creará
un Job con los valores predeterminados siguientes:
Un Job del duración (cuánto se programará para ejecutarse) solo es hasta que el dispositivo se reinicia – una
vez que el dispositivo se reinicia el Job se pierde.
Un Job no es periódico – sólo se ejecutará una vez.
Un Job se programará para que se ejecute tan pronto como sea posible.
La estrategia de reintento predeterminada para un Job consiste en usar un retroceso exponencial (tratadas en
más detalle más adelante en la sección establecer un RetryStrategy)
Programar un trabajo
Después de crear el Job , se debe programar con la FirebaseJobDispatcher antes de ejecutarse. Hay dos métodos
para programar un Job :

// This will throw an exception if there was a problem scheduling the job
dispatcher.MustSchedule(myJob);

// This method will not throw an exception; an integer result value is returned
int scheduleResult = dispatcher.Schedule(myJob);

El valor devuelto por FirebaseJobDispatcher.Schedule será uno de los siguientes valores enteros:
FirebaseJobDispatcher.ScheduleResultSuccess – El Job se programó correctamente.
FirebaseJobDispatcher.ScheduleResultUnknownError – Lo que impide que produjo algún problema desconocido
el Job de programarse.
FirebaseJobDispatcher.ScheduleResultNoDriverAvailable – No es válido IDriver se usó o IDriver algún modo
no estaba disponible.
FirebaseJobDispatcher.ScheduleResultUnsupportedTrigger – El Trigger no era compatible.
FirebaseJobDispatcher.ScheduleResultBadService – El servicio no está configurado correctamente o no está
disponible.
Configuración de un trabajo
Es posible personalizar un trabajo. Ejemplos de cómo se puede personalizar un trabajo incluyen lo siguiente:
Pasar parámetros a un trabajo – A Job puede requerir valores adicionales para realizar su trabajo, por
ejemplo descarga un archivo.
Establecer restricciones – puede ser necesario ejecutar solo un trabajo cuando se cumplen ciertas condiciones.
Por ejemplo, solo se ejecute un Job cuando el dispositivo se está cargando.
Especifique cuándo un Job debe ejecutarse – el distribuidor de trabajo de Firebase permite que las
aplicaciones especificar un tiempo de cuándo se debe ejecutar el trabajo.
Declarar una estrategia de reintento para trabajos con errores – A estrategia de reintento proporciona
orientación para la FirebaseJobDispatcher sobre qué hacer con Jobs que no puedan completarse.

Cada uno de estos temas se tratarán más en las secciones siguientes.


Pasar parámetros a un trabajo
Los parámetros se pasan a un trabajo mediante la creación de un Bundle que se pasa junto con el
Job.Builder.SetExtras método:

Bundle jobParameters = new Bundle();


jobParameters.PutInt(FibonacciCalculatorJob.FibonacciPositionKey, 25);

Job myJob = dispatcher.NewJobBuilder()


.SetService<DemoJob>("demo-job-tag")
.SetExtras(jobParameters)
.Build();

El Bundle se obtiene acceso desde el IJobParameters.Extras propiedad en el OnStartJob método:

public override bool OnStartJob(IJobParameters jobParameters)


{
int position = jobParameters.Extras.GetInt(FibonacciPositionKey, DEFAULT_VALUE);

// rest of code omitted


}

Configuración de restricciones
Pueden ayudar las restricciones reduce los costos ni la batería purga en el dispositivo. La
Firebase.JobDispatcher.Constraint clase define estas restricciones como valores enteros:

Constraint.OnUnmeteredNetwork – Solo debe ejecutar el trabajo cuando el dispositivo está conectado a una red
unmetered. Esto es útil para evitar que el usuario incurrir en cargos por datos.
Constraint.OnAnyNetwork – Ejecute el trabajo en cualquier red que está conectado el dispositivo. Si se especifica
junto con Constraint.OnUnmeteredNetwork , este valor tendrá prioridad.
Constraint.DeviceCharging – Ejecute el trabajo solo cuando el dispositivo se está cargando.

Las restricciones se establecen con el Job.Builder.SetConstraint método:

Job myJob = dispatcher.NewJobBuilder()


.SetService<DemoJob>("demo-job-tag")
.SetConstraint(Constraint.DeviceCharging)
.Build();
El JobTrigger proporciona orientación para el sistema operativo sobre cuándo debe comenzar el trabajo. Un
JobTrigger tiene un ejecutando ventana que define una hora programada para cuando el Job debe ejecutarse.
La ventana de ejecución tiene un iniciar ventana valor y un ventana de finalización valor. La ventana de inicio es el
número de segundos que el dispositivo debe esperar antes de ejecutar el trabajo y el valor de la ventana de
finalización es el número máximo de segundos que deben transcurrir antes de ejecutar el Job .
Un JobTriggerpueden crearse con el Firebase.Jobdispatcher.Trigger.ExecutionWindow método. Por ejemplo
Trigger.ExecutionWindow(15,60) significa que debe ejecutarse el trabajo entre 15 y 60 segundos desde cuando
esté programada. El Job.Builder.SetTrigger método se usa para

JobTrigger myTrigger = Trigger.ExecutionWindow(15,60);


Job myJob = dispatcher.NewJobBuilder()
.SetService<DemoJob>("demo-job-tag")
.SetTrigger(myTrigger)
.Build();

El valor predeterminado JobTrigger para un trabajo está representado por el valor Trigger.Now , que especifica
que un trabajo se ejecute tan pronto como sea posible después de estar programado...
Establecer un RetryStrategy
El Firebase.JobDispatcher.RetryStrategy se usa para especificar qué parte de un retraso de un dispositivo debe
usar antes de intentar volver a ejecutar un trabajo con error. Un RetryStrategy tiene un directiva, que define qué
algoritmo de la base de tiempo que se utilizará para volver a programar el trabajo con error y una ventana de
ejecución que especifica una ventana en la que se debe programar el trabajo. Esto ventana Reprogramación se
define mediante dos valores. El primer valor es el número de segundos que deben transcurrir antes de volver a
programar el trabajo (el retroceso inicial valor), y el segundo número es el número máximo de segundos antes de
que el trabajo debe ejecutar (el _retroceso máximo_valor).
Los dos tipos de directivas de reintento se identifican con estos valores de tipo int:
RetryStrategy.RetryPolicyExponential – Un retroceso exponencial directiva aumentará el valor inicial de
retroceso exponencial después de cada error. La primera vez que se produce un error en un trabajo, la
biblioteca esperará el intervalo de _inicial que se ha especificado antes de volver a programar el trabajo –
ejemplo 30 segundos. La segunda vez que se produce un error en el trabajo, la biblioteca de espera al menos
60 segundos antes de intentar ejecutar el trabajo. Después de la tercera error del intento, la biblioteca de
espera de 120 segundos y así sucesivamente. El valor predeterminado RetryStrategy para el distribuidor de
trabajo de Firebase biblioteca está representada por la RetryStrategy.DefaultExponential objeto. Tiene un
retroceso inicial de 30 segundos y un retroceso máximo de 3600 segundos.
RetryStrategy.RetryPolicyLinear – Esta estrategia es un retroceso lineal que se debe volver a programar el
trabajo para ejecutarse al establece los intervalos (hasta que se realiza correctamente). Retroceso lineal es más
adecuado para el trabajo que debe completarse tan pronto como sea posible o para resolver problemas que se
resolverá rápidamente a sí mismos. La biblioteca de distribuidor de trabajo de Firebase define un
RetryStrategy.DefaultLinear que tiene una ventana Reprogramación de al menos 30 segundos y hasta 3600
segundos.
Es posible definir un personalizado RetryStrategy con el FirebaseJobDispatcher.NewRetryStrategy método. Acepta
tres parámetros:
1. int policy – El directiva es uno de los anteriores RetryStrategy valores, RetryStrategy.RetryPolicyLinear , o
RetryStrategy.RetryPolicyExponential .
2. int initialBackoffSeconds – El retroceso inicial es un retraso, en segundos, que es necesario antes de intentar
volver a ejecutar el trabajo. El valor predeterminado es 30 segundos.
3. int maximumBackoffSeconds – El retroceso máximo valor declara el número máximo de segundos de retraso
antes de intentar volver a ejecutar el trabajo. El valor predeterminado es 3600 segundos.
RetryStrategy retry = dispatcher.NewRetryStrategy(RetryStrategy.RetryPolicyLinear, initialBackoffSeconds,
maximumBackoffSet);

// Create a Job and set the RetryStrategy via the Job.Builder


Job myJob = dispatcher.NewJobBuilder()
.SetService<DemoJob>("demo-job-tag")
.SetRetryStrategy(retry)
.Build();

Cancelar un trabajo
Es posible cancelar todos los trabajos que se han programado, o simplemente un único trabajo mediante el
FirebaseJobDispatcher.CancelAll() método o la FirebaseJobDispatcher.Cancel(string) método:

int cancelResult = dispatcher.CancelAll();

// to cancel a single job:

int cancelResult = dispatcher.Cancel("unique-tag-for-job");

Devuelven un valor entero cualquiera de estos métodos:


FirebaseJobDispatcher.CancelResultSuccess – El trabajo se canceló correctamente.
FirebaseJobDispatcher.CancelResultUnknownError – Un error impidió que se está cancelando el trabajo.
FirebaseJobDispatcher.CancelResult.NoDriverAvailable – El FirebaseJobDispatcher no puede cancelar el trabajo
ya no es válido no IDriver disponibles.

Resumen
Esta guía describe cómo usar el distribuidor de trabajo de Firebase para realizar el trabajo de forma inteligente en
segundo plano. También se han descrito cómo encapsular el trabajo debe realizarse como una JobService y cómo
usar el FirebaseJobDispatcher para programar ese trabajo, especificar los criterios con un JobTrigger y cómo se
deben controlar los errores con un RetryStrategy .

Vínculos relacionados
Xamarin.Firebase.JobDispatcher en NuGet
firebase-trabajo-dispatcher en GitHub
Enlace Xamarin.Firebase.JobDispatcher
Programación de tareas inteligente
Android batería y optimizaciones de memoria: Google E/S 2016 (vídeo)
Fragments
16/08/2019 • 6 minutes to read • Edit Online

Android 3,0 presentó fragmentos, en los que se muestra cómo admitir diseños más flexibles para los diferentes
tamaños de pantalla que se encuentran en teléfonos y tabletas. En este artículo se explica cómo usar fragmentos
para desarrollar aplicaciones de Xamarin. Android y cómo admitir fragmentos en dispositivos anteriores a
Android 3,0 (nivel de API 11 ).

Información general sobre fragmentos


Los tamaños de pantalla más grandes que se encuentran en la mayoría de las tabletas agregan una capa
adicional de complejidad al desarrollo de Android: un diseño diseñado para la pantalla pequeña no funciona
también en pantallas más grandes y viceversa. Para reducir el número de complicaciones que se introdujeron en,
Android 3,0 agregó dos nuevas características, fragmentos y paquetes de soporte técnico.
Los fragmentos se pueden considerar como módulos de interfaz de usuario. Permiten al desarrollador dividir la
interfaz de usuario en elementos aislados y reutilizables que se pueden ejecutar en actividades independientes.
En tiempo de ejecución, las propias actividades decidirán qué fragmentos se van a utilizar.
Los paquetes de soporte técnico se denominaban originalmente bibliotecas de compatibilidad y fragmentos
permitidos que se usarán en dispositivos que ejecutan versiones de Android anteriores a Android 3,0 (nivel de
API 11).
Por ejemplo, en la imagen siguiente se muestra cómo una sola aplicación utiliza fragmentos en diversos factores
de forma de dispositivo.

El fragmento A contiene una lista, mientras que el fragmento B contiene detalles de un elemento seleccionado
en esa lista. Cuando la aplicación se ejecuta en una tableta, puede mostrar ambos fragmentos en la misma
actividad. Cuando se ejecuta la misma aplicación en un auricular (con un tamaño de pantalla menor), los
fragmentos se hospedan en dos actividades independientes. Los fragmentos A y B son los mismos en ambos
factores de forma, pero las actividades que los hospedan son diferentes.
Para ayudar a que una actividad coordine y administre todos estos fragmentos, Android presentó una nueva
clase denominada FragmentManager. Cada actividad tiene su propia instancia de FragmentManager para agregar,
eliminar y buscar fragmentos hospedados. En el diagrama siguiente se ilustra la relación entre los fragmentos y
las actividades:
En algunos aspectos, los fragmentos se pueden considerar como controles compuestos o como actividades
mínimas. Agrupan partes de la interfaz de usuario en módulos reutilizables que se pueden usar de forma
independiente por parte de los desarrolladores en las actividades. Un fragmento tiene una jerarquía de vistas, al
igual que una actividad, pero, a diferencia de una actividad, se puede compartir entre pantallas. Las vistas difieren
de los fragmentos en que los fragmentos tienen su propio ciclo de vida; las vistas no lo hacen.
Aunque la actividad es un host a uno o varios fragmentos, no es directamente consciente de los propios
fragmentos. Del mismo modo, los fragmentos no reconocen directamente otros fragmentos en la actividad de
hospedaje. Sin embargo, los FragmentManager fragmentos y las actividades son conscientes del de su actividad.
Mediante el uso FragmentManager de, es posible que una actividad o un fragmento obtengan una referencia a una
instancia específica de un fragmento y, a continuación, llame a métodos en esa instancia. De esta manera, la
actividad o los fragmentos pueden comunicarse e interactuar con otros fragmentos.
Esta guía contiene una cobertura completa sobre cómo usar fragmentos, entre los que se incluyen:
Crear fragmentos : Cómo crear un fragmento básico y métodos clave que se deben implementar.
Administración de fragmentos y transacciones : Cómo manipular fragmentos en tiempo de ejecución.
Paquete de soporte de Android : Cómo usar las bibliotecas que permiten usar fragmentos en versiones
anteriores de Android.

Requisitos
Los fragmentos están disponibles en la Android SDK a partir del nivel de API 11 (Android 3,0), tal como se
muestra en la siguiente captura de pantalla:
Los fragmentos están disponibles en Xamarin. Android 4,0 y versiones posteriores. Una aplicación de Xamarin.
Android debe tener como destino al menos el nivel de API 11 (Android 3,0) o superior para poder usar
fragmentos. La plataforma de destino se puede establecer en las propiedades del proyecto, como se muestra a
continuación:

Es posible usar fragmentos en versiones anteriores de Android mediante el paquete de soporte de Android y
Xamarin. Android 4,2 o superior. La forma de hacerlo se describe con más detalle en los documentos de esta
sección.

Vínculos relacionados
Galería de Honeycomb (ejemplo)
Fragmentos
Paquete de soporte
Seminario Web de MOTODEV: Presentación de fragmentos
Implementación de fragmentos: tutorial
31/07/2019 • 5 minutes to read • Edit Online

Los fragmentos son componentes modulares e independientes que pueden ayudar a abordar la complejidad de las
aplicaciones Android que tienen como destino dispositivos con diversos tamaños de pantalla. En este artículo se
explica cómo crear y usar fragmentos al desarrollar aplicaciones de Xamarin. Android.

Información general
En esta sección, recorreremos cómo crear y usar fragmentos en una aplicación de Xamarin. Android. Esta
aplicación mostrará los títulos de varios reproducciones de William Shakespeare en una lista. Cuando el usuario
pulsa el título de una reproducción, la aplicación mostrará una oferta de la misma en una actividad independiente:

Cuando el teléfono se gira en el modo horizontal, la apariencia de la aplicación cambiará: la lista de reproducciones
y las comillas se mostrarán en la misma actividad. Cuando se selecciona reproducir, la oferta se mostrará en la
misma actividad:
Por último, si la aplicación se ejecuta en una tableta:

Esta aplicación de ejemplo se puede adaptar fácilmente a los distintos factores de forma y orientaciones con
cambios mínimos en el código mediante fragmentos y diseños alternativos.
Los datos de la aplicación se encontrarán en dos matrices de cadenas codificadas de forma rígida C# en la
aplicación como matrices de cadenas. Cada una de las matrices actuará como origen de datos para un fragmento.
Una matriz contendrá el nombre de algunas jugadas por Shakespeare y la otra matriz contendrá una comilla de
esa jugada. Cuando se inicia la aplicación, se muestran los nombres de reproducción en un ListFragment . Cuando
el usuario hace clic en una reproducción en el ListFragment , la aplicación iniciará otra actividad que mostrará la
cotización.
La interfaz de usuario de la aplicación constará de dos diseños, uno para vertical y otro para el modo horizontal. En
tiempo de ejecución, Android determinará qué diseño se va a cargar en función de la orientación del dispositivo y
proporcionará ese diseño a la actividad que se va a representar. Toda la lógica para responder a los clics del usuario
y mostrar los datos se incluirá en fragmentos. Las actividades de la aplicación solo existen como contenedores que
hospedarán los fragmentos.
Este tutorial se dividirá en dos guías. La primera parte se centrará en las partes principales de la aplicación. Se
creará un único conjunto de diseños (optimizado para el modo vertical), junto con dos fragmentos y dos
actividades:
1. MainActivity Esta es la actividad de inicio de la aplicación.
2. TitlesFragment Este fragmento mostrará una lista de los títulos de las reproducciones que ha escrito William
Shakespeare. Se hospedará en MainActivity .
3. PlayQuoteActivity iniciará enrespuesta TitlesFragment al usuario que selecciona una reproducción en.
PlayQuoteActivity TitlesFragment
4. PlayQuoteFragment Este fragmento mostrará una comilla de un juego de William Shakespeare. Se hospedará
en PlayQuoteActivity .
En la segunda parte de este tutorial se explica cómo agregar un diseño alternativo (optimizado para el modo
horizontal) que mostrará ambos fragmentos en la pantalla. Además, se realizarán algunos cambios de código
secundarios en el código para que la aplicación adapte su comportamiento al número de fragmentos que se
muestran simultáneamente en la pantalla.

Vínculos relacionados
FragmentsWalkthrough (ejemplo)
Información general del diseñador
Implementar fragmentos
Paquete de soporte
Fragmentos tutorial – del teléfono
19/07/2019 • 17 minutes to read • Edit Online

Esta es la primera parte de un tutorial que creará una aplicación de Xamarin. Android destinada a un dispositivo
Android en orientación vertical. En este tutorial se explica cómo crear fragmentos en Xamarin. Android y cómo
agregarlos a un ejemplo.

Se crearán las siguientes clases para esta aplicación:


1. PlayQuoteFragmentEste fragmento mostrará una comilla de un juego de William Shakespeare. Se hospedará
en PlayQuoteActivity .
2. Shakespeare Esta clase contendrá dos matrices codificadas como propiedades.
3. TitlesFragment Este fragmento mostrará una lista de los títulos de las reproducciones que ha escrito William
Shakespeare. Se hospedará en MainActivity .
4. PlayQuoteActivity iniciará enrespuesta TitlesFragment al usuario que selecciona una reproducción en.
PlayQuoteActivity TitlesFragment

1. Crear el proyecto de Android


Cree un nuevo proyecto de Xamarin. Android denominado FragmentSample.
Visual Studio
Visual Studio para Mac
2. Agregar los datos
Los datos de esta aplicación se almacenarán en dos matrices de cadenas codificadas que son propiedades de un
nombre Shakespeare de clase:
Shakespeare.Titles Esta matriz contendrá una lista de reproducciones de William Shakespeare. Este es el
origen de datos de TitlesFragment .
Shakespeare.Dialogue Esta matriz contendrá una lista de Comillas de una de las jugadas contenidas en
Shakespeare.Titles . Este es el origen de datos de PlayQuoteFragment .

Agregue una nueva C# clase al proyecto FragmentSample y asígnele el nombre Shakespeare.CS. Dentro de
este archivo, cree una C# nueva clase Shakespeare denominada con el siguiente contenido

class Shakespeare
{
public static string[] Titles = {
"Henry IV (1)",
"Henry V",
"Henry VIII",
"Richard II",
"Richard III",
"Merchant of Venice",
"Othello",
"King Lear"
};

public static string[] Dialogue = {


"So shaken as we are, so wan with care, Find we a time for frighted
peace to pant, And breathe short-winded accents of new broils To be commenced in strands afar remote. No more
the thirsty entrance of this soil Shall daub her lips with her own children's blood; Nor more shall trenching
war channel her fields, Nor bruise her flowerets with the armed hoofs Of hostile paces: those opposed eyes,
Which, like the meteors of a troubled heaven, All of one nature, of one substance bred, Did lately meet in the
intestine shock And furious close of civil butchery Shall now, in mutual well-beseeming ranks, March all one
way and be no more opposed Against acquaintance, kindred and allies: The edge of war, like an ill-sheathed
knife, No more shall cut his master. Therefore, friends, As far as to the sepulchre of Christ, Whose soldier
now, under whose blessed cross We are impressed and engaged to fight, Forthwith a power of English shall we
levy; Whose arms were moulded in their mothers' womb To chase these pagans in those holy fields Over whose
acres walk'd those blessed feet Which fourteen hundred years ago were nail'd For our advantage on the bitter
cross. But this our purpose now is twelve month old, And bootless 'tis to tell you we will go: Therefore we
meet not now. Then let me hear Of you, my gentle cousin Westmoreland, What yesternight our council did decree
In forwarding this dear expedience.",
"Hear him but reason in divinity, And all-admiring with an inward wish
"Hear him but reason in divinity, And all-admiring with an inward wish
You would desire the king were made a prelate: Hear him debate of commonwealth affairs, You would say it hath
been all in all his study: List his discourse of war, and you shall hear A fearful battle render'd you in
music: Turn him to any cause of policy, The Gordian knot of it he will unloose, Familiar as his garter: that,
when he speaks, The air, a charter'd libertine, is still, And the mute wonder lurketh in men's ears, To steal
his sweet and honey'd sentences; So that the art and practic part of life Must be the mistress to this
theoric: Which is a wonder how his grace should glean it, Since his addiction was to courses vain, His
companies unletter'd, rude and shallow, His hours fill'd up with riots, banquets, sports, And never noted in
him any study, Any retirement, any sequestration From open haunts and popularity.",
"I come no more to make you laugh: things now, That bear a weighty and
a serious brow, Sad, high, and working, full of state and woe, Such noble scenes as draw the eye to flow, We
now present. Those that can pity, here May, if they think it well, let fall a tear; The subject will deserve
it. Such as give Their money out of hope they may believe, May here find truth too. Those that come to see
Only a show or two, and so agree The play may pass, if they be still and willing, I'll undertake may see away
their shilling Richly in two short hours. Only they That come to hear a merry bawdy play, A noise of targets,
or to see a fellow In a long motley coat guarded with yellow, Will be deceived; for, gentle hearers, know, To
rank our chosen truth with such a show As fool and fight is, beside forfeiting Our own brains, and the opinion
that we bring, To make that only true we now intend, Will leave us never an understanding friend. Therefore,
for goodness' sake, and as you are known The first and happiest hearers of the town, Be sad, as we would make
ye: think ye see The very persons of our noble story As they were living; think you see them great, And
follow'd with the general throng and sweat Of thousand friends; then in a moment, see How soon this mightiness
meets misery: And, if you can be merry then, I'll say A man may weep upon his wedding-day.",
"First, heaven be the record to my speech! In the devotion of a
subject's love, Tendering the precious safety of my prince, And free from other misbegotten hate, Come I
appellant to this princely presence. Now, Thomas Mowbray, do I turn to thee, And mark my greeting well; for
what I speak My body shall make good upon this earth, Or my divine soul answer it in heaven. Thou art a
traitor and a miscreant, Too good to be so and too bad to live, Since the more fair and crystal is the sky,
The uglier seem the clouds that in it fly. Once more, the more to aggravate the note, With a foul traitor's
name stuff I thy throat; And wish, so please my sovereign, ere I move, What my tongue speaks my right drawn
sword may prove.",
"Now is the winter of our discontent Made glorious summer by this sun
of York; And all the clouds that lour'd upon our house In the deep bosom of the ocean buried. Now are our
brows bound with victorious wreaths; Our bruised arms hung up for monuments; Our stern alarums changed to
merry meetings, Our dreadful marches to delightful measures. Grim-visaged war hath smooth'd his wrinkled
front; And now, instead of mounting barded steeds To fright the souls of fearful adversaries, He capers nimbly
in a lady's chamber To the lascivious pleasing of a lute. But I, that am not shaped for sportive tricks, Nor
made to court an amorous looking-glass; I, that am rudely stamp'd, and want love's majesty To strut before a
wanton ambling nymph; I, that am curtail'd of this fair proportion, Cheated of feature by dissembling nature,
Deformed, unfinish'd, sent before my time Into this breathing world, scarce half made up, And that so lamely
and unfashionable That dogs bark at me as I halt by them; Why, I, in this weak piping time of peace, Have no
delight to pass away the time, Unless to spy my shadow in the sun And descant on mine own deformity: And
therefore, since I cannot prove a lover, To entertain these fair well-spoken days, I am determined to prove a
villain And hate the idle pleasures of these days. Plots have I laid, inductions dangerous, By drunken
prophecies, libels and dreams, To set my brother Clarence and the king In deadly hate the one against the
other: And if King Edward be as true and just As I am subtle, false and treacherous, This day should Clarence
closely be mew'd up, About a prophecy, which says that 'G' Of Edward's heirs the murderer shall be. Dive,
thoughts, down to my soul: here Clarence comes.",
"To bait fish withal: if it will feed nothing else, it will feed my
revenge. He hath disgraced me, and hindered me half a million; laughed at my losses, mocked at my gains,
scorned my nation, thwarted my bargains, cooled my friends, heated mine enemies; and what's his reason? I am a
Jew. Hath not a Jew eyes? hath not a Jew hands, organs, dimensions, senses, affections, passions? fed with the
same food, hurt with the same weapons, subject to the same diseases, healed by the same means, warmed and
cooled by the same winter and summer, as a Christian is? If you prick us, do we not bleed? if you tickle us,
do we not laugh? if you poison us, do we not die? and if you wrong us, shall we not revenge? If we are like
you in the rest, we will resemble you in that. If a Jew wrong a Christian, what is his humility? Revenge. If a
Christian wrong a Jew, what should his sufferance be by Christian example? Why, revenge. The villany you teach
me, I will execute, and it shall go hard but I will better the instruction.",
"Virtue! a fig! 'tis in ourselves that we are thus or thus. Our bodies
are our gardens, to the which our wills are gardeners: so that if we will plant nettles, or sow lettuce, set
hyssop and weed up thyme, supply it with one gender of herbs, or distract it with many, either to have it
sterile with idleness, or manured with industry, why, the power and corrigible authority of this lies in our
wills. If the balance of our lives had not one scale of reason to poise another of sensuality, the blood and
baseness of our natures would conduct us to most preposterous conclusions: but we have reason to cool our
raging motions, our carnal stings, our unbitted lusts, whereof I take this that you call love to be a sect or
scion.",
"Blow, winds, and crack your cheeks! rage! blow! You cataracts and
hurricanoes, spout Till you have drench'd our steeples, drown'd the cocks! You sulphurous and thought-
executing fires, Vaunt-couriers to oak-cleaving thunderbolts, Singe my white head! And thou, all-shaking
thunder, Smite flat the thick rotundity o' the world! Crack nature's moulds, an germens spill at once, That
make ingrateful man!"
make ingrateful man!"
};
}

3. Crear PlayQuoteFragment
PlayQuoteFragment Es un fragmento de Android que mostrará una comilla para una reproducción de Shakespeare
seleccionada por el usuario anteriormente en la aplicación. este fragmento no usará un archivo de diseño de
Android; en su lugar, creará dinámicamente su interfaz de usuario. Agregue una nueva Fragment clase
denominada PlayQuoteFragment al proyecto:
Visual Studio
Visual Studio para Mac

A continuación, cambie el código del fragmento para que sea similar a este fragmento:
public class PlayQuoteFragment : Fragment
{
public int PlayId => Arguments.GetInt("current_play_id", 0);

public static PlayQuoteFragment NewInstance(int playId)


{
var bundle = new Bundle();
bundle.PutInt("current_play_id", playId);
return new PlayQuoteFragment {Arguments = bundle};
}

public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)


{
if (container == null)
{
return null;
}

var textView = new TextView(Activity);


var padding = Convert.ToInt32(TypedValue.ApplyDimension(ComplexUnitType.Dip, 4,
Activity.Resources.DisplayMetrics));
textView.SetPadding(padding, padding, padding, padding);
textView.TextSize = 24;
textView.Text = Shakespeare.Dialogue[PlayId];

var scroller = new ScrollView(Activity);


scroller.AddView(textView);

return scroller;
}
}

Se trata de un patrón común en las aplicaciones de Android para proporcionar una Factory Method que creará
una instancia de un fragmento. Esto garantiza que el fragmento se creará con los parámetros necesarios para
funcionar correctamente. En este tutorial, se espera que la aplicación use el PlayQuoteFragment.NewInstance
método para crear un nuevo fragmento cada vez que se selecciona una comilla. El NewInstance método tomará
un parámetro – único el índice de la oferta que se va a mostrar.
Android OnCreateView invocará el método cuando sea el momento de presentar el fragmento en la pantalla.
Devolverá un objeto View Android que es el fragmento. Este fragmento no utiliza un archivo de diseño para crear
una vista. En su lugar, creará la vista mediante programación creando una instancia de TextView para contener la
comilla y mostrará el widget en un ScrollView.

NOTE
Las subclases de fragmento deben tener un constructor público predeterminado que no tenga ningún parámetro.

4. Crear PlayQuoteActivity
Los fragmentos se deben hospedar dentro de una actividad, por lo que esta aplicación requiere una
PlayQuoteFragment actividad que hospede el. La actividad agregará dinámicamente el fragmento a su diseño en
tiempo de ejecución. Agregue una nueva actividad a la aplicación y asígnele el PlayQuoteActivity nombre:
Visual Studio
Visual Studio para Mac
Edite el código PlayQuoteActivity en:

[Activity(Label = "PlayQuoteActivity")]
public class PlayQuoteActivity : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);

var playId = Intent.Extras.GetInt("current_play_id", 0);

var detailsFrag = PlayQuoteFragment.NewInstance(playId);


FragmentManager.BeginTransaction()
.Add(Android.Resource.Id.Content, detailsFrag)
.Commit();
}
}

Cuando PlayQuoteActivity se crea, crea una instancia de un nuevo PlayQuoteFragment y carga ese fragmento en
su vista raíz en el contexto de un FragmentTransaction . Tenga en cuenta que esta actividad no carga un archivo de
diseño de Android para su interfaz de usuario. En su lugar, se PlayQuoteFragment agrega un nuevo a la vista raíz
de la aplicación. El identificador Android.Resource.Id.Content de recursos se usa para hacer referencia a la vista
raíz de una actividad sin conocer su identificador específico.

5. Crear TitlesFragment
La TitlesFragment subclase creará un fragmento especializado conocido ListFragment como que encapsula la
lógica para mostrar un ListView en un fragmento. ListView OnListItemClick Expone una ListAdapter
propiedad( utilizada por
paramostrarsucontenido)yuncontroladordeeventosdenominadoquepermitealfragmentoresponderalosclicsenunafi
laquemuestra. ListView ListFragment
Para empezar, agregue un nuevo fragmento al proyecto y asígnele el nombre TitlesFragment:
Visual Studio
Visual Studio para Mac
Edite el código dentro del fragmento:

public class TitlesFragment : ListFragment


{
int selectedPlayId;

public TitlesFragment()
{
// Being explicit about the requirement for a default constructor.
}

public override void OnActivityCreated(Bundle savedInstanceState)


{
base.OnActivityCreated(savedInstanceState);
ListAdapter = new ArrayAdapter<String>(Activity, Android.Resource.Layout.SimpleListItemActivated1,
Shakespeare.Titles);

if (savedInstanceState != null)
{
selectedPlayId = savedInstanceState.GetInt("current_play_id", 0);
}
}

public override void OnSaveInstanceState(Bundle outState)


{
base.OnSaveInstanceState(outState);
outState.PutInt("current_play_id", selectedPlayId);
}

public override void OnListItemClick(ListView l, View v, int position, long id)


{
ShowPlayQuote(position);
}

void ShowPlayQuote(int playId)


{
var intent = new Intent(Activity, typeof(PlayQuoteActivity));
intent.PutExtra("current_play_id", playId);
StartActivity(intent);
}
}

Cuando se crea la actividad, Android invocará OnActivityCreated el método del fragmento; aquí es donde
ListView se crea el adaptador de lista para. El ShowQuoteFromPlay método iniciará una instancia
PlayQuoteActivity de para mostrar las comillas para la reproducción seleccionada.

Mostrar TitlesFragment en MainActivity


El paso final consiste en TitlesFragment mostrarse MainActivity dentro de. La actividad no carga dinámicamente
el fragmento. En su lugar, el fragmento se cargará estáticamente declarándolo en el archivo de diseño de la
actividad mediante un fragment elemento. El fragmento que se va a cargar se identifica android:name
estableciendo el atributo en la clase Fragment (incluido el espacio de nombres del tipo). Por ejemplo, para utilizar
TitlesFragment android:name , se establecerá en FragmentSample.TitlesFragment .

Edite el archivo de diseño activity_main. axml, reemplazando el XML existente por lo siguiente:

<?xml version="1.0" encoding="utf-8"?>


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:name="FragmentSample.TitlesFragment"
android:id="@+id/titles"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>

NOTE
El class atributo es un sustituto válido para android:name . No hay ninguna orientación formal sobre qué formulario se
prefiere, existen muchos ejemplos de bases de código que se class usarán indistintamente con. android:name

No se requieren cambios de código para MainActivity. El código de esa clase debe ser muy similar a este
fragmento de código:

[Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)]


public class MainActivity : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.activity_main);
}
}

Ejecución de la aplicación
Ahora que el código está completo, ejecute la aplicación en un dispositivo para verlo en acción.
La parte 2 de este tutorial optimtize esta aplicación para los dispositivos que se ejecutan en modo horizontal.
Tutorial de fragmentos – horizontal
11/07/2019 • 9 minutes to read • Edit Online

El fragmentos tutorial – parte 1 se ha mostrado cómo crear y usar los fragmentos en una aplicación de Android
que tenga como destino las pantallas más pequeñas en un teléfono. El siguiente paso en este tutorial es para
modificar la aplicación para aprovechar el espacio horizontal adicional en Tablet PC – habrá una actividad que
siempre será la lista de objetivos (el TitlesFragment ) y PlayQuoteFragment se agregarán dinámicamente a la
actividad en respuesta a una selección realizada por el usuario:

Los teléfonos que se ejecutan en modo horizontal también se beneficiarán de esta mejora:

Actualización de la aplicación para controlar la orientación horizontal


Las siguientes modificaciones se basan en el trabajo realizado en el fragmentos Walkthrough - teléfono
1. Crear un diseño alternativo para mostrar tanto el TitlesFragment y PlayQuoteFragment .
2. Actualización TitlesFragment para detectar si el dispositivo muestra ambos fragmentos simultáneamente y
cambiar el comportamiento en consecuencia.
3. Actualización PlayQuoteActivity cerrar cuando el dispositivo está en modo horizontal.

1. Crear un diseño alternativo


Cuando se crea la actividad principal en un dispositivo Android, Android decidirá qué diseño se carga según la
orientación del dispositivo. De forma predeterminada, Android proporcionará la
Resources/layout/activity_main.axml archivo de diseño. Para los dispositivos que se cargan en modo
horizontal Android proporcionará la Resources/layout-land/activity_main.axml archivo de diseño. La guía
sobre recursos de Android contiene más detalles sobre cómo Android decide qué recurso de archivos para cargar
para una aplicación.
Crear un diseño alternativo que tenga como destino horizontal orientación siguiendo los pasos descritos en la
diseños alternativos guía. Esto debe agregar un nuevo archivo de recursos de diseño para el proyecto,
Resources/layout/activity_main.axml:
Visual Studio
Visual Studio para Mac

Después de crear el diseño alternativo, modifique el origen del archivo Resources/layout-


land/activity_main.axml para que coincida con este código XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/two_fragments_layout"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">

<fragment android:name="FragmentSample.TitlesFragment"
android:id="@+id/titles"
android:layout_weight="1"
android:layout_width="0px"
android:layout_height="match_parent" />

<FrameLayout android:id="@+id/playquote_container"
android:layout_weight="1"
android:layout_width="0px"
android:layout_height="match_parent"
/>
</LinearLayout>

La vista de la raíz de la actividad tiene el identificador de recurso two_fragments_layout y tiene dos vistas
secundarias, un fragment y un FrameLayout . Mientras el fragment es cargados estáticamente el FrameLayout
actúa como un "marcador de posición" que se reemplazará en tiempo de ejecución por el PlayQuoteFragment .
Cada vez que se selecciona un juego nuevo en el TitlesFragment , playquote_container se actualizará con una
nueva instancia de la PlayQuoteFragment .
Cada una de las vistas secundarias ocupará todo el alto de su elemento primario. El ancho de cada vista
secundaria se controla mediante el android:layout_weight y android:layout_width atributos. En este ejemplo,
cada vista secundaria ocupará el 50% del ancho de proporcionar por el elemento primario. Consulte documentos
de Google en el LinearLayout para obtener más información acerca de peso diseño.

2. Cambios realizados en TitlesFragment


Una vez creado el diseño alternativo, es necesario actualizar TitlesFragment . Cuando la aplicación muestra a
continuación, los dos fragmentos en una actividad, TitlesFragment debe cargar el PlayQuoteFragment en la
actividad primaria. En caso contrario, TitlesFragment debe iniciar el PlayQuoteActivity qué host la
PlayQuoteFragment . Una marca booleana que le ayudarán a TitlesFragment determinar el comportamiento que
debe usar. Esta marca se inicializarán en el OnActivityCreated método.
En primer lugar, agregue una variable de instancia en la parte superior de la TitlesFragment clase:

bool showingTwoFragments;

A continuación, agregue el siguiente fragmento de código para OnActivityCreated para inicializar la variable:

var quoteContainer = Activity.FindViewById(Resource.Id.playquote_container);


showingTwoFragments = quoteContainer != null &&
quoteContainer.Visibility == ViewStates.Visible;
if (showingTwoFragments)
{
ListView.ChoiceMode = ChoiceMode.Single;
ShowPlayQuote(selectedPlayId);
}

Si el dispositivo se está ejecutando en modo horizontal, el FrameLayout con el identificador de recurso


playquote_container estará visible en la pantalla, por lo que showingTwoFragments se inicializarán en true . Si el
dispositivo se está ejecutando en modo vertical, a continuación, playquote_container no estará en la pantalla, por
lo que showingTwoFragments será false .
El ShowPlayQuote método será necesario cambiar cómo se muestra una oferta – en un fragmento o iniciar una
nueva actividad. Actualización de la ShowPlayQuote método para cargar un fragmento cuando se muestran dos
fragmentos, de lo contrario debe iniciar una actividad:

void ShowPlayQuote(int playId)


{
selectedPlayId = playId;
if (showingTwoFragments)
{
ListView.SetItemChecked(selectedPlayId, true);

var playQuoteFragment = FragmentManager.FindFragmentById(Resource.Id.playquote_container) as


PlayQuoteFragment;

if (playQuoteFragment == null || playQuoteFragment.PlayId != playId)


{
var container = Activity.FindViewById(Resource.Id.playquote_container);
var quoteFrag = PlayQuoteFragment.NewInstance(selectedPlayId);

FragmentTransaction ft = FragmentManager.BeginTransaction();
ft.Replace(Resource.Id.playquote_container, quoteFrag);
ft.Commit();
}
}
else
{
var intent = new Intent(Activity, typeof(PlayQuoteActivity));
intent.PutExtra("current_play_id", playId);
StartActivity(intent);
}
}

Si el usuario ha seleccionado un juego en el que es diferente del que se muestra actualmente en


PlayQuoteFragment , a continuación, un nuevo PlayQuoteFragment se crea y se reemplazará el contenido de la
playquote_container dentro del contexto de un FragmentTransaction .

Código completo de TitlesFragment


Después de completar todos los cambios anteriores a TitlesFragment , la clase completa debe coincidir con este
código:

public class TitlesFragment : ListFragment


{
int selectedPlayId;
bool showingTwoFragments;

public override void OnActivityCreated(Bundle savedInstanceState)


{
base.OnActivityCreated(savedInstanceState);
ListAdapter = new ArrayAdapter<string>(Activity, Android.Resource.Layout.SimpleListItemActivated1,
Shakespeare.Titles);

if (savedInstanceState != null)
{
selectedPlayId = savedInstanceState.GetInt("current_play_id", 0);
}

var quoteContainer = Activity.FindViewById(Resource.Id.playquote_container);


showingTwoFragments = quoteContainer != null &&
showingTwoFragments = quoteContainer != null &&
quoteContainer.Visibility == ViewStates.Visible;
if (showingTwoFragments)
{
ListView.ChoiceMode = ChoiceMode.Single;
ShowPlayQuote(selectedPlayId);
}
}

public override void OnSaveInstanceState(Bundle outState)


{
base.OnSaveInstanceState(outState);
outState.PutInt("current_play_id", selectedPlayId);
}

public override void OnListItemClick(ListView l, View v, int position, long id)


{
ShowPlayQuote(position);
}

void ShowPlayQuote(int playId)


{
selectedPlayId = playId;
if (showingTwoFragments)
{
ListView.SetItemChecked(selectedPlayId, true);

var playQuoteFragment = FragmentManager.FindFragmentById(Resource.Id.playquote_container) as


PlayQuoteFragment;

if (playQuoteFragment == null || playQuoteFragment.PlayId != playId)


{
var container = Activity.FindViewById(Resource.Id.playquote_container);
var quoteFrag = PlayQuoteFragment.NewInstance(selectedPlayId);

FragmentTransaction ft = FragmentManager.BeginTransaction();
ft.Replace(Resource.Id.playquote_container, quoteFrag);
ft.AddToBackStack(null);
ft.SetTransition(FragmentTransit.FragmentFade);
ft.Commit();
}
}
else
{
var intent = new Intent(Activity, typeof(PlayQuoteActivity));
intent.PutExtra("current_play_id", playId);
StartActivity(intent);
}
}
}

3. Cambios realizados en PlayQuoteActivity


Hay un detalle final que se encargue de: PlayQuoteActivity no es necesario cuando el dispositivo está en modo
horizontal. Si el dispositivo está en modo horizontal el PlayQuoteActivity no debería estar visible. Actualización
de la OnCreate método de PlayQuoteActivity para que se va a cerrar propio. Este código es la versión final de
PlayQuoteActivity.OnCreate :
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);

if (Resources.Configuration.Orientation == Android.Content.Res.Orientation.Landscape)
{
Finish();
}

var playId = Intent.Extras.GetInt("current_play_id", 0);


var playQuoteFrag = PlayQuoteFragment.NewInstance(playId);
FragmentManager.BeginTransaction()
.Add(Android.Resource.Id.Content, playQuoteFrag)
.Commit();
}

Esta modificación agrega una comprobación para la orientación del dispositivo. Si está en modo horizontal, a
continuación, PlayQuoteActivity cerrará a sí mismo.

4. Ejecutar la aplicación
Una vez que estos cambios están completos, ejecute la aplicación, girar el dispositivo para el modo (si es
necesario) horizontal y, a continuación, seleccione un objetivo. La oferta debe mostrarse en la misma pantalla de la
lista de objetivos:
Crear un fragmento
16/08/2019 • 19 minutes to read • Edit Online

Para crear un fragmento, una clase debe heredar Android.App.Fragment de y, a OnCreateView continuación,
reemplazar el método. OnCreateView la actividad de hospedaje lo llamará cuando sea el momento de poner el
fragmento en la pantalla y devolverá un View . Un típico OnCreateView creará esto View al inflar un archivo de
diseño y, a continuación, adjuntarlo a un contenedor primario. Las características del contenedor son importantes,
ya que Android aplicará los parámetros de diseño del elemento primario a la interfaz de usuario del fragmento.
Esto se ilustra en el siguiente ejemplo:

public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)


{
return inflater.Inflate(Resource.Layout.Example_Fragment, container, false);
}

El código anterior impondrá la vista Resource.Layout.Example_Fragment y la agregará como una vista secundaria
ViewGroup al contenedor.

NOTE
Las subclases de fragmento deben tener un constructor público predeterminado sin argumentos.

Agregar un fragmento a una actividad


Hay dos maneras de hospedar un fragmento dentro de una actividad:
Mediante declaración Los fragmentos se pueden usar mediante declaración .axml en los archivos de
diseño <Fragment> mediante la etiqueta. –
Mediante programación También se pueden crear instancias de los fragmentos dinámicamente mediante
FragmentManager la API de la clase. –

El uso mediante programación FragmentManager a través de la clase se explicará más adelante en esta guía.
Usar un fragmento mediante declaración
Agregar un fragmento dentro del diseño requiere el uso <fragment> de la etiqueta y, a continuación, la
identificación class del fragmento proporcionando android:name el atributo o el atributo. En el fragmento de
código siguiente se muestra class cómo usar el atributo fragment para declarar un:

<?xml version="1.0" encoding="utf-8"?>


<fragment class="com.xamarin.sample.fragments.TitlesFragment"
android:id="@+id/titles_fragment"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />

En el siguiente fragmento de código se muestra fragment cómo declarar un android:name mediante el atributo
para identificar la clase Fragment:
<?xml version="1.0" encoding="utf-8"?>
<fragment android:name="com.xamarin.sample.fragments.TitlesFragment"
android:id="@+id/titles_fragment"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />

Cuando se crea la actividad, Android creará una instancia de cada fragmento especificado en el archivo de diseño e
insertará la vista que OnCreateView se crea a partir Fragment de en lugar del elemento. Los fragmentos que se
agregan mediante declaración a una actividad son estáticos y permanecerán en la actividad hasta que se destruyan.
no es posible reemplazar o quitar dinámicamente este fragmento durante la duración de la actividad a la que está
adjuntado.
Cada fragmento debe tener asignado un identificador único:
Android: ID. – Como con otros elementos de la interfaz de usuario de un archivo de diseño, se trata de un
identificador único.
Android: etiqueta – Este atributo es una cadena única.
Si no se usa ninguno de los dos métodos anteriores, el fragmento asumirá el identificador de la vista del
contenedor. En el siguiente ejemplo en el android:id que android:tag no se proporciona ni, Android asignará
fragment_container el identificador al fragmento:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="+@id/fragment_container"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">

<fragment class="com.example.android.apis.app.TitlesFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>

Caso de nombre del paquete


Android no permite caracteres en mayúsculas en los nombres de paquete; se producirá una excepción al intentar
aumentar la vista si un nombre de paquete contiene un carácter en mayúsculas. Sin embargo, Xamarin. Android es
más permisivo y tolerará caracteres en mayúsculas en el espacio de nombres.
Por ejemplo, los dos fragmentos de código siguientes funcionarán con Xamarin. Android. Sin embargo, el segundo
fragmento de código android.view.InflateException hará que una aplicación Android basada en Java pura genere
una.

<fragment class="com.example.DetailsFragment" android:id="@+id/fragment_content"


android:layout_width="match_parent" android:layout_height="match_parent" />

OR

<fragment class="Com.Example.DetailsFragment" android:id="@+id/fragment_content"


android:layout_width="match_parent" android:layout_height="match_parent" />

Ciclo de vida de fragmentos


Los fragmentos tienen su propio ciclo de vida que es en cierto modo independiente del ciclo de vida de la actividad
de hospedaje, pero que todavía se ve afectado por él. Por ejemplo, cuando una actividad se pausa, todos sus
fragmentos asociados están en pausa. En el diagrama siguiente se describe el ciclo de vida del fragmento.

Métodos de ciclo de vida de creación de fragmentos


La lista siguiente muestra el flujo de las distintas devoluciones de llamada en el ciclo de vida de un fragmento
mientras se crea:
OnInflate() – Se llama cuando el fragmento se crea como parte de un diseño de vista. Se puede llamar a
este método inmediatamente después de que el fragmento se cree mediante declaración a partir de un
archivo de diseño XML. El fragmento no está asociado todavía a su actividad, pero la actividad, el Grupoy
el objeto AttributeSet de la jerarquía de vistas se pasan como parámetros. Este método se utiliza mejor
para analizar el AttributeSet y para guardar los atributos que se podrían usar posteriormente en el
fragmento.
OnAttach() – Se llama después de que el fragmento esté asociado a la actividad. Este es el primer método
que se va a ejecutar cuando el fragmento esté listo para usarse. En general, los fragmentos no deben
implementar un constructor ni reemplazar el constructor predeterminado. Los componentes necesarios para
el fragmento se deben inicializar en este método.
OnCreate() – Lo llama la actividad para crear el fragmento. Cuando se llama a este método, es posible que
no se pueda crear una instancia completa de la jerarquía de vista de la actividad de hospedaje, por lo que el
fragmento no debe basarse en ninguna parte de la jerarquía de vistas de la actividad hasta más adelante en
el ciclo de vida del fragmento. Por ejemplo, no utilice este método para realizar ajustes o ajustes en la
interfaz de usuario de la aplicación. Esta es la primera vez que el fragmento puede comenzar a recopilar los
datos que necesita. En este momento, el fragmento se está ejecutando en el subproceso de la interfaz de
usuario, por lo que debe evitar un procesamiento largo o realizar ese procesamiento en un subproceso en
segundo plano. Este método se puede omitir si se llama a SetRetainInstance (true) . Esta alternativa se
describe con más detalle a continuación.
OnCreateView() – Crea la vista para el fragmento. Se llama a este método una vez que se completa el
método alcrear () de la actividad. En este momento, es seguro interactuar con la jerarquía de vistas de la
actividad. Este método debe devolver la vista que va a utilizar el fragmento.
OnActivityCreated() Se llama después de que la actividad de hospedaje haya completado la actividad. he
creado. – Los ajustes finales en la interfaz de usuario deben realizarse en este momento.
OnStart() – Se llama después de que se reanude la actividad contenedora. Esto hace que el fragmento sea
visible para el usuario. En muchos casos, el fragmento contendrá código que, de lo contrario, se encontraría
en el método OnStart () de una actividad.
OnResume() – Este es el último método llamado antes de que el usuario pueda interactuar con el fragmento.
Un ejemplo del tipo de código que se debe realizar en este método sería habilitar las características de un
dispositivo con el que el usuario puede interactuar, como la cámara que los servicios de ubicación. Sin
embargo, los servicios como estos pueden provocar un consumo excesivo de la batería, y una aplicación
debe minimizar su uso para conservar la duración de la batería.
Métodos de ciclo de vida de destrucción de fragmentos
En la lista siguiente se explican los métodos de ciclo de vida a los que se llama como un fragmento que se está
destruyendo:
OnPause() – El usuario ya no puede interactuar con el fragmento. Esta situación existe porque alguna otra
operación de fragmento está modificando este fragmento o la actividad de hospedaje está en pausa. Es
posible que la actividad que hospeda este fragmento todavía esté visible, es decir, que la actividad en el foco
sea parcialmente transparente o no ocupe toda la pantalla. Cuando este método se activa, es la primera
indicación de que el usuario abandona el fragmento. El fragmento debe guardar los cambios.
OnStop() – El fragmento ya no está visible. Es posible que se detenga la actividad del host o que una
operación de fragmento la esté modificando en la actividad. Esta devolución de llamada sirve para el mismo
propósito que Activity. OnStop.
– Se llama a este método para limpiar los recursos asociados a la vista. Se llama a este
OnDestroyView()
método cuando se ha destruido la vista asociada al fragmento.
OnDestroy() – Se llama a este método cuando el fragmento ya no está en uso. Todavía está asociado a la
actividad, pero el fragmento ya no funciona. Este método debe liberar cualquier recurso que esté usando el
fragmento, como un SurfaceView que se pueda usar para una cámara. Este método se puede omitir si se
llama a SetRetainInstance (true) . Esta alternativa se describe con más detalle a continuación.
OnDetach() – Se llama a este método justo antes de que el fragmento deje de estar asociado a la actividad.
La jerarquía de vistas del fragmento ya no existe y todos los recursos utilizados por el fragmento deben
liberarse en este momento.
Usar SetRetainInstance
Es posible que un fragmento especifique que no se debe destruir completamente si se vuelve a crear la actividad.
La Fragment clase proporciona el método SetRetainInstance para este fin. Si true se pasa a este método, cuando
se reinicie la actividad, se usará la misma instancia del fragmento. Si esto ocurre, todos los métodos de devolución
de llamada se invocarán OnCreate excepto OnDestroy las devoluciones de llamada y del ciclo de vida. Este proceso
se ilustra en el diagrama del ciclo de vida mostrado anteriormente (por las líneas de puntos verdes).

Administración de estado de fragmentos


Los fragmentos pueden guardar y restaurar su estado durante el ciclo de vida de los fragmentos mediante Bundle
el uso de una instancia de. La agrupación permite que un fragmento guarde los datos como pares clave-valor y
resulta útil para datos simples que no requieren mucha memoria. Un fragmento puede guardar su estado con una
llamada a OnSaveInstanceState :

public override void OnSaveInstanceState(Bundle outState)


{
base.OnSaveInstanceState(outState);
outState.PutInt("current_choice", _currentCheckPosition);
}

Cuando se crea una nueva instancia de un fragmento, el estado guardado en el Bundle estará disponible para la
nueva instancia a través de OnCreate los OnCreateView métodos, OnActivityCreated y de la nueva instancia. En el
ejemplo siguiente se muestra cómo recuperar el current_choice valor Bundle de:

public override void OnActivityCreated(Bundle savedInstanceState)


{
base.OnActivityCreated(savedInstanceState);
if (savedInstanceState != null)
{
_currentCheckPosition = savedInstanceState.GetInt("current_choice", 0);
}
}

Reemplazar OnSaveInstanceState es un mecanismo adecuado para guardar datos transitorios en un fragmento a


través de cambios de orientación, current_choice como el valor del ejemplo anterior. Sin embargo, la
implementación predeterminada OnSaveInstanceState de se encarga de guardar los datos transitorios en la interfaz
de usuario para cada vista que tenga un identificador asignado. Por ejemplo, examine una aplicación que tenga un
EditText elemento definido en XML como se indica a continuación:

<EditText android:id="@+id/myText"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>

Puesto que EditText el control tiene id un asignado, el fragmento guarda automáticamente los datos en el
widget OnSaveInstanceState cuando se llama a.
Limitaciones de agrupación
Aunque el OnSaveInstanceState uso de facilita el almacenamiento de datos transitorios, el uso de este método tiene
algunas limitaciones:
Si el fragmento no se agrega a la pila de retroceso, su estado no se restaurará cuando el usuario presione el
botón atrás .
Cuando se utiliza la agrupación para guardar los datos, se serializan. Esto puede dar lugar a retrasos en el
procesamiento.

Contribución al menú
Los fragmentos pueden contribuir con elementos al menú de su actividad de hospedaje. Una actividad trata
primero los elementos de menú. Si la actividad no tiene un controlador, el evento se pasará al fragmento, que lo
controlará.
Para agregar elementos al menú de la actividad, un fragmento debe hacer dos cosas. En primer lugar, el fragmento
debe implementar OnCreateOptionsMenu el método y colocar sus elementos en el menú, tal y como se muestra en el
código siguiente:

public override void OnCreateOptionsMenu(IMenu menu, MenuInflater menuInflater)


{
menuInflater.Inflate(Resource.Menu.menu_fragment_vehicle_list, menu);
base.OnCreateOptionsMenu(menu, menuInflater);
}

El menú del fragmento de código anterior se infla a partir del siguiente XML, ubicado en el archivo
menu_fragment_vehicle_list.xml :

<?xml version="1.0" encoding="utf-8"?>


<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/add_vehicle"
android:icon="@drawable/ic_menu_add_data"
android:title="@string/add_vehicle" />
</menu>

A continuación, el fragmento debe SetHasOptionsMenu(true) llamar a. La llamada a este método anuncia a Android
que el fragmento tiene elementos de menú para contribuir al menú de opciones. A menos que se realice la llamada
a este método, no se agregarán los elementos de menú para el fragmento al menú de opciones de la actividad. Esto
se hace normalmente en el método OnCreate() de ciclo de vida, tal y como se muestra en el siguiente fragmento de
código:

public override void OnCreate(Bundle savedState)


{
base.OnCreate(savedState);
SetHasOptionsMenu(true);
}

En la pantalla siguiente se muestra el aspecto de este menú:


Administración de fragmentos
16/08/2019 • 5 minutes to read • Edit Online

Para ayudar con la administración de fragmentos, Android FragmentManager proporciona la clase. Cada actividad
tiene una instancia de Android.App.FragmentManager que buscará o cambiará dinámicamente sus fragmentos. Cada
conjunto de estos cambios se conoce como una transaccióny se realiza mediante una de las API contenidas en la
clase Android.App.FragmentTransation , que FragmentManager está administrada por. Una actividad puede iniciar una
transacción como esta:

FragmentTransaction fragmentTx = this.FragmentManager.BeginTransaction();

Estos cambios en los fragmentos se realizan en la FragmentTransaction instancia de mediante métodos Add()
como Remove(), Commit() y Replace(). , a continuación, los cambios se aplican mediante. Los cambios en una
transacción no se realizan inmediatamente. En su lugar, están programados para ejecutarse en el subproceso de
interfaz de usuario de la actividad lo antes posible.
En el ejemplo siguiente se muestra cómo agregar un fragmento a un contenedor existente:

// Create a new fragment and a transaction.


FragmentTransaction fragmentTx = this.FragmentManager.BeginTransaction();
DetailsFragment aDifferentDetailsFrag = new DetailsFragment();

// The fragment will have the ID of Resource.Id.fragment_container.


fragmentTx.Add(Resource.Id.fragment_container, aDifferentDetailsFrag);

// Commit the transaction.


fragmentTx.Commit();

Si una transacción se confirma después Activity.OnSaveInstanceState() de que se llame a, se producirá una


excepción. Esto sucede porque cuando la actividad guarda su estado, Android también guarda el estado de los
fragmentos hospedados. Si se confirman las transacciones de fragmentos después de este punto, el estado de
estas transacciones se perderá cuando se restaure la actividad.
Es posible guardar las transacciones de fragmentos en la pila de retroceso de la actividad realizando una llamada a
FragmentTransaction.AddToBackStack() . Esto permite al usuario navegar hacia atrás a través de los cambios de
fragmento cuando se presiona el botón atrás . Sin una llamada a este método, los fragmentos que se quitan se
destruirán y dejarán de estar disponibles si el usuario retrocede a través de la actividad.
En el ejemplo siguiente se muestra cómo utilizar AddToBackStack el método de para reemplazar un fragmento, a la
vez que se conserva el estado del primer fragmento en la pila de retroceso: FragmentTransaction
// Create a new fragment and a transaction.
FragmentTransaction fragmentTx = this.FragmentManager.BeginTransaction();
DetailsFragment aDifferentDetailsFrag = new DetailsFragment();

// Replace the fragment that is in the View fragment_container (if applicable).


fragmentTx.Replace(Resource.Id.fragment_container, aDifferentDetailsFrag);

// Add the transaction to the back stack.


fragmentTx.AddToBackStack(null);

// Commit the transaction.


fragmentTx.Commit();

Comunicación con fragmentos


FragmentManager conoce todos los fragmentos que están asociados a una actividad y proporciona dos métodos
para ayudarle a encontrar estos fragmentos:
FindFragmentById – Este método encontrará un fragmento mediante el identificador que se especificó en
el archivo de diseño o el identificador del contenedor cuando el fragmento se agregó como parte de una
transacción.
FindFragmentByTag – Este método se usa para buscar un fragmento que tenga una etiqueta que se
proporcionó en el archivo de diseño o que se agregó en una transacción.
Los fragmentos y las actividades hacen FragmentManager referencia a, por lo que se usan las mismas técnicas para
comunicarse entre ellos. Una aplicación puede encontrar un fragmento de referencia mediante uno de estos dos
métodos, convertir esa referencia al tipo adecuado y, a continuación, llamar directamente a los métodos del
fragmento. El siguiente fragmento de código proporciona un ejemplo:
También es posible que la actividad use FragmentManager para encontrar fragmentos:

var emailList = FragmentManager.FindFragmentById<EmailListFragment>(Resource.Id.email_list_fragment);


emailList.SomeCustomMethod(parameter1, parameter2);

Comunicación con la actividad


Es posible que un fragmento use la Fragment.Activity propiedad para hacer referencia a su host. Al convertir la
actividad en un tipo más específico, es posible que una actividad llame a métodos y propiedades en su host, tal y
como se muestra en el ejemplo siguiente:

var myActivity = (MyActivity) this.Activity;


myActivity.SomeCustomMethod();
Clases de fragmentos especializadas
16/08/2019 • 11 minutes to read • Edit Online

La API de fragmentos proporciona otras subclases que encapsulan algunas de las funciones más comunes que se
encuentran en las aplicaciones. Estas subclases son:
ListFragment – Este fragmento se usa para mostrar una lista de elementos enlazados a un origen de
objetos, como una matriz o un cursor.
DialogFragment – Este fragmento se utiliza como contenedor alrededor de un cuadro de diálogo. El
fragmento mostrará el cuadro de diálogo encima de su actividad.
PreferenceFragment – Este fragmento se usa para mostrar los objetos de preferencias como listas.

ListFragment
Es muy similar en concepto y funcionalidad ListActivity a; es un contenedor que hospeda un ListView en un
fragmento. ListFragment La imagen siguiente muestra un ListFragment que se ejecuta en una tableta y un
teléfono:

Enlazar datos con ListAdapter


La ListFragment clase ya proporciona un diseño predeterminado, por lo que no es necesario invalidar
OnCreateView para ListFragment mostrar el contenido de. Se ListView enlaza a los datos mediante una
ListAdapter implementación de. En el ejemplo siguiente se muestra cómo se puede hacer mediante una matriz
simple de cadenas:

public override void OnActivityCreated(Bundle savedInstanceState)


{
base.OnActivityCreated(savedInstanceState);
string[] values = new[] { "Android", "iPhone", "WindowsMobile",
"Blackberry", "WebOS", "Ubuntu", "Windows7", "Max OS X",
"Linux", "OS/2" };
this.ListAdapter = new ArrayAdapter<string>(Activity, Android.Resource.Layout.SimpleExpandableListItem1,
values);
}

Al establecer ListAdapter, es importante usar la ListFragment.ListAdapter propiedad, y no la


ListView.ListAdapter propiedad. El ListView.ListAdapter uso de hará que se omita el código de inicialización
importante.
Responder a la selección del usuario
Para responder a las selecciones de usuario, una aplicación debe OnListItemClick reemplazar el método. En el
ejemplo siguiente se muestra una de estas posibilidades:

public override void OnListItemClick(ListView l, View v, int index, long id)


{
// We can display everything in place with fragments.
// Have the list highlight this item and show the data.
ListView.SetItemChecked(index, true);

// Check what fragment is shown, replace if needed.


var details = FragmentManager.FindFragmentById<DetailsFragment>(Resource.Id.details);
if (details == null || details.ShownIndex != index)
{
// Make new fragment to show this selection.
details = DetailsFragment.NewInstance(index);

// Execute a transaction, replacing any existing


// fragment with this one inside the frame.
var ft = FragmentManager.BeginTransaction();
ft.Replace(Resource.Id.details, details);
ft.SetTransition(FragmentTransit.FragmentFade);
ft.Commit();
}
}

En el código anterior, cuando el usuario selecciona un elemento en el ListFragment , se muestra un nuevo


fragmento en la actividad de hospedaje, que muestra más detalles sobre el elemento seleccionado.

DialogFragment
DialogFragment es un fragmento que se usa para mostrar un objeto de cuadro de diálogo dentro de un fragmento
que flotará en la parte superior de la ventana de la actividad. Está pensado para reemplazar las API de diálogo
administradas (a partir de Android 3,0). En la captura de pantalla siguiente se muestra DialogFragment un ejemplo
de:
Un DialogFragment garantiza que el estado entre el fragmento y el cuadro de diálogo sigue siendo coherente.
Todas las interacciones y el control del objeto de cuadro de DialogFragment diálogo se deben producir a través de
la API y no se pueden realizar con llamadas directas en el objeto de cuadro de diálogo. La DialogFragment API
proporciona a cada instancia un Show() método que se utiliza para mostrar un fragmento. Hay dos maneras de
deshacerse de un fragmento:
Llame DialogFragment.Dismiss() a en DialogFragment la instancia de.
Mostrar otro DialogFragment .

Para crear DialogFragment , una clase hereda de Android.App.DialogFragment, y, a continuación, reemplaza uno de
los dos métodos siguientes:
OnCreateView – Esto crea y devuelve una vista.
OnCreateDialog – Esto crea un cuadro de diálogo personalizado. Normalmente se usa para mostrar un
AlertDialog. Al reemplazar este método, no es necesario invalidar OnCreateView .
Un DialogFragment simple
En la captura de pantalla siguiente DialogFragment se muestra un TextView simple que Button tiene un y dos s:
Mostrará el número de veces que el usuario hizo clic DialogFragment en un botón del, mientras que al hacer clic en
el otro botón, se cerrará el fragmento. TextView El código de DialogFragment es:

public class MyDialogFragment : DialogFragment


{
private int _clickCount;
public override void OnCreate(Bundle savedInstanceState)
{
_clickCount = 0;
}

public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)


{
base.OnCreate(savedInstanceState)

var view = inflater.Inflate(Resource.Layout.dialog_fragment_layout, container, false);


var textView = view.FindViewById<TextView>(Resource.Id.dialog_text_view);

view.FindViewById<Button>(Resource.Id.dialog_button).Click += delegate
{
textView.Text = "You clicked the button " + _clickCount++ + " times.";
};

// Set up a handler to dismiss this DialogFragment when this button is clicked.


view.FindViewById<Button>(Resource.Id.dismiss_dialog_button).Click += (sender, args) => Dismiss();
return view;
}
}
}

Mostrar un fragmento
Al igual que todos los DialogFragment fragmentos, se muestra en el contexto FragmentTransaction de un.
El Show() método en un DialogFragment toma FragmentTransaction y string como entrada. El cuadro de diálogo
se agregará a la actividad y FragmentTransaction se confirmará.
En el código siguiente se muestra una posible manera de que una Show() actividad pueda usar el DialogFragment
método para mostrar un:

public void ShowDialog()


{
var transaction = FragmentManager.BeginTransaction();
var dialogFragment = new MyDialogFragment();
dialogFragment.Show(transaction, "dialog_fragment");
}

Descartar un fragmento
La Dismiss() llamada a en una instancia DialogFragment de un provoca que se quite un fragmento de la actividad
y confirme esa transacción. Se llamará a los métodos de ciclo de vida de fragmento estándar que intervienen en la
destrucción de un fragmento.
Cuadro de diálogo de alerta
En lugar de reemplazar OnCreateView DialogFragment , en su lugar se puede invalidar OnCreateDialog . Esto
permite que una aplicación cree un AlertDialog administrado por un fragmento. El código siguiente es un ejemplo
que usa AlertDialog.Builder para crear un: Dialog
public class AlertDialogFragment : DialogFragment
{
public override Dialog OnCreateDialog(Bundle savedInstanceState)
{
EventHandler<DialogClickEventArgs> okhandler;
var builder = new AlertDialog.Builder(Activity)
.SetMessage("This is my dialog.")
.SetPositiveButton("Ok", (sender, args) =>
{
// Do something when this button is clicked.
})
.SetTitle("Custom Dialog");
return builder.Create();
}
}

PreferenceFragment
Para ayudar a administrar las preferencias, la API de PreferenceFragment fragmentos proporciona la subclase. Es
similar a PreferenceActivity – , que muestra una jerarquía de preferencias para el usuario en un fragmento.
PreferenceFragment A medida que el usuario interactúe con las preferencias, se guardarán automáticamente en
SharedPreferences. En aplicaciones Android 3,0 o versiones posteriores, use PreferenceFragment para tratar con
las preferencias de las aplicaciones. En la siguiente imagen se muestra un ejemplo PreferenceFragment de un:
Crear un fragmento de preferencias a partir de un recurso
El fragmento de preferencias se puede inflar a partir de un archivo de recursos XML mediante el método
PreferenceFragment. AddPreferencesFromResource . Un lugar lógico para llamar a este método en el ciclo de vida
del fragmento sería en OnCreate el método.
La PreferenceFragment imagen anterior se creó cargando un recurso desde XML. El archivo de recursos es:

<?xml version="1.0" encoding="utf-8"?>

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">

<PreferenceCategory android:title="Inline Preferences">


<CheckBoxPreference android:key="checkbox_preference"
android:title="Checkbox Preference Title"
android:summary="Checkbox Preference Summary" />

</PreferenceCategory>

<PreferenceCategory android:title="Dialog Based Preferences">

<EditTextPreference android:key="edittext_preference"
android:title="EditText Preference Title"
android:summary="EditText Preference Summary"
android:dialogTitle="Edit Text Preferrence Dialog Title" />

</PreferenceCategory>

<PreferenceCategory android:title="Launch Preferences">

<!-- This PreferenceScreen tag serves as a screen break (similar to page break
in word processing). Like for other preference types, we assign a key
here so it is able to save and restore its instance state. -->
<PreferenceScreen android:key="screen_preference"
android:title="Title Screen Preferences"
android:summary="Summary Screen Preferences">

<!-- You can place more preferences here that will be shown on the next screen. -->

<CheckBoxPreference android:key="next_screen_checkbox_preference"
android:title="Next Screen Toggle Preference Title"
android:summary="Next Screen Toggle Preference Summary" />

</PreferenceScreen>

<PreferenceScreen android:title="Intent Preference Title"


android:summary="Intent Preference Summary">

<intent android:action="android.intent.action.VIEW"
android:data="http://www.android.com" />

</PreferenceScreen>

</PreferenceCategory>

</PreferenceScreen>

El código para el fragmento de preferencias es el siguiente:


public class PrefFragment : PreferenceFragment
{
public override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
AddPreferencesFromResource(Resource.Xml.preferences);
}
}

Consultar actividades para crear un fragmento de preferencias


Otra técnica para crear un PreferenceFragment implica consultar las actividades. Cada actividad puede usar el
atributo de preferencia de clave__ de metadatos que apuntará a un archivo de recursos XML. En Xamarin. Android,
esto se hace mediante el uso de una etiqueta de MetaDataAttribute actividad con el y, a continuación, la
especificación del archivo de recursos que se va a usar. La PreferenceFragment clase proporciona el método
AddPreferenceFromIntent que se puede usar para consultar una actividad para encontrar este recurso XML y
aumentar una jerarquía de preferencias para él.
En el siguiente fragmento de código se proporciona un ejemplo de este proceso, que AddPreferencesFromIntent usa
para crear PreferenceFragment un:

public class MyPreferenceFragment : PreferenceFragment


{
public override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
var intent = new Intent(this.Activity, typeof (MyActivityWithPreferences));
AddPreferencesFromIntent(intent);
}
}

Android examinará la clase MyActivityWithPreference . La clase se debe adornar con MetaDataAttribute, como se
muestra en el siguiente fragmento de código:

[Activity(Label = "My Activity with Preferences")]


[MetaData(PreferenceManager.MetadataKeyPreferences, Resource = "@xml/preference_from_intent")]
public class MyActivityWithPreferences : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// This is deliberately blank
}
}

Declara un archivo de recursos XML PreferenceFragment que utilizará para inflar la jerarquía de preferencias.
MetaDataAttribute Si no MetatDataAttribute se proporciona, se producirá una excepción en tiempo de ejecución.
Cuando se ejecuta este código, PreferenceFragment aparece como en la siguiente captura de pantalla:
Proporcionar compatibilidad con versiones anteriores
del paquete de soporte de Android
16/08/2019 • 3 minutes to read • Edit Online

La utilidad de los fragmentos sería limitada sin compatibilidad con versiones anteriores a Android 3,0 (nivel de API
11). Para proporcionar esta funcionalidad, Google presentó la biblioteca de soporte (originalmente llamada
biblioteca de compatibilidad de Android cuando se lanzó), que transporta algunas de las API de versiones más
recientes de Android a versiones anteriores de Android. Es el paquete de soporte de Android que permite que los
dispositivos que ejecutan Android 1,6 (nivel de API 4) en Android 2.3.3. (Nivel de API 10).

NOTE
Solo los ListFragment DialogFragment y están disponibles a través del paquete de soporte de Android. Ninguna de las
otras subclases de fragmento, como PreferenceFragment, , se admiten en el paquete de soporte de Android. No
funcionarán en aplicaciones anteriores a Android 3,0.

Agregar el paquete de soporte


El paquete de soporte de Android no se agrega automáticamente a una aplicación de Xamarin. Android. Xamarin
proporciona el paquete NuGet de la biblioteca de compatibilidad de Android V4 para simplificar la adición de las
bibliotecas de soporte técnico a una aplicación de Xamarin. Android. Para incluir los paquetes de soporte en la
aplicación de Xamarin. Android, incluya el componente biblioteca de compatibilidad de Android V4 en el proyecto
de Xamarin. Android, como se muestra en la siguiente captura de pantalla:

Una vez realizados estos pasos, se pueden usar fragmentos en versiones anteriores de Android. Las API de
fragmentos funcionarán de la misma ahora en estas versiones anteriores, con las siguientes excepciones:
Cambiar la versión mínima de Android – La aplicación ya no necesita tener como destino Android 3,0 o
superior, como se muestra a continuación:
Extender FragmentActivity Las actividades que hospedan fragmentos deben heredar ahora
Android.Support.V4.App.FragmentActivity de y no de Android.App.Activity . –

Actualizar espacios de nombres Las clases que heredan de Android.App.Fragment deben heredar ahora
de Android.Support.V4.App.Fragment . – Quite la instrucción using " using Android.App; " en la parte superior
del archivo de código fuente y reemplácela por " using Android.Support.V4.App ".
Usar SupportFragmentManager expone una propiedad que se debe utilizar para obtener una referencia
a. FragmentManager – Android.Support.V4.App.FragmentActivity SupportingFragmentManager Por ejemplo:

FragmentTransaction fragmentTx = this.SupportingFragmentManager.BeginTransaction();


DetailsFragment detailsFrag = new DetailsFragment();
fragmentTx.Add(Resource.Id.fragment_container, detailsFrag);
fragmentTx.Commit();

Una vez realizados estos cambios, será posible ejecutar una aplicación basada en fragmentos en Android 1,6 o 2. x,
así como en Honeycomb y Sandwich de hielo.

Vínculos relacionados
NuGet de la biblioteca de compatibilidad de Android V4
Vinculación de aplicaciones en Android
16/08/2019 • 15 minutes to read • Edit Online

En esta guía se explica cómo Android 6,0 admite la vinculación de aplicaciones, una técnica que permite a las
aplicaciones móviles responder a las direcciones URL de los sitios Web. Se explica qué es la vinculación de
aplicaciones, cómo implementar la vinculación de aplicaciones en una aplicación Android 6,0 y cómo configurar
un sitio web para conceder permisos a la aplicación móvil para un dominio.

Información general de vinculación de aplicaciones


Las aplicaciones móviles ya no viven en un – silo en muchos casos son componentes importantes de sus negocios,
junto con su sitio Web. Es deseable que las empresas conecten sin problemas su presencia web y sus aplicaciones
móviles, con vínculos en un sitio web que inician aplicaciones móviles y muestran contenido relevante en la
aplicación móvil. Aplicación: vinculación (también conocido como vinculación profunda) es una técnica que
permite a un dispositivo móvil responder a un URI e iniciar una aplicación móvil que se corresponda con ese URI.
Android controla la vinculación de aplicaciones a través del sistema – de intención cuando el usuario hace clic en
un vínculo en un explorador móvil, el explorador móvil enviará un intento de que Android delegue a una aplicación
registrada. Por ejemplo, al hacer clic en un vínculo de un sitio web de cocina, se abriría una aplicación móvil que
está asociada a ese sitio web y se muestra una receta específica al usuario. Si hay más de una aplicación registrada
para controlar esa intención, Android generará lo que se conoce como un cuadro de diálogo de desambiguación
que le pedirá a un usuario la aplicación de la aplicación que debe administrar la intención, por ejemplo:

Android 6,0 mejora esto mediante el control automático de vínculos. Es posible que Android registre
automáticamente una aplicación como el controlador predeterminado para un URI – que la aplicación iniciará
automáticamente y navegará directamente a la actividad correspondiente. El modo en que Android 6,0 decide
controlar un URI haga clic en depende de los siguientes criterios:
1. Una aplicación existente ya está asociada con el URI – Es posible que el usuario ya haya asociado una
aplicación existente con un URI. En ese caso, Android seguirá usando esa aplicación.
2. No hay ninguna aplicación existente asociada al URI, pero se instala una aplicación auxiliar . – En este
escenario, el usuario no ha especificado una aplicación existente, por lo que Android usará la aplicación de
soporte instalada para controlar la solicitud.
3. No hay ninguna aplicación existente asociada al URI, pero hay muchas aplicaciones auxiliares
instaladas . – Dado que hay varias aplicaciones que admiten el URI, se mostrará el cuadro de diálogo de
anulación de ambigüedades y el usuario debe seleccionar qué aplicación controlará el URI.
Si el usuario no tiene ninguna aplicación instalada que admita el URI y otra se instala posteriormente, Android
establecerá esa aplicación como el controlador predeterminado para el URI después de comprobar la asociación
con el sitio web que está asociado con el URI.
En esta guía se explica cómo configurar una aplicación Android 6,0 y cómo crear y publicar el archivo de vínculos
de recursos digitales para admitir la vinculación de aplicaciones en Android 6,0.

Requisitos
En esta guía se requiere Xamarin. Android 6,1 y una aplicación destinada a Android 6,0 (nivel de API 23) o
superior.
La vinculación de aplicaciones es posible en versiones anteriores de Android mediante el paquete de NuGet
remaches del almacén de componentes de Xamarin. El paquete de remaches no es compatible con la vinculación
de aplicaciones en Android 6,0; no admite la vinculación de aplicaciones Android 6,0.

Configuración de la vinculación de aplicaciones en Android 6,0


La configuración de vínculos de aplicación en Android 6,0 implica dos pasos principales:
1. Agregar uno o varios filtros de intención para el URI del sitio web – la guía de filtros de intención de
Android en cómo administrar una dirección URL haga clic en un explorador móvil.
2. Publicación de un archivo JSON de vínculos de activos digitales en el sitio web – este es un archivo que
se carga en un sitio web y que se usa en Android para comprobar la relación entre la aplicación móvil y el
dominio del sitio Web. Sin esto, Android no puede instalar la aplicación como el identificador predeterminado
de los URI. el usuario debe hacerlo manualmente.
Configuración del filtro de intención
Es necesario configurar un filtro de intención que asigne un URI (o un conjunto de URI posible) de un sitio web a
una actividad en una aplicación Android. En Xamarin. Android, esta relación se establece mediante la etiquetación
de una actividad con el IntentFilterAttribute. El filtro de intención debe declarar la siguiente información:
Intent.ActionView – Se registrará el filtro de intención para responder a las solicitudes de visualización de la
información.
Categories El filtro de intención debe registrar ambos propósitos. CategoryBrowsable y intención.
CategoryDefault para poder administrar correctamente el URI Web. –
DataScheme El filtro de intención debe http declarar y/ https o. – Estos son los únicos dos esquemas válidos.
DataHost – Este es el dominio del que se originarán los URI.
DataPathPrefix – Se trata de una ruta de acceso opcional a los recursos del sitio Web.
AutoVerify – El autoVerify atributo indica a Android que Compruebe la relación entre la aplicación y el sitio
Web. Esto se tratará más adelante.
En el ejemplo siguiente se muestra cómo usar IntentFilterAttribute para controlar vínculos desde
https://www.recipe-app.com/recipes y hacia http://www.recipe-app.com/recipes :
[IntentFilter(new [] { Intent.ActionView },
Categories = new[] { Intent.CategoryBrowsable, Intent.CategoryDefault },
DataScheme = "http",
DataHost = "recipe-app.com",
DataPathPrefix = "/recipe",
AutoVerify=true)]
public class RecipeActivity : Activity
{
// Code for the activity omitted
}

Android comprobará todos los hosts identificados por los filtros de intención en el archivo de recursos digitales en
el sitio Web antes de registrar la aplicación como el controlador predeterminado para un URI. Todos los filtros de
intención deben pasar la comprobación antes de que Android pueda establecer la aplicación como el controlador
predeterminado.
Crear el archivo de vínculo de recursos digitales
La vinculación de aplicaciones Android 6,0 requiere que Android Compruebe la asociación entre la aplicación y el
sitio Web antes de establecer la aplicación como el controlador predeterminado para el URI. Esta comprobación se
realizará cuando se instale la aplicación por primera vez. El archivo de vínculos de recursos digitales es un archivo
JSON que se hospeda en los webdomains relevantes.

NOTE
El android:autoVerify filtro– de intención debe establecer el atributo; en caso contrario, Android no realizará la
comprobación.

El archivo lo coloca el webmaster del dominio en la ubicación https://domain/.well-known/assetlinks.json .


El archivo de recursos digitales contiene los metadatos necesarios para que Android Compruebe la asociación. Un
archivo assetlinks. JSON tiene los siguientes pares clave-valor:
namespace – espacio de nombres de la aplicación Android.
package_name – el nombre del paquete de la aplicación de Android (declarado en el manifiesto de aplicación).
sha256_cert_fingerprints – las huellas digitales SHA256 de la aplicación firmada. Consulte la guía de búsqueda
de la firma MD5 o SHA1 de su almacén de claves para obtener más información sobre cómo obtener la huella
digital SHA1 de una aplicación.
El siguiente fragmento de código es un ejemplo de assetlinks. JSON con una sola aplicación enumerada:

[
{
"relation":[
"delegate_permission/common.handle_all_urls"
],
"target":{
"namespace":"android_app",
"package_name":"com.example",
"sha256_cert_fingerprints":[
"14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"
]
}
}
]

Es posible registrar más de una huella digital SHA256 para admitir distintas versiones o compilaciones de la
aplicación. Este archivo assetlinks. JSON siguiente es un ejemplo de registro de varias aplicaciones:
[
{
"relation":[
"delegate_permission/common.handle_all_urls"
],
"target":{
"namespace":"android_app",
"package_name":"example.com.puppies.app",
"sha256_cert_fingerprints":[
"14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"
]
}
},
{
"relation":[
"delegate_permission/common.handle_all_urls"
],
"target":{
"namespace":"android_app",
"package_name":"example.com.monkeys.app",
"sha256_cert_fingerprints":[
"14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"
]
}
}
]

El sitio web de Google Digital Asset links tiene una herramienta en línea que puede ayudarle a crear y probar el
archivo de recursos digitales.
Probar la aplicación: vínculos
Después de implementar los vínculos de la aplicación, se deben probar las distintas partes para asegurarse de que
funcionan según lo previsto.
Es posible confirmar que el archivo de recursos digitales está formateado y hospedado correctamente mediante la
API de vínculos de activos digitales de Google, tal como se muestra en este ejemplo:

https://digitalassetlinks.googleapis.com/v1/statements:list?source.web.site=
https://<WEB SITE ADDRESS>:&relation=delegate_permission/common.handle_all_urls

Se pueden realizar dos pruebas para asegurarse de que los filtros de intención se han configurado correctamente y
de que la aplicación se establece como el controlador predeterminado para un URI:
1. El archivo de recursos digitales se hospeda correctamente como se describió anteriormente. La primera
prueba enviará un intento que Android debe redirigir a la aplicación móvil. La aplicación de Android debe
iniciar y mostrar la actividad registrada para la dirección URL. En un símbolo del sistema, escriba:

$ adb shell am start -a android.intent.action.VIEW \


-c android.intent.category.BROWSABLE \
-d "http://<domain1>/recipe/scalloped-potato"

2. Muestra las directivas de control de vínculos existentes para las aplicaciones instaladas en un dispositivo
determinado. El siguiente comando volcará una lista de directivas de vínculo para cada usuario en el
dispositivo con la siguiente información. En el símbolo del sistema, escriba el siguiente comando:

$ adb shell dumpsys package domain-preferred-apps

Package – Nombre del paquete de la aplicación.


Domain – Los dominios (separados por espacios) cuyos vínculos Web controlará la aplicación
Status – Este es el estado actual de control de vínculos de la aplicación. Un valor de siempre significa
que la aplicación ha android:autoVerify=true declarado y ha pasado la comprobación del sistema. Va
seguido de un número hexadecimal que representa el registro del sistema Android de la preferencia.
Por ejemplo:

$ adb shell dumpsys package domain-preferred-apps

App linkages for user 0:


Package: com.android.vending
Domains: play.google.com market.android.com
Status: always : 200000002

Resumen
En esta guía se describe cómo funciona la vinculación de aplicaciones en Android 6,0. A continuación, se explica
cómo configurar una aplicación Android 6,0 para admitir y responder a los vínculos de la aplicación. También se
describe cómo probar la vinculación de aplicaciones en una aplicación Android.

Vínculos relacionados
Buscar la firma MD5 o SHA1 de su almacén de claves
Actividades e intents
AppLinks
Vínculos a recursos digitales de Google
Generador y evaluador de la lista de instrucciones
Características de gráficos circulares de Android
19/08/2019 • 23 minutes to read • Edit Online

Cómo empezar a desarrollar aplicaciones para el gráfico circular de Android 9 con Xamarin. Android.
El gráfico circular de Android 9 ahora está disponible en Google. Una serie de nuevas características y API están
disponibles en esta versión, y muchas de ellas son necesarias para aprovechar las nuevas capacidades de hardware
de los dispositivos Android más recientes.

Este artículo está estructurado para ayudarle a empezar a desarrollar aplicaciones de Xamarin. Android para el
gráfico circular de Android. Explica cómo instalar las actualizaciones necesarias, configurar el SDK y preparar un
emulador o un dispositivo para realizar pruebas. También proporciona un esquema de las nuevas características de
los gráficos circulares de Android y proporciona código fuente de ejemplo que muestra cómo usar algunas de las
características clave de los sectores de Android.
Xamarin. Android 9,0 proporciona compatibilidad con el gráfico circular de Android. Para obtener más información
sobre la compatibilidad de Xamarin. Android con el gráfico circular de Android, consulte las notas de la versión de
Android P Developer Preview 3 .

Requisitos
La lista siguiente es necesaria para usar las características de gráficos circulares de Android en aplicaciones
basadas en Xamarin:
Visual Studio – Se recomienda Visual Studio 2019. Si usa Visual Studio 2017, en Windows Update a
Visual Studio 2017, versión 15,8 o posterior. En macOS, actualice a Visual Studio 2017 para Mac versión 7,6
o posterior.
Xamarin. Android – Xamarin. Android 9.0.0.17 o posterior debe instalarse con Visual Studio (Xamarin.
Android se instala automáticamente como parte de la carga de trabajo desarrollo para dispositivos
móviles con .net ).
Kit para desarrolladores de Java – El desarrollo de Xamarin Android 9.0 requiere JDK 8 (o puede probar
la versión preliminar de la distribución de Microsoft de OpenJDK). JDK8 se instala automáticamente como
parte de la carga de trabajo desarrollo para dispositivos móviles con .net .
Android SDK – Android SDK API 28 o posterior debe instalarse a través del administrador de Android
SDK.

Introducción
Para empezar a desarrollar aplicaciones de gráficos circulares de Android con Xamarin. Android, debe descargar e
instalar las herramientas y los paquetes de SDK más recientes antes de poder crear su primer proyecto de circular
de Android:
1. Se recomienda Visual Studio 2019. Si usa Visual Studio 2017, actualice a visual studio 2017 versión 15,8 o
posterior. Si usa Visual Studio para Mac, actualice a Visual Studio 2017 para Mac versión 7,6 o posterior.
2. Instale paquetes y herramientas de gráficos circulares de Android (API 28) mediante el administrador
de SDK.
3. Cree un nuevo proyecto de Xamarin. Android que tenga como destino Android 9,0.
4. Configurar un emulador o un dispositivo para probar aplicaciones de gráficos circulares Android.
En las secciones siguientes se explica cada uno de estos pasos:
Actualizar Visual Studio
Se recomienda Visual Studio 2019 para compilar aplicaciones de gráficos circulares de Android con Xamarin.
Si usa Visual Studio 2017, actualice a Visual Studio 2017 versión 15,8 o posterior (para obtener instrucciones,
consulte actualización de Visual studio 2017 a la versión más reciente). En macOS, actualice a Visual Studio 2017
para Mac 7,6 o posterior (para obtener instrucciones, consulte configuración e instalación Visual Studio para Mac).
Instalar el Android SDK
Para crear un proyecto con Xamarin. Android 9,0, primero debe usar el administrador de Android SDK para
instalar la plataforma SDK para el círculo de Android (nivel de API 28) o posterior.
1. Inicie el administrador de SDK. En Visual Studio, haga clic en herramientas > Android > Android SDK
Manager. En Visual Studio para Mac, haga clic en herramientas > administrador de SDK.
2. En la esquina inferior derecha, haga clic en el icono de engranaje y seleccione repositorio > Google (no
compatible) :

3. Instale los paquetes del SDK de gráficos circulares de Android , que se muestran como Android SDK
plataforma 28 en la pestaña plataformas (para obtener más información acerca del uso del administrador
de SDK, consulte Android SDK Setup):
4. Si usa un emulador, cree un dispositivo virtual que admita el nivel de API 28. Para obtener más
información acerca de la creación de dispositivos virtuales, consulte Administración de dispositivos virtuales
con el Android Device Manager.
Iniciar un proyecto de Xamarin. Android
Cree un nuevo proyecto de Xamarin. Android. Si no está familiarizado con el desarrollo de Android con Xamarin,
consulte Hello, Android para obtener información sobre la creación de proyectos de Xamarin. Android.
Al crear un proyecto de Android, debe configurar las opciones de versión para que tengan como destino Android
9,0 o posterior. Por ejemplo, para tener como destino el gráfico circular de Android, debe configurar el nivel de API
de Android de destino de su proyecto a android 9,0 (API 28). Se recomienda que también establezca el nivel de
plataforma de destino en API 28 o posterior. Para más información sobre la configuración de los niveles de la API
de Android, consulte Descripción de los niveles de API de Android.
Configurar un dispositivo o emulador
Si usa un dispositivo físico, como un nexo o un píxel, puede actualizar el dispositivo a un gráfico circular de
Android siguiendo las instrucciones de imágenes de fábrica para dispositivos de nexo y píxel.
Si usa un emulador, cree un dispositivo virtual para el nivel de API 28 y seleccione una imagen basada en x86. Para
obtener información sobre el uso de la Android Device Manager para crear y administrar dispositivos virtuales,
consulte Administración de dispositivos virtuales con la Android Device Manager. Para obtener información sobre
cómo usar el emulador de Android para probar y depurar, consulte depuración en el Android Emulator.

Características nuevas
El gráfico circular de Android presenta una variedad de características nuevas. Algunas de estas nuevas
características están pensadas para aprovechar las nuevas capacidades de hardware que ofrecen los dispositivos
Android más recientes, mientras que otras están diseñadas para mejorar aún más la experiencia del usuario de
Android:
Mostrar compatibilidad con recortes Proporciona API para buscar la ubicación y la forma del recorte en
la parte superior de la pantalla en los dispositivos Android más recientes. –
Mejoras en las notificaciones Ahora, los mensajes de notificación pueden mostrar imágenes, Person y se
usa una nueva clase para simplificar los participantes de la conversación. –
Posicionamiento interior – Compatibilidad de la plataforma con el protocolo WiFi de tiempo de ida y
vuelta, que permite que las aplicaciones usen dispositivos wifi para la navegación en la configuración de
interior.
Compatibilidad con varias cámaras – Ofrece la capacidad de obtener acceso a flujos simultáneamente
desde varias cámaras físicas (como cámaras duales y de doble retroceso).
En las secciones siguientes se resaltan estas características y se proporcionan ejemplos de código breves para
ayudarle a empezar a usarlas en la aplicación.
Mostrar compatibilidad con recortes
Muchos dispositivos Android más recientes con pantallas de borde a borde tienen un recorte de pantalla (o
"muesca") en la parte superior de la pantalla de la cámara y el altavoz. La captura de pantalla siguiente proporciona
un ejemplo de emulador de un recorte:

Para administrar el modo en que la ventana de la aplicación muestra su contenido en los dispositivos con un
recorte de pantalla, el gráfico circular de Android ha agregado un nuevo atributo de diseño de ventana de
LayoutInDisplayCutoutMode . Este atributo se puede establecer en uno de los siguientes valores:
LayoutInDisplayCutoutModeNever – La ventana nunca se puede superponer con el área de recorte.
LayoutInDisplayCutoutModeShortEdges – La ventana se puede extender en el área de recorte, pero solo en
los bordes cortos de la pantalla.
LayoutInDisplayCutoutModeDefault – Se permite que la ventana se extienda en el área de recorte si el
recorte está incluido en una barra del sistema.
Por ejemplo, para evitar que la ventana de la aplicación se superponga con el área de recorte, establezca el modo
de recorte del diseño en nunca:

Window.Attributes.LayoutInDisplayCutoutMode =
Android.Views.LayoutInDisplayCutoutMode.Never;

En los ejemplos siguientes se proporcionan ejemplos de estos modos de recorte. La primera captura de pantalla de
la izquierda es la aplicación en modo sin pantalla completa. En la captura de pantalla del centro, la aplicación se
rellenará LayoutInDisplayCutoutModeShortEdges con LayoutInDisplayCutoutMode el valor establecido en. Tenga en
cuenta que el fondo blanco de la aplicación se extiende en el área Mostrar recorte:
En la captura de pantalla final (encima de la derecha LayoutInDisplayCutoutMode ), se
LayoutInDisplayCutoutModeShortNever establece en antes de que pase a la pantalla completa. Tenga en cuenta que
no se permite que el fondo blanco de la aplicación se extienda en el área Mostrar recorte.
Si necesita información más detallada sobre el área de recorte en el dispositivo, puede usar la nueva clase
DisplayCutout . DisplayCutout representa el área de la pantalla que no se puede usar para mostrar el contenido.
Puede usar esta información para recuperar la ubicación y la forma del recorte para que la aplicación no intente
Mostrar contenido en este área no funcional.
Para obtener más información acerca de las nuevas características de recorte en Android P, consulte Mostrar
compatibilidad conrecortes.
Mejoras en las notificaciones
El gráfico circular de Android presenta las siguientes mejoras para mejorar la experiencia de mensajería:
Los canales de notificación (introducidos en Android Oreo) ahora admiten el bloqueo de grupos de canales.
El sistema de notificación tiene tres nuevas categorías de no molestar (priorizar alarmas, sonidos del
sistema y orígenes multimedia). Además, hay siete nuevos modos de no molestar que se pueden usar para
suprimir las interrupciones visuales (como los distintivos, las luces de notificación, la apariencia de la barra
de estado y el inicio de las actividades de pantalla completa).
Se ha agregado una nueva clase Person para representar al remitente de un mensaje. El uso de esta clase
ayuda a optimizar la representación de cada notificación al identificar a las personas implicadas en una
conversación (incluidos los avatares y los URI).
Las notificaciones ahora pueden mostrar imágenes.
En el ejemplo siguiente se muestra cómo usar las nuevas API para generar una notificación que contiene una
imagen. En las siguientes capturas de pantallas, se publica una notificación de texto y va seguida de una
notificación con una imagen incrustada. Cuando las notificaciones se expanden (como se muestra a la derecha), se
muestra el texto de la primera notificación y se amplía la imagen incrustada en la segunda notificación:
En el ejemplo siguiente se muestra cómo incluir una imagen en una notificación circular de Android y se muestra
el uso de la Person nueva clase:
1. Cree un Person objeto que represente al remitente. Por ejemplo, el nombre y el icono del remitente se
incluyen en fromPerson :

Icon senderIcon = Icon.CreateWithResource(this, Resource.Drawable.sender_icon);


Person fromPerson = new Person.Builder()
.SetIcon(senderIcon)
.SetName("Mark Sender")
.Build();

2. Cree un Notification.MessagingStyle.Message que contenga la imagen que se va a enviar, pasando la


imagen al nuevo método Notification. MessagingStyle. Message. SetData . Por ejemplo:

Uri imageUri = Uri.Parse("android.resource://com.xamarin.pminidemo/drawable/example_image");


Notification.MessagingStyle.Message message = new Notification.MessagingStyle
.Message("Here's a picture of where I'm currently standing", 0, fromPerson)
.SetData("image/", imageUri);

3. Agregue el mensaje a un Notification.MessagingStyle objeto. Por ejemplo:

Notification.MessagingStyle style = new Notification.MessagingStyle(fromPerson)


.AddMessage(message);

4. Conecte este estilo al generador de notificaciones. Por ejemplo:


builder = new Notification.Builder(this, MY_CHANNEL)
.SetContentTitle("Tour of the Colosseum")
.SetContentText("I'm standing right here!")
.SetSmallIcon(Resource.Mipmap.ic_notification)
.SetStyle(style)
.SetChannelId(MY_CHANNEL);

5. Publique la notificación. Por ejemplo:

const int notificationId = 1000;


notificationManager.Notify(notificationId, builder.Build());

Para obtener más información sobre la creación de notificaciones, consulte notificaciones locales.
Posicionamiento interior
El gráfico circular de Android proporciona compatibilidad con IEEE 802.11 MC (también conocido como tiempo de
ida yvuelta WiFi), lo que permite que las aplicaciones detecten la distancia a uno o varios puntos de acceso Wi-Fi.
Con esta información, es posible que la aplicación aproveche el posicionamiento interior con una precisión de uno
a dos metros. En los dispositivos Android que proporcionan compatibilidad de hardware para IEEE 801.11 MC, la
aplicación puede ofrecer características de navegación, como el control basado en la ubicación de dispositivos
inteligentes o las instrucciones que se activan a través de un almacén:

La nueva clase WifiRttManager y varias clases auxiliares proporcionan los medios para medir la distancia a los
dispositivos Wi-Fi. Para obtener más información sobre las API de posicionamiento interior introducidas en
Android P, consulte Android .net. WiFi. RTT.
Compatibilidad con varias cámaras
Muchos dispositivos Android más recientes tienen cámaras duales y/o de doble retroceso que son útiles para
características como la visión estéreo, los efectos visuales mejorados y la capacidad de zoom mejorada. Android P
incorpora una nueva API de varias cámaras que permite que la aplicación use una cámara lógica (o variascámaras
lógicas) que esté respaldada por dos o más cámaras físicas. Para determinar si el dispositivo es compatible con una
cámara lógica múltiple, puede ver las capacidades de cada cámara en el dispositivo para ver si es compatible con
RequestAvailableCapabilitiesLogicalMultiCamera.
Android circular también incluye una nueva clase configuracióndesesión que se puede usar para ayudar a reducir
los retrasos durante la captura inicial y eliminar la necesidad de iniciar e iniciar el flujo de la cámara.
Para obtener más información sobre la compatibilidad con varias cámaras en Android P, consulte compatibilidad
con múltiples cámaras y actualizacionesde la cámara.
Otras características
Además, el gráfico circular de Android admite otras características nuevas:
La nueva clase AnimatedImageDrawable , que se puede usar para dibujar y mostrar imágenes animadas.
Nueva clase ImageDecoder que reemplaza BitmapFactory A. ImageDecoder se puede usar para descodificar
AnimatedImageDrawable un.

Compatibilidad con imágenes HDR (alto rango dinámico) y vídeo HEIF (formato de archivo de imagen de
alta eficiencia).
El JobScheduler se ha mejorado para controlar de forma más inteligente los trabajos relacionados con la
red. El nuevo método GetNetwork de la clase JobParameters devuelve la mejor red para realizar cualquier
solicitud de red para un trabajo determinado.
Para obtener más información sobre las características más recientes de los gráficos circulares de Android,
consulte características y API de Android 9.

Cambios de comportamiento
Cuando la versión de Android de destino se establece en el nivel de API 28, hay varios cambios de plataforma que
pueden afectar al comportamiento de la aplicación incluso si no está implementando las nuevas características
descritas anteriormente. La lista siguiente es un breve resumen de estos cambios:
Las aplicaciones deben solicitar ahora permisos de primer plano antes de usar los servicios en primer plano.
Si la aplicación tiene más de un proceso, no puede compartir un único directorio de datos de vista única en
todos los procesos.
Ya no se permite acceder directamente al directorio de datos de otra aplicación mediante la ruta de acceso.
Para más información sobre los cambios de comportamiento de las aplicaciones destinadas a Android P, consulte
cambios de comportamiento.

Código de ejemplo
AndroidPMiniDemo es una aplicación de ejemplo de Xamarin. Android para un gráfico circular de Android que
muestra cómo establecer los modos de recorte Person de pantalla, cómo usar la nueva clase y cómo enviar una
notificación que incluye una imagen.

Resumen
En este artículo se presentó Android circular y se explica cómo instalar y configurar las herramientas y los
paquetes más recientes para el desarrollo de Xamarin. Android con el gráfico circular de Android. Proporciona
información general sobre las características clave disponibles en el gráfico circular de Android, con código fuente
de ejemplo para algunas de estas características. Incluye vínculos a la documentación de la API y temas para
desarrolladores de Android que le ayudarán a empezar a crear aplicaciones para el gráfico circular de Android.
También se resaltan los cambios de comportamiento de los sectores de Android más importantes que podrían
afectar a las aplicaciones existentes.

Vínculos relacionados
Gráfico circular de Android 9
Características de Oreo
16/08/2019 • 30 minutes to read • Edit Online

Cómo empezar a usar Xamarin. Android para desarrollar aplicaciones para la versión más reciente de Android.
Android 8,0 Oreo es la versión más reciente de Android disponible en Google. Android Oreo ofrece muchas
características nuevas de interés para los desarrolladores de Xamarin. Android. Estas características incluyen
canales de notificación, notificaciones de notificación, fuentes personalizadas en XML, fuentes descargables,
Autorrellenar e imagen en imagen (PIP ). Android Oreo incluye nuevas API para estas nuevas funcionalidades y
estas API están disponibles para las aplicaciones de Xamarin. Android cuando se usa Xamarin. Android 8,0 y
versiones posteriores.

Este artículo está estructurado para ayudarle a empezar a desarrollar aplicaciones de Xamarin. Android para
Android 8,0 Oreo. Se explica cómo instalar las actualizaciones necesarias, configurar el SDK y crear un emulador
(o dispositivo) para las pruebas. También proporciona un esquema de las nuevas características de Android 8,0
Oreo, con vínculos a aplicaciones de ejemplo que muestran cómo usar las características de Android Oreo en
aplicaciones de Xamarin. Android.

Requisitos
Se requiere lo siguiente para usar las características de Oreo de Android en aplicaciones basadas en Xamarin:
Visual Studio – Si usa Windows, se requiere la versión 15,5 o posterior de Visual Studio. Si utiliza un
equipo Mac, se necesita Visual Studio para Mac versión 7.2.0.
Xamarin. Android – Xamarin. Android 8,0 o posterior debe estar instalado y configurado con Visual
Studio.
Android SDK – Android SDK 8,0 (API 26) o posterior debe instalarse a través del administrador de
Android SDK.

Introducción
Para empezar a usar Android Oreo con Xamarin. Android, debe descargar e instalar las herramientas y los
paquetes de SDK más recientes antes de poder crear un proyecto de Oreo de Android:
1. Actualice a la versión más reciente de Visual Studio.
2. Instale las herramientas y los paquetes de Android 8.0.0 (API 26) o posterior a través del administrador
de SDK.
3. Cree un nuevo proyecto de Xamarin. Android que tenga como destino Android Oreo (API 26).
4. Configurar un emulador o un dispositivo para probar aplicaciones Android Oreo.
En las secciones siguientes se explica cada uno de estos pasos:
Actualización de Visual Studio y Xamarin. Android
Para agregar compatibilidad con Android Oreo a Visual Studio, haga lo siguiente:
Visual Studio
Visual Studio para Mac
Para Visual Studio 2019, use el Administrador de SDK para instalar el nivel de API 26,0 o posterior.
Si usa Visual Studio 2017:
1. Actualice a Visual Studio 2017 versión 15,7 o posterior (consulte Actualizar visual studio 2017).
2. Use el Administrador de SDK para instalar el nivel de API 26,0 o posterior.
Para obtener más información sobre la compatibilidad de Xamarin con Android Oreo, consulte las notas de la
versión de Xamarin. Android 8,0.
Instalar el Android SDK
Para crear un proyecto con Xamarin. Android 8,0, primero debe usar el administrador de Android SDK de
Xamarin para instalar la plataforma SDK para Android 8,0-Oreo o posterior. También debe instalar Android SDK
Tools 26,0 o posterior.
Visual Studio
Visual Studio para Mac
1. Inicie el administrador de SDK (en Visual Studio, haga clic en herramientas > Android > Android SDK
Manager).
2. Instale los paquetes de Android 8,0-Oreo . Si usa el emulador de Android SDK, asegúrese de incluir las
imágenes del sistema x86 que necesitará:
3. Instale Android SDK Tools 26.0.2 o posterior, Android SDK Platform -Tools 26.0.0 o posterior y
Android SDK build-tools 26.0.0 (o posterior):

Iniciar un proyecto de Xamarin. Android


Cree un nuevo proyecto de Xamarin. Android. Si no está familiarizado con el desarrollo de Android con Xamarin,
consulte Hello, Android para obtener información sobre la creación de proyectos de Xamarin. Android.
Al crear un proyecto de Android, debe configurar las opciones de versión para que tengan como destino Android
8,0 o posterior. Por ejemplo, para tener como destino el proyecto para Android 8,0, debe configurar el nivel de API
de Android de destino de su proyecto en android 8,0 (API 26) . Se recomienda que también establezca el nivel
de plataforma de destino en la API 26 o posterior. Para más información sobre la configuración de niveles de nivel
de API de Android, consulte Descripción de los niveles de API de Android.
Configurar un emulador o un dispositivo
Si intenta iniciar el administrador de AVD basado en la GUI de Google predeterminado después de instalar
Android SDK Tools 26,0 o una versión posterior, es posible que aparezca el siguiente cuadro de diálogo de error,
que le indica que debe usar la herramienta de administrador de la línea de comandos avdmanager en su lugar:
Visual Studio
Visual Studio para Mac

Este mensaje se muestra porque Google ya no proporciona un administrador AVD de GUI independiente que
admite la API 26,0 y versiones posteriores. Para Android 8,0 Oreo, debe usar el administrador de Android
Emulator de Xamarin o la herramienta de línea avdmanager de comandos para crear dispositivos virtuales para
Android Oreo.
Para usar la Android Device Manager para crear y administrar dispositivos virtuales, consulte Administración de
dispositivos virtuales con la Android Device Manager. Para crear dispositivos virtuales sin el Android Device
Manager, siga los pasos descritos en la sección siguiente.
Creación de dispositivos virtuales con avdmanager
Para usar avdmanager para crear un nuevo dispositivo virtual, siga estos pasos:
Visual Studio
Visual Studio para Mac
1. Abra una ventana del símbolo del sistema JAVA_HOME y establezca la ubicación del SDK de Java en el
equipo. Para una instalación típica de Xamarin, puede usar el siguiente comando:

setx JAVA_HOME "C:\Program Files\Java\jdk1.8.0_131"

2. Agregue la ubicación de la carpeta bin Android SDK a su PATH . Para una instalación típica de Xamarin,
puede usar el siguiente comando:

setx PATH "%PATH%;C:\Program Files (x86)\Android\android-sdk\tools\bin"

3. Cierre la ventana del símbolo del sistema y abra una nueva ventana del símbolo del sistema. Cree un nuevo
dispositivo virtual mediante el comando avdmanager . Por ejemplo, para crear un AVD denominado AVD -
Oreo-8,0 con la imagen de sistema x86 para el nivel de API 26, use el siguiente comando:

avdmanager create avd -n AVD-Oreo-8.0 -k "system-images;android-26;google_apis;x86"

4. Cuando se le pregunte si desea crear un perfil de hardware personalizado [no] , puede escribir no y
aceptar el perfil de hardware predeterminado. En caso afirmativo, avdmanager le pedirá una lista de
preguntas para personalizar el perfil de hardware.
Después de avdmanager para crear el dispositivo virtual, se incluirá en el menú desplegable del dispositivo:
Para obtener más información sobre la configuración de un emulador de Android para pruebas y depuración,
consulte depuración en el Android Emulator.
Si usa un dispositivo físico, como un nexo o un píxel, puede actualizar el dispositivo a través de las actualizaciones
automáticas por aire (OTA) o descargar una imagen del sistema y hacer que el dispositivo parpadee directamente.
Para obtener más información sobre cómo actualizar manualmente el dispositivo a Android Oreo, consulte
imágenes de fábrica para dispositivos de nexo y píxel.

Características nuevas
Android Oreo presenta una variedad de nuevas características y funcionalidades, como canales de notificación,
notificaciones de notificación, fuentes personalizadas en XML, fuentes descargables, Autorrellenar e imagen en
imagen. En las secciones siguientes se resaltan estas características y se proporcionan vínculos para ayudarle a
empezar a usarlas en la aplicación.
Canales de notificación
Los canales de notificación son categorías definidas por la aplicación para las notificaciones. Puede crear un canal
de notificación para cada tipo de notificación que necesite enviar, y puede crear canales de notificación para
reflejar las elecciones realizadas por los usuarios de la aplicación. La nueva característica de canales de notificación
permite proporcionar a los usuarios un control minucioso de los distintos tipos de notificaciones. Por ejemplo, si
está implementando una aplicación de mensajería, puede crear canales de notificación independientes para cada
grupo de conversación creado por un usuario.
Canales de notificación explica cómo crear un canal de notificación y usarlo para publicar notificaciones locales.
Para obtener un ejemplo de código del mundo real, consulte el ejemplo NotificationChannels . en esta aplicación
de ejemplo se administran dos canales y se establecen otras opciones de notificación.
Notificaciones de notificación
Los distintivos de notificación son pequeños puntos que aparecen en los iconos de la aplicación, tal como se
muestra en esta captura de pantalla:
Estos puntos indican que hay nuevas notificaciones de uno o varios canales de notificación en la aplicación
asociada a ese icono – de la aplicación. se trata de notificaciones que el usuario todavía no ha descartado o que ha
actuado. Los usuarios pueden presionar un botón largo para echar un vistazo a las notificaciones asociadas a una
notificación de notificación, descartando o actuando en notificaciones del menú de larga duración que appeaars.
Para obtener más información sobre los distintivos de notificación, consulte el tema notificaciones de notificación
para desarrolladores de Android.
Fuentes personalizadas en XML
Android Oreo incluye fuentes en XML, lo que permite incorporar fuentes personalizadas como recursos. Se
admiten los formatos de fuente OpenType ( . OTF) y TrueType ( . ttf). Para agregar fuentes como recursos, haga lo
siguiente:
1. Cree una carpeta de recursos/fuente .
2. Copie los archivos de fuente (por ejemplo, archivos . ttf y . OTF ) en recursos/fuente.
3. Si es necesario, cambie el nombre de cada archivo de fuente para que se adhiere a las convenciones de
nomenclatura de archivos de Android (es decir, use solo minúsculas a -z, 0 -9y caracteres de subrayado en
los nombres de archivo). Por ejemplo, se podría cambiar Pacifico-Regular.ttf el nombre del archivo de
fuente pacifico.ttf a algo parecido a.
4. Aplique la fuente personalizada con el nuevo android:fontFamily atributo en el XML de diseño. Por
ejemplo, la siguiente TextView declaración utiliza el recurso de fuente Pacifico. ttf agregado:

<TextView
android:text="Example Text in Pacifico Regular"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/pacifico" />

También puede crear un archivo XML de la familia de fuentes que describa varias fuentes, así como los detalles de
estilo y peso. Para obtener más información, vea el tema sobre las fuentes de desarrollador de Android en XML .
Fuentes descargables
A partir de Android Oreo, las aplicaciones pueden solicitar fuentes de un proveedor en lugar de agruparlas en el
APK. Las fuentes se descargan de la red solo según sea necesario. Esta característica reduce el tamaño de APK, lo
que mantiene la memoria del teléfono y el uso de datos móviles. También puede usar esta característica en las
versiones 14 y posteriores de la API de Android mediante la instalación del paquete de la biblioteca de
compatibilidad de Android 26.
Cuando la aplicación necesita una fuente, se crea un FontsRequest objeto (que especifica la fuente que se va a
descargar) y, a FontsContract continuación, se pasa a un método para descargar la fuente. En los pasos siguientes
se describe con más detalle el proceso de descarga de fuentes:
1. Cree una instancia de un objeto FontRequest .
2. Subclase y cree una instancia de FontsContract. FontRequestCallback.
3. Implemente el método FontRequestCallback. OnTypeFaceRetrieved , que se usa para controlar la
finalización de la solicitud de fuente.
4. Implemente el método FontRequestCallback. OnTypeFaceRequestFailed , que se usa para informar a la
aplicación de los errores que se produzcan durante el proceso de solicitud de fuentes.
5. Llame al método FontsContract. RequestFonts para recuperar la fuente del proveedor de fuentes.
Cuando se llama al RequestFonts método, primero comprueba si la fuente se almacena en caché localmente
(desde una llamada anterior a RequestFont ). Si no se almacena en caché, llama al proveedor de fuentes, recupera
la fuente de forma asincrónica y, a continuación, devuelve los resultados a la aplicación invocando
OnTypeFaceRetrieved el método.

En el ejemplo de fuentes descargables se muestra cómo usar la característica de fuentes descargables introducida
en Android Oreo.
Para obtener más información acerca de la descarga de fuentes, vea el tema sobre las fuentes descargables para
desarrolladores de Android.
Rellena
El nuevo marco de Autorrelleno en Android Oreo facilita a los usuarios la administración de tareas repetitivas
como el inicio de sesión, la creación de cuentas y las transacciones de tarjetas de crédito. Los usuarios dedican
menos tiempo a escribir información (lo que puede provocar errores de entrada). Para que la aplicación pueda
trabajar con el marco de Autorrelleno, se debe habilitar un servicio de Autorrelleno en la configuración del
sistema (los usuarios pueden habilitar o deshabilitar Autorrellenar).
En el ejemplo AutofillFramework se muestra el uso del marco de Autorrelleno. Incluye implementaciones de las
actividades de cliente con vistas que se deben rellenar de autocompletar y un servicio que puede proporcionar
datos de Autorrelleno a las actividades de cliente.
Para obtener más información sobre la nueva característica Autorrellenar y cómo optimizar la aplicación para
Autorrellenar, vea el tema sobre el marco de Autorrelleno para desarrolladores de Android.
Imagen en imagen (PIP)
Android Oreo permite que una actividad se inicie en modo de imagen en imagen (PIP ), superponiendo la pantalla
de otra actividad. Esta característica está destinada a la reproducción de vídeo.
Para especificar que la actividad de la aplicación puede usar el modo PIP, establezca la marca siguiente en true en
el manifiesto de Android:

android:supportsPictureInPicture

Para especificar cómo debe comportarse la actividad cuando está en modo PIP, use el nuevo objeto
PictureInPictureParams . PictureInPictureParams representa un conjunto de parámetros que se usan para
inicializar y actualizar una actividad en modo PIP (por ejemplo, la relación de aspecto preferida de la actividad). Se
han agregado los siguientes métodos PIP nuevos Activity a en Android Oreo:
EnterPictureInPictureMode – coloca la actividad en modo PIP. La actividad se coloca en la esquina de la
pantalla y el resto de la pantalla se rellena con la actividad anterior que estaba en la pantalla.
SetPictureInPictureParams – Actualiza los valores de configuración de PIP de la actividad (por ejemplo, un
cambio en la relación de aspecto).
En el ejemplo PictureInPicture se muestra el uso básico del modo de imagen en imagen (PIP ) para dispositivos de
mano introducidos en Oreo. En el ejemplo se reproduce un vídeo que continúa sin interrupciones mientras se
alterna entre los modos de visualización u otras actividades.
Otras características
Android Oreo contiene muchas otras características nuevas, como la biblioteca de compatibilidad de Emoji, la API
de ubicación, los límites de fondo, el color de gama amplia para las aplicaciones, los nuevos códecs de audio, las
mejoras de WebView, la compatibilidad con la navegación mediante el teclado mejorada y una nueva API de
AAudio (audio de Pro) para audio de baja latencia de alto rendimiento. para obtener más información sobre estas
características, vea el tema Android Developer Android Oreo features and API .
Cambios de comportamiento
Android Oreo incluye una variedad de cambios de comportamiento del sistema y de la API que pueden afectar a
la funcionalidad de las aplicaciones existentes. Estos cambios se describen como se indica a continuación.
Límites de ejecución en segundo plano
Para mejorar la experiencia del usuario, Android Oreo impone limitaciones en lo que las aplicaciones pueden
hacer mientras se ejecuta en segundo plano. Por ejemplo, si el usuario ve un vídeo o juega un juego, una
aplicación que se ejecuta en segundo plano podría perjudicar el rendimiento de una aplicación de uso intensivo de
vídeo que se ejecuta en primer plano. Como resultado, Android Oreo coloca las siguientes restricciones en las
aplicaciones que no interactúan directamente con el usuario:
1. Limitaciones del servicio en segundo plano – Cuando una aplicación se ejecuta en segundo plano,
tiene una ventana de varios minutos en la que todavía se permite crear y usar los servicios. Al final de la
ventana, Android detiene el servicio en segundo plano de la aplicación y lo tratacomo inactivo.
2. Limitaciones de difusión – Android 7,0 (API 25) colocaba limitaciones en las difusiones que una
aplicación registra para recibir. Android Oreo hace que estas limitaciones sean más rigurosas. Por ejemplo,
las aplicaciones de Oreo de Android ya no pueden registrar receptores de difusión para difusiones
implícitas en sus manifiestos.
Para obtener más información sobre los nuevos límites de ejecución en segundo plano, vea el tema sobre los
límites de ejecución en segundo plano para desarrolladores de Android.
Cambios importantes
Las aplicaciones que tienen como destino Android Oreo o posterior deben modificar sus aplicaciones para admitir
los siguientes cambios, si procede:
Android Oreo deja de tener la capacidad de establecer la prioridad de las notificaciones individuales. En su
lugar, establezca un nivel de importancia recomendado al crear un canal de notificación. El nivel de
importancia que se asigna a un canal de notificación se aplica a todos los mensajes de notificación que se
publican en él.
En el caso de las aplicaciones destinadas a Android Oreo, PendingIntent.GetService() no funciona debido a
los nuevos límites de los servicios iniciados en segundo plano. Si tiene como destino Android Oreo, debe
usar PendingIntent. GetBroadcast en su lugar.

Código de ejemplo
Hay varios ejemplos de Xamarin. Android disponibles para mostrarle cómo sacar provecho de las características
de Oreo de Android:
NotificationsChannels muestra cómo usar el nuevo sistema de canales de notificación introducido en
Android Oreo. En este ejemplo se administran dos canales de notificaciones: uno con la importancia
predeterminada y el otro con importancia alta.
PictureInPicture muestra el uso básico del modo de imagen en imagen (PIP ) para dispositivos de mano
introducidos en Oreo. En el ejemplo se reproduce un vídeo que continúa sin interrupciones mientras se
alterna entre los modos de visualización u otras actividades.
AutofillFramework muestra el uso del marco de Autorrelleno. Incluye implementaciones de las actividades
de cliente con vistas que se deben rellenar de autocompletar y un servicio que puede proporcionar datos de
Autorrelleno a las actividades de cliente.
Fuentes descargables proporciona un ejemplo de cómo usar la característica de fuentes descargables que
se ha descrito anteriormente.
EmojiCompat muestra el uso de la biblioteca de compatibilidad con EmojiCompat. Puede usar esta
biblioteca para impedir que la aplicación muestre caracteres de Emoji que faltan como caracteres "tofu".
La intención de actualizaciones de ubicación pendientes muestra el uso de la API de ubicación para obtener
actualizaciones de la ubicación PendingIntent de un dispositivo mediante.
El servicio en primer plano actualizaciones de ubicación muestra cómo usar la API de ubicación para
obtener actualizaciones sobre la ubicación de un dispositivo mediante un servicio en primer plano enlazado
e iniciado.

Vídeo
Desarrollo de Android 8,0 Oreo conC#

Resumen
En este artículo se presentaron Android Oreo y se explicó cómo instalar y configurar las herramientas y los
paquetes más recientes para el desarrollo de Xamarin. Android en Android Oreo. Proporciona información
general sobre las características clave disponibles en Android Oreo, con vínculos a código fuente de ejemplo para
varias características nuevas. Incluye vínculos a la documentación de la API y temas para desarrolladores de
Android que le ayudarán a empezar a crear aplicaciones para Android Oreo. También se resaltan los cambios de
comportamiento de Android Oreo más importantes que podrían afectar a las aplicaciones existentes.

Vínculos relacionados
Android 8,0 Oreo
Características de nougat
19/08/2019 • 23 minutes to read • Edit Online

Cómo empezar a usar Xamarin. Android para desarrollar aplicaciones para Android nougat.
En este artículo se proporciona un esquema de las características introducidas en Android nougat, se explica cómo
preparar Xamarin. Android para el desarrollo de Android nougat y se proporcionan vínculos a aplicaciones de
ejemplo que muestran cómo usar las características de Android nougat en Aplicaciones de Xamarin. Android.

Información general
Android nougat es el seguimiento de Google para Android 6,0 Marshmallow. Xamarin. Android proporciona
compatibilidad con enlaces Android 7. x en Xamarin Android 7,0 y versiones posteriores. Android nougat agrega
muchas API nuevas para las características de nougat que se describen a continuación: estas API están disponibles
para las aplicaciones de Xamarin. Android cuando se usa Xamarin. Android 7,0.

Para obtener más información sobre las API de Android 7. x, consulte android 7,1 para desarrolladores. Para
obtener una lista de problemas conocidos de Xamarin. Android 7,0, consulte las notas de la versión.
Android nougat proporciona muchas características nuevas de interés para los desarrolladores de Xamarin.
Android. Entre ellas se incluyen:
Compatibilidad con varias ventanas – Esta mejora permite a los usuarios abrir dos aplicaciones en la
pantalla al mismo tiempo.
Mejoras en las notificaciones El sistema de notificaciones rediseñada en Android nougat incluye una
característica de respuesta directa que permite a los usuarios responder rápidamente a los mensajes de
texto directamente desde la interfaz de usuario de notificaciones. – Además, si la aplicación crea
notificaciones para los mensajes recibidos, la nueva característica de notificaciones integradas puede
agrupar las notificaciones como un solo grupo cuando se recibe más de un mensaje.
Protector de datos – Esta característica es un nuevo servicio del sistema que ayuda a reducir el uso de
datos móviles por parte de las aplicaciones; ofrece a los usuarios el control sobre cómo usan los datos
móviles los datos de las aplicaciones.
Además, Android nougat ofrece muchas otras mejoras de interés para los desarrolladores de aplicaciones, como
una nueva característica de configuración de seguridad de red, Doze sobre la marcha, atestación de clave, nuevas
API de configuración rápida, compatibilidad con múltiples configuraciones regionales, API de ICU4J, mejoras de
WebView, acceso a las características del lenguaje Java 8, acceso a directorios de ámbito, una API de puntero
personalizada, compatibilidad con plataforma VR, archivos virtuales y optimizaciones de procesamiento en
segundo plano.
En este artículo se explica cómo empezar a compilar aplicaciones con Android nougat para probar las nuevas
características y planear la migración o el trabajo de características para dirigirse a la nueva plataforma Android
nougat.

Requisitos
Para usar las nuevas características de Android nougat en aplicaciones basadas en Xamarin, se requiere lo
siguiente:
Visual Studio o Visual Studio para Mac – Si usa Visual Studio, se requiere la versión 4.2.0.628 o
posterior de Visual Studio Tools para Xamarin. Si usa Visual Studio para Mac, se requiere la versión 6.1.0 o
posterior de Visual Studio para Mac.
Xamarin. Android – Xamarin. Android 7,0 o posterior debe estar instalado y configurado con Visual Studio
o Visual Studio para Mac.
Android SDK Android SDK 7,0 (API 24) o posterior debe instalarse a través del administrador de Android
SDK.
Kit para desarrolladores de Java El desarrollo de Xamarin Android 7,0 requiere JDK 8 o posterior si está
desarrollando para el nivel de API 24 o superior (JDK 8 también admite niveles de API anteriores a 24). –
Se requiere la versión de 64 bits de JDK 8 Si usa controles personalizados o la vista previa de formularios.

IMPORTANT
Xamarin.Android no admite JDK 9.

Tenga en cuenta que las aplicaciones se deben volver a generar con Xamarin C6SR4 o una versión posterior para
que funcionen de forma confiable con Android nougat. Dado que Android nougat solo puede vincularse a las
bibliotecas nativas proporcionadas por NDK, es posible que las aplicaciones existentes que usan bibliotecas como
mono. Data. SQLite. dll se bloqueen al ejecutarse en Android nougat si no se vuelven a generar correctamente.

Introducción
Para empezar a usar Android nougat con Xamarin. Android, debe descargar e instalar las herramientas y los
paquetes de SDK más recientes antes de poder crear un proyecto de nougat de Android:
1. Instale las últimas actualizaciones de Xamarin. Android desde Xamarin.
2. Instale los paquetes y las herramientas de Android 7,0 (API 24) o versiones posteriores.
3. Cree un nuevo proyecto de Xamarin. Android que tenga como destino Android nougat.
4. Configurar un emulador o un dispositivo para Android nougat.
En las secciones siguientes se explica cada uno de estos pasos:
Instalación de actualizaciones de Xamarin
Para agregar compatibilidad con Xamarin para Android nougat, cambie el canal de actualizaciones en Visual
Studio o Visual Studio para Mac al canal estable y aplique las actualizaciones más recientes. Si también necesita
características que solo están disponibles en el canal alfa o beta, puede cambiar al canal alfa o beta (los canales alfa
y beta también proporcionan compatibilidad con Android 7. x). Para obtener información sobre cómo cambiar el
canal de actualizaciones (versiones), consulte cambiar el canal de actualizaciones.
Instalar el Android SDK
Para crear un proyecto con Xamarin Android 7,0, primero debe usar el administrador de Android SDK para
instalar la plataforma SDK Android N (API 24) o posterior. También debe instalar la Android SDK Toolsmás
reciente:
1. Inicie el administrador de Android SDK (en Visual Studio para Mac, use Herramientas > abrir el…
administrador de Android SDK; en Visual Studio, use Herramientas > Android > Android SDK
Manager).
2. Instale Android 7,0 (API 24) o posterior:

3. Instale las herramientas de Android SDK más recientes:

Debe instalar Android SDK Tools revisión 25.2.2 o posterior, Android SDK Platform Tools 24.0.3 o posterior
y Android SDK Build Tools 24.0.2 o posterior.
4. Compruebe que la Ubicación del kit de desarrollo de Java está configurada para JDK 1,8:

Para ver esta configuración en Visual Studio, haga clic en herramientas > opciones > Xamarin >
configuración de Android. En Visual Studio para Mac, haga clic en preferencias > proyectos >
ubicaciones del SDK > Android.
Iniciar un proyecto de Xamarin. Android
Cree un nuevo proyecto de Xamarin. Android. Si no está familiarizado con el desarrollo de Android con Xamarin,
consulte Hello, Android para obtener información sobre la creación de proyectos de Xamarin. Android.
Al crear un proyecto de Android, debe configurar las opciones de versión para que tengan como destino Android
7,0 o posterior. Por ejemplo, para tener como destino el proyecto para Android 7,0, debe configurar el nivel de API
de Android de destino de su proyecto en android 7,0 (API 24-nougat) . Se recomienda establecer el nivel de
plataforma de destino en API 24 o posterior. Para más información sobre la configuración de niveles de nivel de
API de Android, consulte Descripción de los niveles de API de Android.

NOTE
Actualmente, debe establecer la versión mínima de Android en Android 7,0 (API 24-nougat) para implementar la
aplicación en dispositivos Android nougat o emuladores.

Configurar un emulador o un dispositivo


Si usa un emulador, inicie Android AVD Manager y cree un nuevo dispositivo con la siguiente configuración:
Dispositivo: Nexus 5X, Nexus 6, el 6P de Nexus, el jugador de Nexus, el Nexus 9 o el píxel C.
Destino: Android 7,0-nivel de API 24
Abi: x86 o x86_64
Por ejemplo, este dispositivo virtual está configurado para emular un nexo 6:

Si usa un dispositivo físico, como un nexo de Nexus 5, 6 o 9, puede actualizar el dispositivo a través de las
actualizaciones automáticas por aire (OTA) o descargar una imagen del sistema y hacer que el dispositivo parpadee
directamente. Para obtener más información sobre cómo actualizar manualmente el dispositivo a Android nougat,
consulte imágenes de OTA para dispositivos Nexus.
Tenga en cuenta que los dispositivos de Nexus 5 no se admiten en Android nougat.

Características nuevas
Android nougat presenta una variedad de características y funcionalidades nuevas, como la compatibilidad con
varias ventanas, las mejoras de notificaciones y el protector de datos. En las secciones siguientes se resaltan estas
características y se proporcionan vínculos para ayudarle a empezar a usarlas en la aplicación.
Modo de varias ventanas
El modo de varias ventanas permite a los usuarios abrir dos aplicaciones a la vez con una compatibilidad completa
con varias tareas. Estas aplicaciones pueden ejecutarse en paralelo (horizontal) o una por encima de la otra
(vertical) en el modo de pantalla dividida. Los usuarios pueden arrastrar un divisor entre las aplicaciones para
cambiar su tamaño y pueden cortar y pegar contenido entre las aplicaciones. Cuando se presentan dos
aplicaciones en el modo de varias ventanas, la actividad seleccionada continúa ejecutándose mientras la actividad
no seleccionada se pausa pero sigue estando visible. El modo de varias ventanas no modifica el ciclo de vida de la
actividad de Android.

Puede configurar cómo las actividades de la aplicación de Xamarin. Android admiten el modo de varias ventanas.
Por ejemplo, puede configurar atributos que establezcan el tamaño mínimo y el alto y ancho predeterminados de
la aplicación en el modo de varias ventanas. Puede usar la nueva Activity.IsInMultiWindowMode propiedad para
determinar si la actividad está en modo de varias ventanas. Por ejemplo:

if (!IsInMultiWindowMode) {
multiDisabledMessage.Visibility = ViewStates.Visible;
} else {
multiDisabledMessage.Visibility = ViewStates.Gone;
}

La aplicación de ejemplo MultiWindowPlayground incluye código C# que muestra cómo sacar partido de varias
interfaces de usuario de ventana con la aplicación.
Para obtener más información sobre el modo de varias ventanas, vea compatibilidad con varias ventanas.
Notificaciones mejoradas
Android nougat introduce un sistema de notificación rediseñado. Incluye una nueva característica de respuesta
directa que permite a los usuarios responder rápidamente a las notificaciones de mensajes de texto entrantes
directamente en la interfaz de usuario de notificaciones. A partir de Android 7,0, los mensajes de notificación se
pueden agrupar como un solo grupo cuando se recibe más de un mensaje. Además, los desarrolladores pueden
personalizar las vistas de notificación, aprovechar las decoraciones del sistema en las notificaciones y aprovechar
las nuevas plantillas de notificación al generar notificaciones.
Respuesta directa
Cuando un usuario recibe una notificación de mensaje entrante, Android nougat hace posible responder al
mensaje dentro de la notificación (en lugar de abrir la aplicación de mensajería para enviar una respuesta). Esta
característica de respuesta en línea permite a los usuarios responder rápidamente a un mensaje SMS o de texto
directamente dentro de la interfaz de notificación:

Para admitir esta característica en la aplicación, debe agregar acciones de respuesta en línea a la aplicación a través
de un objeto RemoteInput para que los usuarios puedan responder a través del texto directamente desde la
interfaz de usuario de notificaciones. Por ejemplo, el código siguiente genera un RemoteInput para recibir la
entrada de texto, crea un intento pendiente para la acción de respuesta y crea una acción de entrada remota
habilitada:

// Build a RemoteInput for receiving text input:


var remoteInput = new Android.Support.V4.App.RemoteInput.Builder (EXTRA_REMOTE_REPLY)
.SetLabel (GetString (Resource.String.reply))
.Build ();

// Build a Pending Intent for the reply action to trigger:


PendingIntent replyIntent = PendingIntent.GetBroadcast (ApplicationContext,
conversation.ConversationId,
GetMessageReplyIntent (conversation.ConversationId),
PendingIntentFlags.UpdateCurrent);

// Build an Android 7.0 compatible Remote Input enabled action:


NotificationCompat.Action actionReplyByRemoteInput = new NotificationCompat.Action.Builder (
Resource.Drawable.notification_icon,
GetString (Resource.String.reply),
replyIntent).AddRemoteInput (remoteInput).Build ();

Esta acción se agrega a la notificación:


// Create the notification:
NotificationCompat.Builder builder = new NotificationCompat.Builder (ApplicationContext)
.SetSmallIcon (Resource.Drawable.notification_icon)
...
.AddAction (actionReplyByRemoteInput);

La aplicación de ejemplo del servicio C# de RemoteInput Mensajería incluye código que muestra cómo extender
las notificaciones con un objeto. Para obtener más información sobre cómo agregar acciones de respuesta en línea
a la aplicación para Android 7,0 o posterior, consulte el tema respuesta de Android a las notificaciones.
Notificaciones agrupadas
Los Nougats de Android pueden agrupar los mensajes de notificación juntos (por ejemplo, por tema de mensaje) y
mostrar el grupo en lugar de cada mensaje independiente. Esta característica de notificaciones integradas permite
a los usuarios descartar o archivar un grupo de notificaciones en una acción. El usuario puede desplazarse hacia
abajo para expandir el paquete de notificaciones para ver cada notificación en detalle:

Para admitir notificaciones integradas, la aplicación puede usar el método Builder. SetGroup para agrupar
notificaciones similares. Para obtener más información sobre los grupos de notificación agrupados en Android N,
vea el tema sobre las notificaciones de empaquetado de Android.
Vistas personalizadas
Android nougat permite crear vistas de notificación personalizadas con encabezados de notificación del sistema,
acciones y diseños expansibles. Para obtener más información sobre las vistas de notificaciones personalizadas en
Android nougat, consulte el tema mejoras en las notificaciones de Android.
Protector de datos
A partir de Android nougat, los usuarios pueden habilitar una nueva configuración del protector de datos que
bloquee el uso de datos en segundo plano. Esta configuración también indica a la aplicación que use menos datos
en primer plano siempre que sea posible. El ConnectivityManager se ha ampliado en Android nougat para que la
aplicación pueda comprobar si el usuario ha habilitado el protector de datos para que la aplicación pueda hacer un
esfuerzo por limitar su uso de datos cuando se habilita el protector de datos.
Para obtener más información sobre la nueva característica de protector de datos en Android nougat, consulte el
tema sobre el uso de datos de red de optimización de Android.
Accesos directos a aplicaciones
Android 7,1 presentó una característica de accesos directos de aplicaciones que permite a los usuarios iniciar
rápidamente tareas comunes o recomendadas con la aplicación. Para activar el menú de accesos directos, el
usuario presiona el icono de aplicación para un segundo o más – el menú aparece con una vibración rápida. La
liberación de la prensa hace que el menú permanezca:
Esta característica solo está disponible en el nivel de API 25 o superior. Para obtener más información sobre la
nueva característica de accesos directos de aplicación en Android 7,1, vea el tema sobre accesos directos a
aplicaciones de Android.
Código de ejemplo
Hay varios ejemplos de Xamarin. Android disponibles para mostrarle cómo sacar provecho de las características
de nougat de Android:
MultiWindowPlayground muestra el uso de la API de varias ventanas disponible en Android nougat. Puede
cambiar la aplicación de ejemplo en modo de varias ventanas para ver cómo afecta al ciclo de vida y el
comportamiento de la aplicación.
El servicio de mensajería es un servicio sencillo que envía notificaciones NotificationCompatManager
mediante el. También extiende la notificación con un RemoteInput objeto para permitir que los dispositivos
nougat de Android respondan a través del texto directamente de la notificación sin tener que abrir una
aplicación.
Notificaciones activas muestra cómo usar la API NotificationManager para indicarle el número de
notificaciones que se muestran actualmente en la aplicación.
Acceso a directorios con ámbito Muestra cómo usar la API de acceso a directorios de ámbito para acceder
fácilmente a directorios específicos. Esto sirve como alternativa a tener que definir READ_EXTERNAL_STORAGE
permisos o WRITE_EXTERNAL_STORAGE en el manifiesto.
Arranque directo Muestra cómo almacenar los datos en un almacenamiento cifrado de dispositivo que
siempre está disponible mientras el dispositivo se arranca antes y después de que se escriban las
credenciales de usuario (PIN/patrón/contraseña).

Resumen
En este artículo se presentaron Android nougat y se explicó cómo instalar y configurar las herramientas y los
paquetes más recientes para el desarrollo de Xamarin. Android en Android nougat. También se proporciona
información general sobre las características clave disponibles en Android nougat, con vínculos a código fuente de
ejemplo para ayudarle a empezar a crear aplicaciones para Android nougat.
Vínculos relacionados
Android 7,1 para desarrolladores
Notas de la versión de Xamarin Android 7,0
Características de marshmallow
16/08/2019 • 26 minutes to read • Edit Online

Este artículo le ayudará a empezar a usar Xamarin. Android para desarrollar aplicaciones para Android 6,0
Marshmallow.
En este artículo se proporciona un esquema de las nuevas características de Android 6,0 Marshmallow, se explica
cómo preparar Xamarin. Android para el desarrollo de Android Marshmallow y se proporcionan vínculos a
aplicaciones de ejemplo que muestran cómo hacer uso de las nuevas Marshmallow de Android características de
las aplicaciones de Xamarin. Android.

Información general
Android 6,0 Marshmallow, es la próxima versión principal de Android después de un círculo de Android. Xamarin.
Android es compatible con Android Marshmallow e incluye:
Enlaces de API 23/Android 6,0 – Android 6,0 agrega muchas API nuevas para las nuevas características que
se describen a continuación; estas API están disponibles para las aplicaciones de Xamarin. Android cuando el
destino es el nivel de API 23. Para obtener más información sobre las API de Android 6,0, consulte API de
android 6,0.

Aunque la versión de marshmallow se centra principalmente en "polaco y calidad", también proporciona muchas
características nuevas de interés para los desarrolladores de Xamarin. Android. Entre ellas se incluyen:
Permisos de tiempo de ejecución – Esta mejora permite a los usuarios aprobar los permisos de
seguridad en el tiempo de ejecución.
Mejoras de autenticación A partir de Android Marshmallow, las aplicaciones pueden usar ahora sensores
de huellas digitales para autenticar a los usuarios, y una nueva característica confirmar credenciales
minimiza la necesidad de escribir contraseñas. –
Vinculación de aplicaciones Esta característica ayuda a eliminar la necesidad de hacer que el selector de
aplicaciones se abra mediante la Asociación automática de aplicaciones con dominios Web. –
Recurso compartido directo Puede definir destinos directos de recursos compartidos que hacen que el
uso compartido sea rápido e intuitivo para los usuarios; esta característica permite a UERs compartir
contenido con otras aplicaciones. –
Interacciones de voz – Esta nueva API le permite crear características de voz de conversación en la
aplicación.
modo de presentación de 4k – En Android Marshmallow, la aplicación puede solicitar una resolución de
pantalla de 4k en el hardware que lo admita.
Nuevas características de audio – A partir de marshmallow, Android ahora es compatible con el
protocolo MIDI. También proporciona nuevas clases para crear objetos de captura y reproducción de audio
digital, y ofrece nuevos enlaces de API para asociar dispositivos de audio y de entrada.
Nuevas características de vídeo – Marshmallow proporciona una nueva clase que ayuda a las
aplicaciones a representar secuencias de audio y vídeo en sincronización; esta clase también proporciona
compatibilidad con la velocidad de reproducción dinámica.
Android for work – Marshmallow incluye controles mejorados para dispositivos de usuario único
corporativos. Admite la instalación silenciosa y desinstalación de aplicaciones por parte del propietario del
dispositivo, la aceptación automática de las actualizaciones del sistema, la administración mejorada de
certificados, el seguimiento del uso de datos, la administración de permisos y las notificaciones de estado
del trabajo.
Biblioteca de compatibilidad de diseño de materiales La nueva biblioteca de soporte técnico de diseño
proporciona componentes y patrones de diseño que facilitan la compilación de la apariencia y el
funcionamiento del diseño de material en la aplicación. –
Además, muchas de las actualizaciones principales de la biblioteca de Android se lanzaron con Android M, y estas
actualizaciones proporcionan nuevas características para Android M y versiones anteriores de Android.
Además, muchas de las actualizaciones principales de la biblioteca de Android se lanzaron con Android
Marshmallow y estas actualizaciones proporcionan nuevas características para Android Marshmallow y versiones
anteriores de Android. En este artículo se explica cómo empezar a compilar aplicaciones con Android
Marshmallow y se proporciona información general sobre las nuevas características destacadas en Android 6,0.

Requisitos
Para usar las nuevas características de Android Marshmallow en aplicaciones basadas en Xamarin, se requiere lo
siguiente:
Xamarin. Android – Xamarin. Android 5.1.7.12 o posterior debe estar instalado y configurado con Visual
Studio o Xamarin Studio.
Visual Studio para Mac o Visual Studio – si usa Visual Studio para Mac, se requiere la versión 5.9.7.22 o
posterior. Si usa Visual Studio, se requiere la versión 3.11.1537 o posterior de las herramientas de Xamarin
para Visual Studio.
Android SDK – Android SDK 6,0 (API 23) o posterior debe instalarse a través del administrador de
Android SDK.
Kit para desarrolladores de Java Xamarin. Android requiere JDK 1,8 o posterior si está desarrollando
para el nivel de API 24 o superior (JDK 1,8 también admite los niveles de API anteriores a 24, incluido
Marshmallow ). – Se requiere la versión de 64 bits de JDK 1,8 Si usa controles personalizados o la vista
previa de formularios.
Puede seguir usando JDK 1,7 si está desarrollando específicamente para el nivel de API 23 o una versión anterior.

Introducción
Para empezar a usar Android Marshmallow con Xamarin. Android, debe descargar e instalar las herramientas y los
paquetes de SDK más recientes antes de poder crear un proyecto de marshmallow de Android:
1. Instale las últimas actualizaciones de Xamarin desde el canal estable .
2. Instale los paquetes y las herramientas del SDK de Android 6,0 Marshmallow.
3. Cree un nuevo proyecto de Xamarin. Android que tenga como destino Android 6,0 Marshmallow (nivel de
API 23).
4. Configurar un emulador o un dispositivo para Android Marshmallow.
En las secciones siguientes se explica cada uno de estos pasos:
Instalación de actualizaciones de Xamarin
Para actualizar Xamarin para que incluya compatibilidad con Android 6,0 Marshmallow, cambie el canal de
actualización a estable e instale todas las actualizaciones. Para obtener más información sobre la instalación de
actualizaciones desde el canal de actualizaciones, consulte cambiar el canal de actualizaciones.
Instalación del SDK de Android 6,0
Para crear un proyecto de Xamarin. Android para Android Marshmallow, primero debe usar el administrador de
Android SDK para instalar el SDK de Android 6,0:
Inicie el administrador de Android SDK (en Visual Studio para Mac, use herramientas > SDK Manager;
en Visual Studio, use herramientas > Android > Android SDK Manager) e instale el Android SDK Tools
más reciente:

Además, instale los paquetes de SDK de Android 6,0 más recientes:

Debe instalar Android SDK Tools revisión 24.3.4 o posterior. Para obtener más información sobre cómo usar el
administrador de Android SDK para instalar el SDK de Android 6,0, consulte SDK Manager.
Iniciar un proyecto de Xamarin. Android
Cree un nuevo proyecto de Xamarin. Android. Si no está familiarizado con el desarrollo de Android con Xamarin,
consulte Hello, Android para obtener información sobre la creación de proyectos de Android.
Al crear un proyecto de Android, debe configurar las opciones de versión para que tengan como destino Android
6,0 MarshMallow. Para dirigirse al proyecto para Marshmallow, debe configurar el proyecto para el nivel de API
23 (compatibilidad con Xamarin. Android v 6.0) . Para más información sobre la configuración de niveles de
nivel de API de Android, consulte Descripción de los niveles de API de Android.
Configurar un emulador o un dispositivo
Si usa un emulador, inicie Android AVD Manager y cree un nuevo dispositivo con la siguiente configuración:
Dispositivo: Nexus 5, 6 o 9.
Destino: Android 6,0-nivel de API 23
ABI: x86
Por ejemplo, este dispositivo virtual está configurado para emular un nexo 5:

Si usa un dispositivo físico como un nexo 5, 6 o 9, puede instalar una imagen de vista previa de Android
Marshmallow. Para obtener más información sobre cómo actualizar el dispositivo a Android Marshmallow,
consulte imágenes del sistema de hardware.

Características nuevas
Muchos de los cambios introducidos en Android Marshmallow se centran en mejorar la experiencia del usuario de
Android, el aumento del rendimiento y la corrección de errores. Sin embargo, Marshmallow también presentó
algunos cambios importantes en los aspectos básicos de la plataforma Android. En las secciones siguientes se
resaltan estas mejoras y se proporcionan vínculos para ayudarle a empezar a usar las nuevas características de
Android Marshmallow en su aplicación.
Permisos de tiempo de ejecución
El sistema de permisos de Android se ha optimizado y simplificado significativamente desde el círculo de Android.
En Android Marshmallow, los usuarios conceden permisos en cada caso en tiempo de ejecución en lugar de en el
momento de la instalación. Para admitir esta característica en Android Marshmallow y versiones posteriores,
diseñe la aplicación para que solicite permisos al usuario en tiempo de ejecución (en el contexto en el que se
necesitan los permisos). Este cambio facilita que los usuarios empiecen a usar la aplicación inmediatamente, ya que
simplifica el proceso de instalación y actualización de la aplicación.
Consulte solicitar permisos en tiempo de ejecución en Android Marshmallow para más información (incluidos
ejemplos de código) sobre la implementación de permisos en tiempo de ejecución en aplicaciones de Xamarin.
Android. Xamarin también proporciona una aplicación de ejemplo que muestra cómo funcionan los permisos en
tiempo de ejecución en Android Marshmallow (y versiones posteriores): RuntimePermissions.
En esta aplicación de ejemplo se muestra lo siguiente:
Cómo comprobar y solicitar permisos en tiempo de ejecución.
Cómo declarar permisos para dispositivos Android M.
Para usar esta aplicación de ejemplo:
1. Puntee en los botones cámara o contactos para mostrar un cuadro de diálogo de solicitud de permisos.
2. Conceder permiso para ver fragmentos de cámara o contactos.
Para obtener más información sobre las nuevas características de permisos en tiempo de ejecución en Android
Marshmallow, consulte trabajar con permisos del sistema.
Mejoras de autenticación
Android Marshmallow incluye dos mejoras de autenticación que ayudan a eliminar la necesidad de contraseñas:
Autenticación mediante huella digital – Usa un examen de huellas digitales para autenticar a los
usuarios.
Confirmar credencial – Autentica a los usuarios en función del tiempo que se ha desbloqueado el
dispositivo.
Los vínculos y las aplicaciones de ejemplo que se describen a continuación pueden ayudarle a familiarizarse con
estas nuevas características.
Autenticación de huella digital
En los dispositivos que admiten hardware de análisis de huellas digitales, FingerPrintManager puede usar la nueva
clase para autenticar a un usuario. Para obtener más información sobre la característica de autenticación mediante
huellas digitales en Android Marshmallow, consulte autenticación mediante huellas digitales.
Xamarin proporciona una aplicación de ejemplo que muestra cómo usar huellas digitales registradas para
autenticar a un usuario en la aplicación: FingerprintDialog.
Para usar esta aplicación de ejemplo:
1. Pulse el botón comprar para abrir un cuadro de diálogo de autenticación mediante huellas digitales.
2. Digitalice la huella digital registrada para autenticarse.
Tenga en cuenta que esta aplicación de ejemplo requiere un dispositivo con un lector de huellas digitales. Esta
aplicación no almacena la huella digital (o la contraseña).
Interacciones de voz
La nueva característica de interacciones de voz introducida en Android Marshmallow permite a los usuarios de la
aplicación usar su voz para confirmar acciones y seleccionar en una lista de opciones. Para obtener más
información sobre las interacciones de voz, consulte información general de la API de interacción de voz.
Consulte incorporación de una conversación a la aplicación Android con interacciones de voz para más
información (incluidos ejemplos de código) sobre cómo implementar interacciones de voz en aplicaciones de
Xamarin. Android. Hay disponible una aplicación de ejemplo que muestra cómo usar la API de interacción de voz
en una aplicación de Xamarin. Android: Interacciones de voz.
Confirmar credencial
Con la nueva característica de confirmación de credenciales de Android Marshmallow, puede dejar que los
usuarios tengan que recordar y especificar contraseñas específicas de la aplicación mediante su autenticación en
función del tiempo que se ha desbloqueado su dispositivo. Para ello, use el nuevo
SetUserAuthenticationValidityDurationSeconds método KeyGenerator de. Use el KeyGuardManager método
CreateConfirmDeviceCredentialIntent de para volver a autenticar al usuario desde dentro de la aplicación. Para
obtener más información sobre esta nueva característica en Android Marshmallow, vea CONFIRM Credential.
Xamarin proporciona una aplicación de ejemplo que muestra cómo usar las credenciales del dispositivo (como
PIN, patrón o contraseña) en la aplicación: ConfirmCredential
Para usar esta aplicación de ejemplo:
1. Configurar una pantalla de bloqueo segura en el dispositivo (protección > seguridad > Screenlock).
2. Puntee en el botón comprar y confirme las credenciales de la pantalla de bloqueo seguro.
Pestañas personalizadas de Chrome
Los desarrolladores de aplicaciones se encuentran en una opción cuando un usuario pulsa una dirección URL: la
aplicación puede iniciar un explorador o usar un explorador en la WebView aplicación basado en un. Ambas
opciones presentan desafíos – que inician el explorador es un cambio de contexto intensivo que no se WebView
pueden personalizar, mientras que s no comparten el estado con el explorador. Además, el uso WebView de s puede
Agregar una sobrecarga de mantenimiento adicional.
Las pestañas personalizadas de Chrome permiten mostrar fácilmente sitios web con el potencial de Chrome sin
que los usuarios salgan de la aplicación. Esta característica ofrece a la aplicación más control sobre la experiencia
web del usuario. hace que las transiciones entre el contenido nativo y web sean más fluidas sin tener WebView que
recurrir a un. La aplicación también puede afectar a la apariencia y el aspecto de Chrome personalizando lo
siguiente:
Color de la barra de herramientas
Entrar y salir de animaciones
Acciones personalizadas en la barra de herramientas de Chrome y en el menú de desbordamiento
Preinicio y captura previa de Chrome (para una carga más rápida)
Para aprovechar esta característica en la aplicación de Xamarin. Android, descargue e instale la biblioteca de
pestañas personalizadas de compatibilidad con Android. Para obtener más información sobre esta característica,
consulte pestañas personalizadas de Chrome.
Biblioteca de compatibilidad de diseño de materiales
El círculo de Android presentó el diseño de material como un nuevo lenguaje de diseño para actualizar la
experiencia de Android (consulte el tema material para obtener información sobre cómo usar el diseño de material
en las aplicaciones de Xamarin. Android). Con Android Marshmallow, Google presentó la biblioteca de
compatibilidad de diseño de Android para facilitar a los desarrolladores de aplicaciones la adopción de la
apariencia y el funcionamiento del diseño del material. Esta biblioteca incluye los componentes siguientes:
CoordinatorLayout El nuevo CoordinatorLayout widget es similar a, FrameLayout pero más eficaz que. –
Puede usar CoordinatorLayout como contenedor para vistas secundarias o como un diseño de nivel
superior, y proporciona un layout_anchor atributo que se puede usar para delimitar vistas en relación con
otras vistas.
Contraer barras de herramientas La nueva CollapsingToolbarLayout es una barra de la aplicación que se
contrae que es un contenedor para Toolbar . – (Tenga en cuenta que la barra de la aplicación es lo que antes
se conocía como la barra de acciones).
Botón de acción flotante – Un botón redondo que denota la acción principal en la interfaz de la
aplicación.
Etiquetas flotantes para editar texto Usa un TextInputLayout nuevo EditText widget (que se ajusta)
para mostrar una etiqueta flotante cuando se oculta una sugerencia cuando un usuario escribe texto. –
Vista de navegación – El nuevo NavigationView widget le ayuda a usar el cajón de navegación de una
manera más fácil de navegar por los usuarios.
Snackbar – El nuevo SnackBar widget es un mecanismo de comentarios ligeros (similar a una notificación
del sistema) que muestra un mensaje breve en la parte inferior de la pantalla, que aparece encima de los
demás elementos de la pantalla.
Pestañas de material – El nuevo TabLayout widget proporciona un diseño horizontal para mostrar las
pestañas como forma de implementar la navegación de nivel superior en la aplicación.
Para beneficiarse de la biblioteca de soporte técnico de diseño de la aplicación de Xamarin. Android, descargue e
instale el paquete NuGet de diseño de la biblioteca de compatibilidad de Xamarin Xamarin.
Vea el bonito diseño de material con la biblioteca de diseño de compatibilidad con Android para más información
(incluidos ejemplos de código) sobre el uso de la biblioteca de compatibilidad de diseño de materiales en
aplicaciones de Xamarin. Android. Xamarin proporciona una aplicación de ejemplo que muestra una demostración
de la nueva biblioteca de diseño de – Android en Xamarin. Android Cheesesquare. Este ejemplo muestra las
siguientes características de la biblioteca de diseño:
Barra de herramientas contraer
Botón de acción flotante
Ver delimitación
NavigationView
Snackbar
Para obtener más información sobre la biblioteca de diseño, vea biblioteca de compatibilidad de diseño de Android
en el blog del desarrollador de Android.
Actualizaciones adicionales de la biblioteca
Además de Android Marshmallow, Google ha anunciado actualizaciones relacionadas con varias bibliotecas
básicas de Android. Xamarin proporciona compatibilidad con Xamarin. Android para estas actualizaciones a través
de varios paquetes de NuGet de versión preliminar:
Google Play Services La versión más reciente de Google Play Services incluye la nueva característica de
invitaciones de aplicación, que permite a los usuarios compartir su aplicación con amigos. – Para obtener
más información sobre esta característica, vea el apartado sobre cómo ampliar el alcance de su aplicación
con los invitados de la aplicación de Google.
Bibliotecas de compatibilidad con Android – Estos paquetes Nuget ofrecen características que solo están
disponibles para las API de biblioteca al mismo tiempo que proporcionan versiones compatibles con
versiones anteriores de las API de Android Framework.
Biblioteca portátil de Android – este NuGet incluye enlaces de Google Play Services. La versión más
reciente de la biblioteca portátil aporta nuevas características (incluida una navegación más sencilla para
aplicaciones personalizadas) a la plataforma de desgaste de Android.

Resumen
En este artículo se presentaron Android Marshmallow y se explicó cómo instalar y configurar las herramientas y
los paquetes más recientes para el desarrollo de Xamarin. Android en Marshmallow. También se proporciona
información general sobre las nuevas características de Android Marshmallow para el desarrollo de Xamarin.
Android.

Vínculos relacionados
Android 6,0 Marshmallow
Obtener la Android SDK
Información general sobre características
Notas de la versión
RuntimePermissions (ejemplo)
ConfirmCredential (ejemplo)
FingerprintDialog (ejemplo)
Características de los círculos
16/08/2019 • 46 minutes to read • Edit Online

En este artículo se proporciona información general de alto nivel sobre las nuevas características introducidas en
Android 5,0 (Lollipop ). Estas características incluyen un nuevo estilo de interfaz de usuario denominado "tema de
material", así como nuevas características auxiliares, como animaciones, ver sombras y matices Dibujables.
Android 5,0 también incluye notificaciones mejoradas, dos nuevos widgets de interfaz de usuario, un nuevo
programador de trabajos y una serie de nuevas API para mejorar las capacidades de almacenamiento, redes,
conectividad y multimedia.

Información general sobre el círculo


Android 5,0 (Lollipop) incorpora un nuevo lenguaje de diseño, diseño del materialy, además, ofrece una
conversión de nuevas características para que las aplicaciones sean más fáciles y más intuitivas de usar. Con el
diseño de material, Android 5,0 no solo ofrece teléfonos Android a Facelift; también proporciona un nuevo
conjunto de reglas de diseño para tabletas basadas en Android, equipos de escritorio, relojes y televisores
inteligentes. Estas reglas de diseño resaltan la simplicidad y el mínimo a la vez que usan atributos táctiles
familiares (como las señales de borde y de superficie realistas) para ayudar a los usuarios a comprender la
interfaz de forma rápida e intuitiva.
El tema material es el encarnación de estos principios de diseño de la interfaz de usuario en Android. En este
artículo se explican las características auxiliares del tema de material:
Animaciones Animaciones de comentarios táctiles, animaciones de transición de actividad, animaciones
de transición de estado de vista y un efecto de revelar. –
Ver sombras y elevación Las vistas ahora tienen elevation una propiedad; – las vistas con elevation
valores mayores proyectan sombras mayores en el fondo.
Características de color El tinte que se puede dibujar permite volver a usar los recursos de imagen
cambiando su color, y la extracción de color prominente le ayuda a hacer tema de forma dinámica a la
aplicación en función de los colores de una imagen. –
Muchas características del tema material ya están integradas en la experiencia de interfaz de usuario de Android
5,0, mientras que otras deben agregarse explícitamente a las aplicaciones. Por ejemplo, algunas vistas estándar
(como los botones) ya incluyen animaciones de comentarios táctiles, mientras que las aplicaciones deben
habilitar la mayoría de las sombras de la vista.
Además de las mejoras de la interfaz de usuario que se han incorporado a través del tema material, Android 5,0
también incluye otras características nuevas que se describen en este artículo:
Notificaciones mejoradas Las notificaciones en Android 5,0 se han actualizado de forma significativa
con un nuevo aspecto, compatibilidad con las notificaciones de la pantalla de bloqueo y un nuevo formato
de presentación de notificaciones emergentes. –
Widgets de interfaz de usuario nuevos El nuevo RecyclerView widget facilita a las aplicaciones la
transmisión de grandes conjuntos de datos y la información compleja, y CardView el nuevo widget
proporciona un formato de presentación de tipo tarjeta simplificado para mostrar texto e imágenes. –
Nuevas API – Android 5,0 agrega nuevas API para la compatibilidad con varias redes, conectividad
Bluetooth mejorada, administración de almacenamiento más sencilla y un control más flexible de los
reproductores multimedia y los dispositivos de cámara. Hay disponible una nueva característica de
programación de trabajos para ejecutar tareas de forma asincrónica a horas programadas. Esta
característica ayuda a mejorar la duración de la batería, por ejemplo, la programación de tareas que se
deben realizar cuando el dispositivo está conectado y cargándose.

Requisitos
Para usar las nuevas características de Android 5,0 en aplicaciones basadas en Xamarin, se requiere lo siguiente:
Xamarin. Android – Xamarin. Android 4,20 o posterior debe estar instalado y configurado con Visual
Studio o Visual Studio para Mac.
Android SDK – Android 5,0 (API 21) o posterior debe instalarse a través del administrador de Android
SDK.
Kit para desarrolladores de Java Xamarin. Android requiere JDK 1,8 o posterior si está desarrollando
para el nivel de API 24 o superior (JDK 1,8 también admite niveles de API anteriores a 24, incluido el
círculo). – Se requiere la versión de 64 bits de JDK 1,8 Si usa controles personalizados o la vista previa de
formularios.
Puede seguir usando JDK 1,7 si está desarrollando específicamente para el nivel de API 23 o una versión
anterior.

Configuración de un proyecto de Android 5,0


Para crear un proyecto de Android 5,0, debe instalar las herramientas y los paquetes de SDK más recientes. Siga
estos pasos para configurar un proyecto de Xamarin. Android que tenga como destino Android 5,0:
1. Instale las herramientas de Xamarin. Android y active la licencia de Xamarin. Consulte configuración e
instalación para obtener más información sobre la instalación de Xamarin. Android.
2. Si usa Visual Studio para Mac, instale las últimas actualizaciones de Android 5,0.
3. Inicie el administrador de Android SDK (en Visual Studio para Mac, use > herramientas abrir Android
SDK…Manager) e instale Android SDK Tools 23.0.5 o posterior:

Además, instale los paquetes de SDK de Android 5,0 más recientes (API 21 o posterior):

Para obtener más información acerca del uso del administrador de Android SDK, consulte SDK Manager.
4. Cree un nuevo proyecto de Xamarin. Android. Si no está familiarizado con el desarrollo de Android con
Xamarin, consulte Hello, Android para obtener información sobre la creación de proyectos de Android.
Cuando cree un proyecto de Android, asegúrese de configurar las opciones de versión para Android 5,0.
En Visual Studio para Mac, vaya a opciones > de proyecto > generar general y establezca plataforma
de destino en Android 5,0 (Lollipop) o posterior:
En opciones > de proyecto > compilar aplicación de Android, establecer versión de Android mínima
y de destino en la versión de .NET Framework de destino de uso automático:

5. Configure un emulador o un dispositivo Android para probar la aplicación. Si usa un emulador, consulte
Android Emulator configuración para obtener información sobre cómo configurar un emulador de
Android para su uso con Xamarin Studio o Visual Studio. Si usa un dispositivo Android, consulte
configuración del SDK de versión preliminar para obtener información sobre cómo actualizar el
dispositivo para Android 5,0. Para configurar el dispositivo Android para ejecutar y depurar aplicaciones
de Xamarin. Android, consulte configurar el dispositivo para el desarrollo.
Nota: Si va a actualizar un proyecto de Android existente que tenía como destino la versión preliminar de
Android, debe actualizar la versión de .NET Framework de destino y Android a los valores descritos
anteriormente.

Cambios importantes
Las aplicaciones Android publicadas anteriormente podrían verse afectadas por los cambios en Android 5,0. En
concreto, Android 5,0 usa un nuevo tiempo de ejecución y un formato de notificación que cambia
significativamente.
Tiempo de ejecución de Android
Android 5,0 usa el nuevo tiempo de ejecución de Android (ART) como el tiempo de ejecución predeterminado en
lugar de Dalvik. ART implementa varias características principales nuevas:
Compilación de antemano del tiempo (AOT) – AOT puede mejorar el rendimiento de las aplicaciones
compilando el código de la aplicación antes de que se inicie la aplicación por primera vez. Cuando se
instala una aplicación, el arte genera un archivo ejecutable de aplicación compilada para el dispositivo de
destino.
Recolección de elementos no utilizados mejorada (GC ) – Las mejoras de GC en arte también
pueden mejorar el rendimiento de las aplicaciones. La recolección de elementos no utilizados ahora usa
una pausa de GC en lugar de dos, y las operaciones de GC simultáneas se completan de manera más
oportuna.
Depuración de aplicaciones mejorada – Art proporciona más detalles de diagnóstico para ayudar a
analizar excepciones e informes de bloqueo.
Las aplicaciones existentes deberían funcionar sin cambios en – el material gráfico, excepto para las aplicaciones
que aprovechan técnicas únicas del tiempo de ejecución de Dalvik anterior, que puede que no funcionen en arte.
Para obtener más información sobre estos cambios, consulte comprobar el comportamiento de la aplicación en
el tiempo de ejecución de Android (arte).
Cambios de notificación
Las notificaciones han cambiado significativamente en Android 5,0:
Los sonidos y las vibraciones se tratan de forma diferente Ringtone Notification.Builder Vibrator
MediaPlayer Ahora se administran los sonidos y las vibraciones en lugar de, y. –
Nueva combinación de colores – De acuerdo con el tema material, las notificaciones se representan
con texto oscuro sobre el fondo blanco o muy ligero. Además, Android puede modificar los canales alfa en
los iconos de notificación para que se coordinen con las combinaciones de colores del sistema.
Notificaciones de la pantalla de bloqueo – Las notificaciones ahora pueden aparecer en la pantalla de
bloqueo del dispositivo.
Cabezas – Las notificaciones de prioridad alta ahora aparecen en una pequeña ventana flotante
(notificación de cierre) cuando el dispositivo está desbloqueado y la pantalla está activada.

En la mayoría de los casos, la migración de la funcionalidad de notificación de aplicación existente a Android 5,0
requiere los pasos siguientes:
1. Convierta el código para Notification.Builder usar ( NotificationsCompat.Builder o) para crear
notificaciones.
2. Compruebe que los recursos de notificación existentes estén visibles en la nueva combinación de colores
del tema del material.
3. Decida qué visibilidad deben tener las notificaciones cuando se presentan en la pantalla de bloqueo. Si
una notificación no es pública, ¿qué contenido debe aparecer en la pantalla de bloqueo?
4. Establezca la categoría de las notificaciones para que se controlen correctamente en el nuevo modo
Android 5,0 no molestar.
Si las notificaciones presentan controles de transporte, muestran el estado de reproducción RemoteControlClient
multimedia, el ActivityManager.GetRecentTasks uso o la llamada, consulte cambios importantes en el
comportamiento para obtener más información sobre cómo actualizar las notificaciones para Android 5,0.
Para obtener información sobre cómo crear notificaciones en Android, consulte notificaciones locales.

Tema de materiales
El nuevo tema material de Android 5,0 aporta cambios en la apariencia de la interfaz de usuario de Android. Los
elementos visuales ahora usan superficies táctiles que toman los gráficos en negrita, la tipografía y los colores
brillantes del diseño basado en la impresión. Los ejemplos de temas de material se representan en las siguientes
capturas de pantallas:
Android 5,0 le muestra la pantalla principal que aparece a la izquierda. La captura de pantalla de Center es la
primera pantalla de la lista de aplicaciones y la captura de pantalla de la derecha es la pantalla de configuración
. La especificación de diseño de material de Google explica las reglas de diseño subyacentes en el nuevo
concepto de tema de materiales.
El tema material incluye tres tipos integrados que puede usar en la aplicación: el Theme.Material tema oscuro (el
valor predeterminado), el Theme.Material.Light tema y el Theme.Material.Light.DarkActionBar tema:

Para obtener más información sobre el uso de las características del tema material en las aplicaciones de
Xamarin. Android, consulte el tema material.

Animaciones
Android 5,0 proporciona animaciones de comentarios táctiles, animaciones de transición de actividad y
animaciones de transición de estado de vista para que las interfaces de aplicaciones sean más intuitivas de usar.
Además, las aplicaciones de Android 5,0 pueden usar animaciones de efecto de visualización para ocultar o
mostrar vistas. Puede usar la configuración de movimiento curvado para configurar el modo en que se
representan las animaciones rápidamente o lentas.
Animaciones de comentarios táctiles
Las animaciones de comentarios táctiles proporcionan a los usuarios comentarios visuales cuando se toca una
vista. Por ejemplo, los botones ahora muestran un efecto de rizo cuando se – tocan esta es la animación de
comentarios táctiles predeterminada en Android 5,0. La nueva RippleDrawable clase implementa la animación
Ripple. El efecto de rizo puede configurarse para que termine en los límites de la vista o se extienda más allá de
los límites de la vista. Por ejemplo, la siguiente secuencia de capturas de pantalla muestra el efecto de rizo en un
botón durante la animación táctil:

El contacto táctil inicial con el botón aparece en la primera imagen de la izquierda, mientras que la secuencia
restante (de izquierda a derecha) muestra cómo se distribuye el efecto de rizo al borde del botón. Cuando finaliza
la animación Ripple, la vista vuelve a su apariencia original. La animación de rizo predeterminada tiene lugar en
una fracción de segundo, pero la longitud de la animación se puede personalizar para una longitud de tiempo
mayor o menor.
Para obtener más información sobre animaciones de comentarios táctiles en Android 5,0, consulte
Personalización de comentarios táctiles.
Animaciones de transición de actividad
Las animaciones de transición de actividad proporcionan a los usuarios una sensación de continuidad visual
cuando una actividad realiza una transición a otra. Las aplicaciones pueden especificar tres tipos de animaciones
de transición:
Escribir transición – Cuando una actividad entra en la escena.
Transición de salida – Para cuando una actividad sale de la escena.
Transición de elementos compartidos – Para cuando una vista que es común a dos actividades cambia a
medida que la primera actividad pasa al siguiente.
Por ejemplo, la siguiente secuencia de capturas de pantallas muestra una transición de elementos compartidos:

Un elemento compartido (una fotografía de un Caterpillar) es una de las diversas vistas de la primera actividad;
se amplía para convertirse en la única vista de la segunda actividad a medida que la primera actividad pasa al
segundo.
Escribir tipos de animación de transición
En el caso de las transiciones de entrada, Android 5,0 proporciona tres tipos de animaciones:
Expandir animación – Amplía una vista desde el centro de la escena.
Animación de diapositivas – Mueve una vista de uno de los bordes de una escena.
Animación de atenuación – Atenúa una vista en la escena.
Tipos de animación de transición de salida
En el caso de las transiciones de salida, Android 5,0 proporciona tres tipos de animaciones:
Expandir animación – Reduce una vista al centro de la escena.
Animación de diapositivas – Mueve una vista a uno de los bordes de una escena.
Animación de atenuación – Atenúa una vista fuera de la escena.
Tipos de animación de transición de elementos compartidos
Las transiciones de elementos compartidas admiten varios tipos de animaciones, como:
Cambiar los límites de diseño o recorte de una vista.
Cambiar la escala y la rotación de una vista.
Cambiar el tamaño y el tipo de escala de una vista.
Para más información sobre las animaciones de transición de actividad en Android 5,0, consulte Personalización
de las transiciones de actividad.
Ver animaciones de transición de estado
Android 5,0 permite que las animaciones se ejecuten cuando cambia el estado de una vista. Puede animar las
transiciones de estado de vista mediante una de las técnicas siguientes:
Cree drawables que animen los cambios de estado asociados a una vista determinada. La nueva
AnimatedStateListDrawable clase permite crear drawables que muestran animaciones entre los cambios
del estado de vista.
Definir la funcionalidad de animación que se ejecuta cuando cambia el estado de una vista. La nueva
StateListAnimator clase permite definir un animador que se ejecuta cuando cambia el estado de una
vista.
Para más información sobre las animaciones de transición de estado de vista en Android 5,0, consulte animar los
cambios de estado de vista.
Mostrar efecto
El efecto revelar es un círculo de recorte que cambia el radio para mostrar u ocultar una vista. Puede controlar
este efecto estableciendo el radio inicial y final del círculo de recorte. La siguiente secuencia de capturas de
pantalla muestra una animación de efecto de visualización desde el centro de la pantalla:

La secuencia siguiente muestra una animación de efecto de visualización que tiene lugar desde la esquina
inferior izquierda de la pantalla:
Se pueden invertir animaciones de visualización. es decir, el círculo de recorte puede reducirse para ocultar la
vista en lugar de ampliarla para mostrar la vista.
Para obtener más información sobre el efecto de revelar de Android 5,0 en, consulte usar el efecto de revelar.
Movimiento curvo
Además de estas características de animación, Android 5,0 también proporciona nuevas API que le permiten
especificar las curvas de tiempo y movimiento de animaciones. Android 5,0 usa estas curvas para interpolar el
movimiento temporal y espacial durante las animaciones. Se definen tres curvas en Android 5,0:
Fast_out_linealen_ acelera– rápidamente y continúa acelerando hasta el final de la animación.
La velocidad_de_salida rápida rápida_y lenta se ralentiza rápidamente y lentamente hacia el final de la
animación. –
La tecnología_linealde_baja velocidad comienza con una velocidad máxima y ralentiza
lentamente hasta el final de la animación._ –
Puede usar la nueva PathInterpolator clase para especificar cómo se realiza la interpolación de movimiento.
PathInterpolator es un interpolador que atraviesa las rutas de animación según los puntos de control y las
curvas de movimiento especificados. Para obtener más información sobre cómo especificar la configuración de
movimiento curvado en Android 5,0, consulte usar movimiento curvo.

Ver sombras & elevación


En Android 5,0, puede especificar la elevación de una vista mediante el establecimiento de una Z nueva
propiedad. Un valor Z mayor hace que la vista convierta una sombra más grande en segundo plano, lo que
hace que la vista parezca más flotante encima del fondo. Puede establecer la elevación inicial de una vista
configurando su elevation atributo en el diseño.
En el ejemplo siguiente se muestran las sombras convertidas por TextView un control vacío cuando su atributo
de elevación está establecido en 2DP, 4DP y 6DP, respectivamente:

La configuración de sombra de vista puede ser estática (como se mostró anteriormente) o se puede usar en
animaciones para que aparezca una vista que se encuentra por encima del fondo de la vista. Puede utilizar la
ViewPropertyAnimator clase para animar la elevación de una vista. La elevación de una vista es la suma de su
configuración elevation de diseño más translationZ una propiedad que se puede establecer a
ViewPropertyAnimator través de una llamada al método.

Para obtener más información sobre cómo ver las sombras en Android 5,0, consulte definir sombras y vistasde
recorte.

Características de color
Android 5,0 proporciona dos nuevas características para administrar el color de las aplicaciones:
La tinción dibujable permite modificar los colores de los recursos de imagen mediante el cambio de un
atributo de diseño.
La extracción de color prominente permite personalizar dinámicamente el tema de color de la aplicación
para que se coordine con la paleta de colores de una imagen mostrada.
Tinción dibujable
Los diseños de Android 5,0 reconocen un tint nuevo atributo que puede usar para establecer el color de
drawables sin tener que crear varias versiones de estos recursos para mostrar distintos colores. Para usar esta
característica, debe definir un mapa de bits como una máscara alfa y tint usar el atributo para definir el color
del recurso. Esto permite crear activos una vez y colorearlos en el diseño para que coincidan con el tema.
En el ejemplo siguiente, se usa un único – recurso de imagen con un logotipo blanco – con un fondo
transparente para crear variaciones de matiz:

Este logotipo se muestra sobre un fondo circular azul, tal como se muestra en los ejemplos siguientes. La imagen
de la izquierda es la forma en que aparece el tint logotipo sin una configuración. En la imagen central, el
atributo del tint logotipo se establece en un gris oscuro. En la imagen de la derecha, tint se establece en gris
claro:

Para obtener más información sobre la tinción dibujable en Android 5,0, consulte creaciónde matices Dibujables.
Extracción de color prominente
La nueva clase de Palette Android 5,0 le permite extraer colores de una imagen para que pueda aplicarlos
dinámicamente a una paleta de colores personalizada. La Palette clase extrae seis colores de una imagen y
etiqueta estos colores según sus niveles relativos de saturación de color y brillo:
Pantallas
Vibrante oscuro
Luz vibrante
Silenciada
Silenciado oscuro
Luz silenciada
Por ejemplo, en las siguientes capturas de pantalla, una aplicación de visualización de fotografías extrae los
colores destacados de la imagen en la pantalla y usa estos colores para adaptar la combinación de colores de la
aplicación para que coincida con la imagen:
En las capturas de pantallas anteriores, la barra de acción se establece en el color "vibrante claro" extraído y el
fondo se establece en el color "oscuro oscuro" extraído. En cada ejemplo anterior, se incluye una fila de pequeños
cuadrados de color para ilustrar los colores de la paleta que se extrajeron de la imagen.
Para más información sobre la extracción de color en Android 5,0, consulte extracción de colores destacados de
una imagen.

Widgets de interfaz de usuario nuevos


Android 5,0 presenta dos nuevos widgets de interfaz de usuario:
RecyclerView – Un grupo de vistas que muestra una lista de elementos desplazables.
CardView – Diseño básico con esquinas redondeadas.

Ambos widgets incluyen compatibilidad integrada con las características del tema de materiales; por ejemplo,
RecyclerView usa animaciones para agregar y quitar vistas, y CardView usa las sombras de la vista para que
cada tarjeta parezca flotar encima del fondo. En las siguientes capturas de pantallas se muestran ejemplos de
estos nuevos widgets:

La captura de pantalla de la izquierda es un RecyclerView ejemplo de tal como se usa en una aplicación de
correo electrónico, y la captura de CardView pantalla de la derecha es un ejemplo de tal como se usa en una
aplicación de reserva de viajes.
RecyclerView
RecyclerView es similar a ListView, , pero es más adecuado para conjuntos grandes de vistas o listas con
elementos que cambian dinámicamente. Al ListView, igual que especifica un adaptador para tener acceso al
conjunto de datos subyacente. Sin embargo, a ListView, diferencia de se usa un Administrador de diseño para
RecyclerView colocar los elementos dentro de. El administrador de diseño también se encarga del reciclaje de
vistas; administra la reutilización de las vistas de elementos que ya no son visibles para el usuario.
Cuando se usa un RecyclerView widget, debe especificar un LayoutManager y un adaptador. Como se muestra en
esta ilustración LayoutManager , es el intermediario entre el adaptador RecyclerView y:

Las siguientes capturas de RecyclerView pantallas muestran un que contiene 100 elementos (cada elemento
ImageView consta de TextView un y un):
RecyclerView controla este conjunto de datos de gran – tamaño con un desplazamiento sencillo desde el
principio de la lista hasta el final de la lista en esta aplicación de ejemplo solo tarda unos segundos. RecyclerView
también admite animaciones; de hecho, las animaciones para agregar y quitar elementos están habilitadas de
forma predeterminada. Cuando se agrega un elemento a un RecyclerView , se atenúa como se muestra en esta
secuencia de capturas de pantallas:

Para obtener más RecyclerView información sobre, vea RecyclerView.


CardView
CardView es una vista simple que simula una tarjeta flotante con esquinas redondeadas. Dado CardView que
tiene sombras de vistas integradas, proporciona una manera sencilla de agregar profundidad visual a la
aplicación. Las capturas de pantallas siguientes muestran tres ejemplos orientados a texto de CardView :
Cada una de las tarjetas del ejemplo anterior contiene un TextView ; el color de fondo se establece mediante
cardBackgroundColor el atributo.

Para obtener más CardView información acerca de, consulte CardView.

Notificaciones mejoradas
El sistema de notificación en Android 5,0 se ha actualizado significativamente con un nuevo formato visual y
nuevas características. Las notificaciones tienen una nueva apariencia en Android 5,0. Por ejemplo, las
notificaciones en Android 5,0 ahora usan texto oscuro sobre un fondo claro:

Cuando se muestra un icono grande en una notificación (como se muestra en el ejemplo anterior), Android 5,0
presenta el icono pequeño como un distintivo en el icono de gran tamaño.
En Android 5,0, las notificaciones también pueden aparecer en la pantalla de bloqueo del dispositivo. Por
ejemplo, a continuación se muestra una captura de pantalla de ejemplo de un bloqueo de pantalla con una sola
notificación:
Los usuarios pueden hacer doble punteo en una notificación en la pantalla de bloqueo para desbloquear el
dispositivo y saltar a la aplicación que originó esa notificación, o bien deslizar para descartar la notificación. Las
notificaciones tienen una nueva configuración de visibilidad que determina la cantidad de contenido que se
puede mostrar en la pantalla de bloqueo. Los usuarios pueden elegir si desea permitir que se muestre contenido
confidencial en las notificaciones de la pantalla de bloqueo.
Android 5,0 presenta un nuevo formato de presentación de notificaciones de alta prioridad denominado " Head -
up". Las notificaciones de los cabezales se desplazan hacia abajo desde la parte superior de la pantalla durante
unos segundos y, a continuación, se revierten a la sombra de la notificación en la parte superior de la pantalla.
Las notificaciones de cabezales permiten que la interfaz de usuario del sistema Coloque información importante
delante del usuario sin interrumpir la actividad que se está ejecutando actualmente. En el ejemplo siguiente se
muestra una notificación de suscripción sencilla que se muestra en la parte superior de una aplicación:

Las notificaciones de suscripción se suelen usar para los siguientes eventos:


Nuevo mensaje siguiente
Una llamada telefónica entrante
Indicación de batería baja
Una alarma
Android 5,0 solo muestra una notificación en formato de cara al día cuando tiene un valor de prioridad alto o
máximo.
En Android 5,0, puede proporcionar metadatos de notificación para ayudar a Android a ordenar y Mostrar
notificaciones de forma más inteligente. Android 5,0 organiza las notificaciones según la prioridad, la visibilidad y
la categoría. Las categorías de notificación se usan para filtrar las notificaciones que se pueden presentar cuando
el dispositivo está en modo no molesta .
Para obtener información detallada sobre la creación y el inicio de notificaciones con las últimas características
de Android 5,0, consulte notificaciones locales.

Nuevas API.
Además de las nuevas características que se han descrito anteriormente, Android 5,0 agrega nuevas API que
amplían las capacidades de la funcionalidad de multimedia, almacenamiento y conectividad inalámbrica
existente. Además, Android 5,0 incluye nuevas API que proporcionan compatibilidad con una nueva
característica de programador de trabajos.
Cámara
Android 5,0 proporciona varias API nuevas para mejorar las capacidades de la cámara. El nuevo
Android.Hardware.Camera2 espacio de nombres incluye funcionalidad para tener acceso a dispositivos de cámara
individuales conectados a un dispositivo Android. Además, Android.Hardware.Camera2 modela cada dispositivo de
cámara como una canalización: acepta una solicitud de captura, captura la imagen y, a continuación, genera el
resultado. Este enfoque permite a las aplicaciones poner en cola varias solicitudes de captura en un dispositivo
de cámara.
Las siguientes API hacen posibles estas nuevas características:
Ayuda a obtener acceso mediante programación a los dispositivos de
CameraManager.GetCameraIdList
cámara CameraManager.OpenCamera ; se usa para conectarse a un dispositivo de cámara específico. –
CameraCaptureSession – Captura o transmite imágenes desde el dispositivo de cámara. La
CameraCaptureSession.CaptureListener interfaz se implementa para controlar los nuevos eventos de
captura de imagen.
CaptureRequest – Define los parámetros de captura.
CaptureResult – Proporciona los resultados de una operación de captura de imagen.

Para obtener más información acerca de las nuevas API de cámara en Android 5,0, consulte multimedia.
Reproducción de audio
Android 5,0 actualiza la AudioTrack clase para una mejor reproducción de audio:
ENCODING_PCM_FLOAT – Configura para aceptar los datos de audio en formato de punto flotante para un
mejor intervalo dinámico, mayor espacio y mayor calidad (gracias a la mayor precisión). AudioTrack
Además, el formato de punto flotante ayuda a evitar el recorte de audio.
ByteBuffer Ahora puede proporcionar datos de audio a AudioTrack como una matriz de bytes. –
WRITE_NON_BLOCKING – Esta opción simplifica el almacenamiento en búfer y multithreading para algunas
aplicaciones.
Para obtener más AudioTrack información sobre las mejoras en Android 5,0, consulte multimedia.
Control de reproducción multimedia
Android 5,0 presenta la nueva Android.Media.MediaController clase, que reemplaza RemoteControlClient a.
Android.Media.MediaController proporciona API de control de transporte simplificado y ofrece control seguro
para subprocesos de la reproducción fuera del contexto de la interfaz de usuario. Las siguientes API nuevas
administran el control de transporte:
– Una sesión de control multimedia que controla varios
Android.Media.Session.MediaSession
controladores. Llame MediaSession.GetSessionToken a para solicitar un token que la aplicación use para
interactuar con la sesión.
MediaController.TransportControls Controla los comandos de transporte, como reproducir, detenery
omitir. –
Además, puede usar la nueva Android.App.Notification.MediaStyle clase para asociar una sesión multimedia a
un contenido de notificación enriquecido (como la extracción y visualización de carátulas de álbum).
Para obtener más información acerca de las nuevas características de control de reproducción multimedia en
Android 5,0, consulte multimedia.
Almacenamiento
Android 5,0 actualiza el marco de acceso de almacenamiento para que las aplicaciones funcionen con directorios
y documentos más fácilmente:
Para seleccionar un subárbol de directorio, puede crear y enviar un
Android.Intent.Action.OPEN_DOCUMENT_TREE intento. Esta intención hace que el sistema muestre todas las
instancias de proveedor que admiten la selección de subárbol. a continuación, el usuario examina y
selecciona un directorio.
Para crear y administrar nuevos documentos o directorios en cualquier parte de un subárbol, use los
CreateDocument nuevos RenameDocument métodos, DeleteDocument y de DocumentsContract .

Para obtener las rutas de acceso a los directorios de medios en todos los dispositivos de
Android.Content.Context.GetExternalMediaDirs almacenamiento compartido, se llama al método New.

Para más información sobre las nuevas API de almacenamiento en Android 5,0, consulte almacenamiento.
Conectividad de & inalámbrica
Android 5,0 agrega las siguientes mejoras de API para la conectividad inalámbrica y la conectividad:
Nuevas API de múltiples redes que permiten a las aplicaciones buscar y seleccionar redes con capacidades
específicas antes de establecer una conexión.
Funcionalidad de difusión de Bluetooth que permite a un dispositivo Android 5,0 actuar como periféricos
Bluetooth de bajo consumo de energía.
Mejoras de NFC que facilitan el uso de la funcionalidad de comunicaciones de campo Near para
compartir datos con otros dispositivos.
Para más información sobre las nuevas API de conectividad y redes inalámbricas en Android 5,0, consulte
conectividad inalámbrica y conectividad.
Programación de trabajos
Android 5,0 introduce una nueva JobScheduler API que puede ayudar a los usuarios a minimizar la duración de
la batería mediante la programación de determinadas tareas que se ejecutan solo cuando el dispositivo está
conectado y cargándose. Esta característica de programador de trabajos también puede usarse para programar
una tarea para que se ejecute cuando las condiciones sean más adecuadas para esa tarea, como la descarga de
un archivo grande cuando el dispositivo está conectado a través de una red Wi-Fi en lugar de una red de uso
medido.
Para más información sobre las nuevas API de programación de trabajos en Android 5,0, consulte programación
de trabajos.

Resumen
En este artículo se proporciona información general sobre las nuevas características importantes de Android 5,0
para los desarrolladores de aplicaciones de Xamarin. Android:
Tema de materiales
Animaciones
Ver sombras y elevación
Características de color, como la tinción dibujable y la extracción de color prominente
Los nuevos RecyclerView widgets y CardView

Mejoras en las notificaciones


Nuevas API para la cámara, la reproducción de audio, el control de medios, el almacenamiento, la
conectividad inalámbrica y la programación de trabajos
Si no está familiarizado con el desarrollo de Xamarin Android, lea instalación e instalación para ayudarle a
empezar a trabajar con Xamarin. Android. Hello, Android es una excelente introducción para aprender a crear
proyectos de Android.

Vínculos relacionados
Versión preliminar para desarrolladores de Android L
Obtener la Android SDK
Diseño de materiales
Principios del diseño de materiales
Características de KitKat
19/08/2019 • 43 minutes to read • Edit Online

Android 4,4 (KitKat) se carga con un Cornucopia de características para usuarios y desarrolladores. En esta guía
se resaltan varias de estas características y se proporcionan ejemplos de código y detalles de implementación para
ayudarle a sacar el máximo partido de KitKat.

Información general
Android 4,4 (nivel de API 19), también conocido como "KitKat", se publicó a finales de 2013. KitKat ofrece una
variedad de nuevas características y mejoras, entre las que se incluyen:
Experiencia del usuario – Animaciones sencillas con el marco de transición, el estado translúcido y las barras
de navegación y el modo inmersivo de pantalla completa ayudan a crear una mejor experiencia para el
usuario.
Contenido del usuario – Administración de archivos de usuario simplificada con el marco de acceso de
almacenamiento; la impresión de imágenes, sitios web y otro contenido es más fácil con las API de
impresión mejoradas.
Hardware de Convierta cualquier aplicación en una tarjeta NFC con emulación de tarjeta basada en host
NFC; ejecute sensores de baja energía con el SensorManager . –
Herramientas de desarrollo – Las aplicaciones de screencast en acción con el cliente Android Debug Bridge,
disponibles como parte de la Android SDK.
En esta guía se proporcionan instrucciones para migrar una aplicación de Xamarin. Android existente a KitKat, así
como una introducción de alto nivel de KitKat para desarrolladores de Xamarin. Android.

Requisitos
Para desarrollar aplicaciones de Xamarin. Android con KitKat, necesita Xamarin. Android 4.11.0 o superior y
Android 4,4 (nivel de API 19) instalado a través del administrador de Android SDK, como se muestra en la
siguiente captura de pantalla:
Migración de la aplicación a KitKat
En esta sección se proporcionan algunos elementos de primera respuesta para ayudar a realizar la transición de
aplicaciones existentes a Android 4,4.
Comprobar la versión del sistema
Si una aplicación debe ser compatible con versiones anteriores de Android, asegúrese de ajustar cualquier código
específico de KitKat en una comprobación de la versión del sistema, como se muestra en el ejemplo de código
siguiente:

if (Build.VERSION.SdkInt >= BuildVersionCodes.Kitkat) {


//KitKat only code here
}

Procesamiento por lotes de alarmas


Android usa servicios de alarma para reactivar una aplicación en segundo plano a una hora especificada. KitKat
realiza un paso más en el procesamiento por lotes de las alarmas para conservar la energía. Esto significa que, en
lugar de activar cada aplicación en un momento concreto, KitKat prefiere agrupar varias aplicaciones que están
registradas para reactivarse durante el mismo intervalo de tiempo y reactivarlas al mismo tiempo. Para indicar a
Android que reactive una aplicación durante un intervalo de tiempo SetWindow especificado, AlarmManager llame a
en el, pasando el tiempo mínimo y máximo, en milisegundos, que puede transcurrir antes de que se reactivarán la
aplicación y la operación que se realiza en la reactivación. El código siguiente proporciona un ejemplo de una
aplicación que debe ser reactivarán entre una media hora y una hora desde el momento en que se establece la
ventana:
AlarmManager alarmManager = (AlarmManager)GetSystemService(AlarmService);
alarmManager.SetWindow (AlarmType.Rtc, AlarmManager.IntervalHalfHour, AlarmManager.IntervalHour,
pendingIntent);

Para continuar con la activación de una aplicación en un momento SetExact concreto, use, pasando el tiempo
exacto en que se debe reactivarán la aplicación y la operación que se va a realizar:

alarmManager.SetExact (AlarmType.Rtc, AlarmManager.IntervalDay, pendingIntent);

KitKat ya no permite establecer una alarma de repetición exacta. Aplicaciones que usan SetRepeating y requerir
que las alarmas exactas funcionen ahora deberán desencadenar cada alarma manualmente.
Almacenamiento externo
El almacenamiento externo ahora se divide en dos tipos: almacenamiento único para la aplicación y datos
compartidos por varias aplicaciones. Leer y escribir en la ubicación específica de la aplicación en el
almacenamiento externo no requiere ningún permiso especial. La interacción con los datos en el almacenamiento
compartido requiere READ_EXTERNAL_STORAGE ahora WRITE_EXTERNAL_STORAGE el permiso o. Los dos tipos se pueden
clasificar como tales:
Si va a obtener una ruta de acceso de archivo o directorio mediante una Context llamada a un método en,
por ejemplo, GetExternalFilesDir de GetExternalCacheDirs
la aplicación no requiere permisos adicionales.
Si va a obtener una ruta de acceso de archivo o directorio al obtener acceso a una propiedad o Environment
llamar a un método en, como GetExternalStorageDirectory de GetExternalStoragePublicDirectory , la
aplicación requiere el READ_EXTERNAL_STORAGE permiso WRITE_EXTERNAL_STORAGE o.

NOTE
WRITE_EXTERNAL_STORAGE implica el READ_EXTERNAL_STORAGE permiso, por lo que solo debería tener que establecer un
permiso.

Consolidación de SMS
KitKat simplifica la mensajería para el usuario agregando todo el contenido de SMS en una aplicación
predeterminada seleccionada por el usuario. El desarrollador es responsable de hacer que la aplicación se
seleccione como la aplicación de mensajería predeterminada y se comporte de forma adecuada en el código y en
la vida si la aplicación no está seleccionada. Para obtener más información sobre cómo realizar la transición de la
aplicación SMS a KitKat, consulte la guía de preparación de las aplicaciones SMS para KitKat de Google.
Aplicaciones WebView
WebView tiene un makeover en KitKat. El cambio más importante se agrega seguridad para cargar el contenido
WebView en un. Aunque la mayoría de las aplicaciones que tienen como destino versiones anteriores de API
deberían funcionar según lo WebView esperado, se recomienda encarecidamente probar las aplicaciones que usan
la clase. Para obtener más información sobre las API de WebView afectadas, consulte la documentación sobre la
migración de Android a WebView en android 4,4 .

Experiencia del usuario


KitKat incluye varias API nuevas para mejorar la experiencia del usuario, incluido el nuevo marco de transición
para controlar las animaciones de propiedades y una opción de interfaz de usuario translúcida para los mismos.
Estos cambios se describen a continuación.
Marco de transición
El marco de transición facilita la implementación de animaciones. KitKat le permite realizar una sencilla animación
de propiedades con una sola línea de código o personalizar las transiciones mediante escenas.
Animación de propiedades simples
La nueva biblioteca de transiciones de Android simplifica el código subyacente a las animaciones de propiedad. El
marco de trabajo permite realizar animaciones simples con código mínimo. Por ejemplo, en el ejemplo de código
siguiente se usa TransitionManager.BeginDelayedTransition para animar la visualización y TextView ocultación de:

using Android.Transitions;

public class MainActivity : Activity


{
LinearLayout linear;
Button button;
TextView text;

protected override void OnCreate (Bundle bundle)


{
base.OnCreate (bundle);
SetContentView (Resource.Layout.Main);

linear = FindViewById<LinearLayout> (Resource.Id.linearLayout);


button = FindViewById<Button> (Resource.Id.button);
text = FindViewById<TextView> (Resource.Id.textView);

button.Click += (o, e) => {

TransitionManager.BeginDelayedTransition (linear);

if(text.Visibility != ViewStates.Visible)
{
text.Visibility = ViewStates.Visible;
}
else
{
text.Visibility = ViewStates.Invisible;
}
};
}
}

En el ejemplo anterior se usa el marco de transición para crear una transición automática y predeterminada entre
los valores de propiedad variables. Dado que la animación se controla mediante una sola línea de código, puede
hacerlo fácilmente con versiones anteriores de Android encapsulando la llamada en BeginDelayedTransition una
comprobación de la versión del sistema. Para más información, consulte la sección migración de la aplicación a
KitKat .
En la captura de pantalla siguiente se muestra la aplicación antes de la animación:
En la captura de pantalla siguiente se muestra la aplicación después de la animación:
Puede obtener más control sobre la transición con escenas, que se describen en la sección siguiente.
Escenas de Android
Las escenas se introdujeron como parte del marco de transición para ofrecer al desarrollador más control sobre las
animaciones. Escenas crear un área dinámica en la interfaz de usuario: se especifica un contenedor y varias
versiones, o "escenas", para el contenido XML dentro del contenedor y Android realiza el resto del trabajo para
animar las transiciones entre las escenas. Las escenas de Android permiten crear animaciones complejas con un
trabajo mínimo en el lado de desarrollo.
El elemento de la interfaz de usuario estática que aloja el contenido dinámico es un denominado contenedor o
base de la escena. En el ejemplo siguiente se usa el Android Designer para RelativeLayout crear container un
llamado:

El diseño de ejemplo también define un botón sceneButton denominado debajo container de. Este botón
desencadenará la transición.
El contenido dinámico dentro del contenedor requiere dos nuevos diseños de Android. Estos diseños solo
especifican el código dentro del contenedor. En el código de ejemplo siguiente se define un diseño denominado
Scene1 que contiene dos campos de texto que leen "kit" y "Kat (", respectivamente, y un segundo diseño
denominado Scene2 que contiene los mismos campos de texto inversos. El XML es el siguiente:
Scene1.axml:

<?xml version="1.0" encoding="utf-8"?>


<merge xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:id="@+id/textA"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Kit"
android:textSize="35sp" />
<TextView
android:id="@+id/textB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/textA"
android:text="Kat"
android:textSize="35sp" />
</merge>

Scene2.axml:
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:id="@+id/textB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Kat"
android:textSize="35sp" />
<TextView
android:id="@+id/textA"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/textB"
android:text="Kit"
android:textSize="35sp" />
</merge>

En el ejemplo anterior merge se usa para que el código de vista sea más corto y para simplificar la jerarquía de
vistas. Puede leer más sobre merge los diseños aquí.
Una escena se crea llamando a Scene.GetSceneForLayout , pasando el objeto contenedor, el identificador de recurso
del archivo de diseño de la escena y el actual Context , como se muestra en el ejemplo de código siguiente:

RelativeLayout container = FindViewById<RelativeLayout> (Resource.Id.container);

Scene scene1 = Scene.GetSceneForLayout(container, Resource.Layout.Scene1, this);


Scene scene2 = Scene.GetSceneForLayout(container, Resource.Layout.Scene2, this);

scene1.Enter();

Al hacer clic en el botón se voltea entre las dos escenas, que Android anima con los valores de transición
predeterminados:

sceneButton.Click += (o, e) => {


Scene temp = scene2;
scene2 = scene1;
scene1 = temp;

TransitionManager.Go (scene1);
};

En la captura de pantalla siguiente se muestra la escena antes de la animación:


En la captura de pantalla siguiente se muestra la escena después de la animación:
NOTE
Hay un error conocido en la biblioteca de transiciones de Android que hace que las GetSceneForLayout escenas creadas
con se interrumpan cuando un usuario navega por una actividad por segunda vez. Aquíse describe una solución alternativa
de Java.

T r a n si c i o n e s p e r so n a l i z a d a s e n e sc e n a s

Una transición personalizada se puede definir en un archivo de recursos XML en transition el Resources
directorio de, tal como se muestra en la siguiente captura de pantalla:

En el ejemplo de código siguiente se define una transición que anima cinco segundos y usa el interpolador de
sobremodulación:

<changeBounds
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="5000"
android:interpolator="@android:anim/overshoot_interpolator" />

La transición se crea en la actividad mediante TransitionInflater, como se muestra en el código siguiente:

Transition transition = TransitionInflater.From(this).InflateTransition(Resource.Transition.transition);

La nueva transición se agrega a continuación a Go la llamada que comienza la animación:

TransitionManager.Go (scene1, transition);

Interfaz de usuario translúcida


KitKat le ofrece más control sobre la aplicación con barras de navegación y de estado translúcido opcionales.
Puede cambiar el translucidez de los elementos de la interfaz de usuario del sistema en el mismo archivo XML que
se usa para definir el tema de Android. KitKat presenta las siguientes propiedades:
windowTranslucentStatus -Cuando se establece en true, hace que la barra de estado superior sea translúcida.
windowTranslucentNavigation -Cuando se establece en true, hace que la barra de navegación inferior sea
translúcida.
fitsSystemWindows -Si se establece la barra superior o inferior en transcluent, el contenido se desplaza bajo
los elementos transparentes de la interfaz de usuario de forma predeterminada. Establecer esta propiedad
en true es una forma sencilla de evitar que el contenido se superponga con los elementos de la interfaz de
usuario del sistema translúcido.
En el código siguiente se define un tema con barras de navegación y de estado translúcido:
<?xml version="1.0" encoding="UTF-8" ?>
<resources>
<style name="KitKatTheme" parent="android:Theme.Holo.Light">
<item name="android:windowBackground">@color/xamgray</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
<item name="android:fitsSystemWindows">true</item>
<item name="android:actionBarStyle">@style/ActionBar.Solid.KitKat</item>
</style>

<style name="ActionBar.Solid.KitKat" parent="@android:style/Widget.Holo.Light.ActionBar.Solid">


<item name="android:background">@color/xampurple</item>
</style>
</resources>

En la captura de pantalla siguiente se muestra el tema anterior con las barras de navegación y de estado
translúcido:
Contenido del usuario
Marco de acceso al almacenamiento
El marco de acceso de almacenamiento (SAF ) es una nueva forma de que los usuarios interactúen con el contenido
almacenado, como imágenes, vídeos y documentos. En lugar de presentar a los usuarios un cuadro de diálogo
para elegir una aplicación para controlar el contenido, KitKat abre una nueva interfaz de usuario que permite a los
usuarios tener acceso a sus datos en una ubicación agregada. Una vez que se haya elegido el contenido, el usuario
volverá a la aplicación que solicitó el contenido y la experiencia de la aplicación continuará como es habitual.
Este cambio requiere dos acciones en el lado del Desarrollador: en primer lugar, las aplicaciones que requieren
contenido de los proveedores deben actualizarse a una nueva forma de solicitar contenido. En segundo lugar, las
aplicaciones que escriben datos en un ContentProvider deben modificarse para usar el nuevo marco de trabajo.
Ambos escenarios dependen del nuevo DocumentsProvider API.
DocumentsProvider
En KitKat, las interacciones con ContentProviders se abstraen con la DocumentsProvider clase. Esto significa que
SAF no se preocupa de dónde están los datos físicamente, siempre y cuando sea accesible a DocumentsProvider
través de la API. Los proveedores locales, los servicios en la nube y los dispositivos de almacenamiento externo
usan la misma interfaz, y se tratan de la misma manera, lo que proporciona al usuario y al desarrollador un solo
lugar para interactuar con el contenido del usuario.
En esta sección se explica cómo cargar y guardar contenido con el marco de acceso de almacenamiento.
Solicitar contenido de un proveedor
Podemos indicar a kitkat que queremos elegir contenido mediante la interfaz de usuario de SAF con
ActionOpenDocument la intención, lo que significa que queremos conectarnos a todos los proveedores de contenido
disponibles para el dispositivo. Puede Agregar algún filtro a esta intención especificando CategoryOpenable , lo que
significa que solo se devolverá el contenido que se puede abrir (es decir, contenido accesible y utilizable). KitKat
también permite filtrar el MimeType contenido con. Por ejemplo, el código siguiente filtra los resultados de la
imagen mediante la especificación MimeType de la imagen:

Intent intent = new Intent (Intent.ActionOpenDocument);


intent.AddCategory (Intent.CategoryOpenable);
intent.SetType ("image/*");
StartActivityForResult (intent, save_request_code);
La StartActivityForResult llamada a inicia la interfaz de usuario de SAF, que el usuario puede examinar para
elegir una imagen:
Una vez que el usuario ha elegido una OnActivityResult imagen, Android.Net.Uri devuelve el del archivo elegido.
En el ejemplo de código siguiente se muestra la selección de imagen del usuario:

protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)


{
base.OnActivityResult(requestCode, resultCode, data);

if (resultCode == Result.Ok && data != null && requestCode == save_request_code) {


imageView = FindViewById<ImageView> (Resource.Id.imageView);
imageView.SetImageURI (data.Data);
}
}

Escribir contenido en un proveedor


Además de cargar contenido desde la interfaz de usuario de SAF, KitKat también le permite guardar contenido
ContentProvider en cualquier que implemente la DocumentProvider API. Al guardar el contenido Intent ,
ActionCreateDocument se usa un con:

Intent intentCreate = new Intent (Intent.ActionCreateDocument);


intentCreate.AddCategory (Intent.CategoryOpenable);
intentCreate.SetType ("text/plain");
intentCreate.PutExtra (Intent.ExtraTitle, "NewDoc");
StartActivityForResult (intentCreate, write_request_code);

En el ejemplo de código anterior se carga la interfaz de usuario de SAF, lo que permite al usuario cambiar el
nombre de archivo y seleccionar un directorio para hospedar el nuevo archivo:
Cuando el usuario presiona Guardar, OnActivityResult se pasa el Android.Net.Uri del archivo recién creado, al
que se puede tener acceso con data.Data . El URI se puede usar para transmitir los datos en el nuevo archivo:

protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)


{
base.OnActivityResult(requestCode, resultCode, data);

if (resultCode == Result.Ok && data != null && requestCode == write_request_code) {


using (Stream stream = ContentResolver.OpenOutputStream(data.Data)) {
Encoding u8 = Encoding.UTF8;
string content = "Hello, world!";
stream.Write (u8.GetBytes(content), 0, content.Length);
}
}
}

Tenga en cuenta que ContentResolver.OpenOutputStream(Android.Net.Uri) Devuelve un System.IO.Stream objeto, por


lo que se puede escribir en .net todo el proceso de streaming.
Para obtener más información sobre la carga, la creación y la edición de contenido con el marco de acceso de
almacenamiento, consulte la documentación de Android para el marco de acceso de almacenamiento.
Impresión
El contenido de impresión se simplifica en KitKat con la introducción de los servicios PrintManager de impresión y.
KitKat también es la primera versión de la API para aprovechar completamente las API del servicio de impresión
en la nube de Google con la aplicación Google Cloud Print. La mayoría de los dispositivos que se incluyen con
KitKat descargan automáticamente la aplicación de impresión en la nube de Google y el complemento del servicio
de impresión de HPcuando se conectan por primera vez a WiFi Un usuario puede comprobar la configuración de
impresión de su dispositivo navegando a configuración > sistema > impresión:
NOTE
Aunque las API de impresión están configuradas para que funcionen con Google Cloud Print de forma predeterminada,
Android sigue permitiendo a los desarrolladores preparar el contenido de impresión con las nuevas API y enviarlo a otras
aplicaciones para controlar la impresión.

Imprimir contenido HTML


KitKat crea automáticamente un para una vista Web con
PrintDocumentAdapter
WebView.CreatePrintDocumentAdapter . La impresión de contenido web es un esfuerzo coordinado entre un
WebViewClient que espera a que se cargue el contenido HTML y permite que la actividad sepa que la opción de
impresión está disponible en el menú opciones y la actividad, que espera a que el usuario seleccione la opción de
impresión y llama a Print en el PrintManager . En esta sección se describe la configuración básica necesaria para
imprimir contenido HTML en pantalla.
Tenga en cuenta que la carga y la impresión de contenido Web requieren el permiso de Internet:

El e m e n t o d e m e n ú d e i m p r e si ó n

La opción Imprimir normalmente aparecerá en el menú de opcionesde la actividad. El menú opciones permite que
los usuarios realicen acciones en una actividad. Está en la esquina superior derecha de la pantalla y tiene el
siguiente aspecto:

Los elementos de menú adicionales pueden definirse en el directorio de menúsen recursos. El código siguiente
define un elemento de menú de ejemplo denominado Print:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/menu_print"
android:title="Print"
android:showAsAction="never" />
</menu>

La interacción con el menú de opciones de la actividad se OnCreateOptionsMenu produce OnOptionsItemSelected a


través de los métodos y. OnCreateOptionsMenu es el lugar donde se agregan nuevos elementos de menú, como la
opción de impresión, en el directorio de recursos del menú . OnOptionsItemSelected escucha al usuario
seleccionando la opción de impresión en el menú y comienza la impresión:

bool dataLoaded;

public override bool OnCreateOptionsMenu (IMenu menu)


{
base.OnCreateOptionsMenu (menu);
if (dataLoaded) {
MenuInflater.Inflate (Resource.Menu.print, menu);
}
return true;
}

public override bool OnOptionsItemSelected (IMenuItem item)


{
if (item.ItemId == Resource.Id.menu_print) {
PrintPage ();
return true;
}
return base.OnOptionsItemSelected (item);
}

El código anterior también define una variable denominada dataLoaded para realizar un seguimiento del estado
del contenido HTML. El WebViewClient establecerá esta variable en true cuando se haya cargado todo el contenido,
por lo que la actividad sabrá agregar el elemento de menú de impresión al menú opciones.
W e b Vi e w C l i e n t

El trabajo de WebViewClient es asegurarse de que los datos WebView de se cargan por completo antes de que
aparezca la opción Imprimir en el menú, que OnPageFinished lo hace con el método. OnPageFinished realiza
escuchas para que el contenido web termine de cargarse e indica a la actividad que vuelva a
InvalidateOptionsMenu crear su menú de opciones con:

class MyWebViewClient : WebViewClient


{
PrintHtmlActivity caller;

public MyWebViewClient (PrintHtmlActivity caller)


{
this.caller = caller;
}

public override void OnPageFinished (WebView view, string url)


{
caller.dataLoaded = true;
caller.InvalidateOptionsMenu ();
}
}

OnPageFinishedtambién establece el dataLoaded valor en true , por OnCreateOptionsMenu lo que puede volver a
crear el menú con la opción de impresión en su lugar.
Pr i n t Man ager

En el ejemplo de código siguiente se imprime el WebView contenido de un:

void PrintPage ()
{
PrintManager printManager = (PrintManager)GetSystemService (Context.PrintService);
PrintDocumentAdapter printDocumentAdapter = myWebView.CreatePrintDocumentAdapter ();
printManager.Print ("MyWebPage", printDocumentAdapter, null);
}

Print toma como argumentos: un nombre para el trabajo de impresión ("mi página web" en este ejemplo), un
PrintDocumentAdapter que genera el documento de impresión a partir del contenido y PrintAttributes ( null en
el ejemplo anterior). Puede especificar PrintAttributes para ayudar a diseñar el contenido en la página impresa,
aunque los atributos predeterminados deben controlar la mayoría de los escenarios.
La Print llamada a carga la interfaz de usuario de impresión, que enumera las opciones para el trabajo de
impresión. La interfaz de usuario ofrece a los usuarios la opción de imprimir o guardar el contenido HTML en un
archivo PDF, tal como se muestra en las capturas de pantallas siguientes:
Hardware
KitKat agrega varias API para acomodar las nuevas características del dispositivo. Los más importantes son la
emulación de tarjetas basadas en host y el SensorManager nuevo.
Emulación de tarjeta basada en host en NFC
La emulación de tarjeta basada en host (HCE ) permite que las aplicaciones se comporten como tarjetas NFC o
lectores de tarjetas NFC sin depender del elemento seguro propio del operador. Antes de configurar HCE,
asegúrese de que HCE está disponible en el PackageManager.HasSystemFeature dispositivo con:

bool hceSupport = PackageManager.HasSystemFeature(PackageManager.FeatureNfcHostCardEmulation);

HCE requiere que la característica HCE y el Nfc permiso se registren con el de AndroidManifest.xml la aplicación:

<uses-feature android:name="android.hardware.nfc.hce" />

Para trabajar, HCE tiene que poder ejecutarse en segundo plano y debe iniciarse cuando el usuario realiza una
transacción NFC, incluso si la aplicación que usa HCE no se está ejecutando. Podemos lograr esto escribiendo el
código de HCE como Service . Un servicio HCE implementa la HostApduService interfaz, que implementa los
métodos siguientes:
ProcessCommandApdu : una unidad de datos de protocolo de aplicación (APDU ) es lo que se envía entre el
lector NFC y el servicio HCE. Este método consume un ADPU del lector y devuelve una unidad de datos en
respuesta.
OnDeactivated : HostAdpuService se desactiva cuando el servicio HCE deja de comunicarse con el lector
NFC.
Un servicio HCE también debe registrarse con el manifiesto de la aplicación y decorarse con los permisos, el filtro
de intención y los metadatos adecuados. El código siguiente es un ejemplo de un HostApduService registrado con
el manifiesto de Android mediante Service el atributo (para obtener más información sobre los atributos,
consulte la guía Xamarin Working with Android manifest ):

[Service(Exported=true, Permission="android.permissions.BIND_NFC_SERVICE"),
IntentFilter(new[] {"android.nfc.cardemulation.HOST_APDU_SERVICE"}),
MetaData("android.nfc.cardemulation.host.apdu_service",
Resource="@xml/hceservice")]

class HceService : HostApduService


{
public override byte[] ProcessCommandApdu(byte[] apdu, Bundle extras)
{
...
}

public override void OnDeactivated (DeactivationReason reason)


{
...
}
}

El servicio anterior proporciona una manera para que el lector NFC interactúe con la aplicación, pero el lector NFC
todavía no tiene ninguna manera de saber si este servicio está emulando la tarjeta NFC que debe examinar. Para
ayudar al lector NFC a identificar el servicio, podemos asignar el servicio a un identificador de aplicación único
(AID ) . Especificamos una ayuda, junto con otros metadatos sobre el servicio HCE, en un archivo de recursos XML
registrado MetaData con el atributo (vea el ejemplo de código anterior). Este archivo de recursos especifica uno o
varios filtros de AID: cadenas de identificador único en formato hexadecimal que corresponden a los Aid de uno o
más dispositivos de Lector NFC:

<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
android:description="@string/hce_service_description"
android:requireDeviceUnlock="false"
android:apduServiceBanner="@drawable/service_banner">
<aid-group android:description="@string/aid_group_description"
android:category="payment">
<aid-filter android:name="1111111111111111"/>
<aid-filter android:name="0123456789012345"/>
</aid-group>
</host-apdu-service>

Además de los filtros de ayuda, el archivo de recursos XML también proporciona una descripción orientada al
usuario del servicio HCE, especifica un grupo de AID (aplicación de pago en lugar de "otros") y, en el caso de una
aplicación de pago, un banner de 260x96 DP que se va a mostrar al usuario.
El programa de instalación descrito anteriormente proporciona los bloques de creación básicos para una aplicación
que emula una tarjeta NFC. El propio NFC requiere varios pasos más y otras pruebas para configurar. Para
obtener más información sobre la emulación de tarjetas basadas en host, consulte el portal de documentación de
Android. Para más información sobre el uso de NFC con Xamarin, consulte los ejemplos de NFC de Xamarin.
Sensores
KitKat proporciona acceso a los sensores del dispositivo a través SensorManager de un. SensorManager Permite al
sistema operativo programar la entrega de información de sensor a una aplicación por lotes, manteniendo la
duración de la batería.
KitKat también incluye dos nuevos tipos de sensor para realizar el seguimiento de los pasos del usuario. Estos se
basan en el acelerómetro e incluyen:
StepDetector -APP se notifica/reactivarán cuando el usuario realiza un paso y el detector proporciona un
valor de tiempo para el momento en que se produjo el paso.
StepCounter : realiza un seguimiento del número de pasos que ha tomado el usuario desde que se registró
el sensor hasta el siguiente reinicio del dispositivo.
En la captura de pantalla siguiente se muestra el contador de pasos en acción:
Puede crear un SensorManager GetSystemService(SensorService) llamando a y SensorManager convirtiendo el
resultado como. Para usar el contador de pasos, GetDefaultSensor llame a SensorManager en. Puede registrar el
sensor y escuchar los cambios en el recuento de pasos con la ayuda del ISensorEventListener , como se muestra en
el ejemplo de código siguiente:

public class MainActivity : Activity, ISensorEventListener


{
float count = 0;

protected override void OnCreate (Bundle bundle)


{
base.OnCreate (bundle);
SetContentView (Resource.Layout.Main);

SensorManager senMgr = (SensorManager) GetSystemService (SensorService);


Sensor counter = senMgr.GetDefaultSensor (SensorType.StepCounter);
if (counter != null) {
senMgr.RegisterListener(this, counter, SensorDelay.Normal);
}
}

public void OnAccuracyChanged (Sensor sensor, SensorStatus accuracy)


{
Log.Info ("SensorManager", "Sensor accuracy changed");
}

public void OnSensorChanged (SensorEvent e)


{
count = e.Values [0];
}
}

OnSensorChanged se llama a si el recuento de pasos se actualiza mientras la aplicación está en primer plano. Si la
aplicación entra en el fondo, o el dispositivo está en OnSensorChanged suspensión, no se llamará a; sin embargo, los
pasos se seguirán contando hasta que UnregisterListener se llame a.
Tenga en cuenta que el valor de recuento de pasos es acumulativo en todas las aplicaciones que registran el sensor.
Esto significa que incluso si desinstala y vuelve a instalar la aplicación e inicializa la count variable en 0 al iniciarse
la aplicación, el valor indicado por el sensor seguirá siendo el número total de pasos que se realizaron mientras se
registraba el sensor, ya sea por el aplicación u otra. Puede evitar que la aplicación se agregue al contador de pasos
llamando UnregisterListener a SensorManager en, como se muestra en el código siguiente:

protected override void OnPause()


{
base.OnPause ();
senMgr.UnregisterListener(this);
}
Al reiniciar el dispositivo, se restablece el número de pasos en 0. La aplicación necesitará código adicional para
asegurarse de que informa de un recuento exacto de la aplicación, independientemente de otras aplicaciones que
usen el sensor o el estado del dispositivo.

NOTE
Mientras que la API para la detección y el recuento de pasos se incluye con KitKat, no todos los teléfonos están desprovistos
del sensor. Puede comprobar si el sensor está disponible ejecutando
PackageManager.HasSystemFeature(PackageManager.FeatureSensorStepCounter); o asegúrese de que el valor devuelto
de GetDefaultSensor no null sea.

Herramientas de desarrollo
Grabación de pantalla
KitKat incluye nuevas capacidades de grabación de pantalla para que los desarrolladores puedan grabar
aplicaciones en acción. La grabación de pantalla está disponible a través del cliente de Android Debug Bridge
(ADB ) , que puede descargarse como parte de la Android SDK.
Para grabar la pantalla, conecte el dispositivo; a continuación, busque la instalación de Android SDK, navegue
hasta el directorio de herramientas de la plataforma y ejecute el cliente ADB :

adb shell screenrecord /sdcard/screencast.mp4

El comando anterior registrará un vídeo de 3 minutos predeterminado en la resolución predeterminada de 4Mbps.


Para editar la longitud, agregue la marca --Time-Limit . Para cambiar la resolución, agregue la marca --bit-rate . El
siguiente comando registrará un vídeo de un minuto en 8Mbps:

adb shell screenrecord --bit-rate 8000000 --time-limit 60 /sdcard/screencast.mp4

Puede encontrar el vídeo en el dispositivo: aparecerá en la Galería cuando se complete la grabación.

Otras adiciones de KitKat


Además de los cambios descritos anteriormente, KitKat le permite:
Use la pantalla completa : KitKat presenta un nuevo modo inmersivo para examinar contenido, jugar a
juegos y ejecutar otras aplicaciones que podrían beneficiarse de una experiencia de pantalla completa.
Personalización de notificaciones: obtenga detalles adicionales acerca de las notificaciones del sistema con
la NotificationListenerService . Esto le permite presentar la información de manera diferente dentro de la
aplicación.
Recursos que se dibujan en reflejo: los recursos que se van a dibujar tienen un nuevo autoMirrored atributo
que indica al sistema que cree una versión reflejada para las imágenes que requieran el volteo de los
diseños de izquierda a derecha.
Pausar animaciones : pausar y reanudar animaciones creadas con el Animator clase.
Leer texto dinámico cambiante : denota partes de la interfaz de usuario que actualizan dinámicamente con
nuevo texto como "regiones activas" con el nuevo accessibilityLiveRegion atributo para que el nuevo texto
se lea automáticamente en el modo de accesibilidad.
Mejorar la experiencia de audio : hacer pistas más fuertes con el LoudnessEnhancer , busque el pico y el RMS
de una secuencia de audio con el Visualizer y obtenga información de una marca de tiempo de audio para
ayudarle con la sincronización de audio y vídeo.
Sincronizar ContentResolver devuelvan en el intervalo personalizado : KitKat agrega cierta variabilidad al
momento en que se realiza una solicitud de sincronización. Sincronizar ContentResolver a un momento o
intervalo ContentResolver.RequestSync personalizado llamando a y pasando un SyncRequest .
Distinguir entre controladores : en KitKat, a los controladores se les asignan identificadores enteros únicos a
los que se puede tener ControllerNumber acceso a través de la propiedad del dispositivo. Esto hace que sea
más fácil distinguir a los jugadores de un juego.
Control remoto : con unos pocos cambios en el lado del hardware y el software, KitKat le permite convertir
un dispositivo de un transmisor de infrarrojos en un control remoto mediante el ConsumerIrService y
interactuar con dispositivos periféricos con el nuevo RemoteController Enumera.
Para más información sobre los cambios anteriores de la API, consulte la introducción a las API de Google
Android 4,4 .

Resumen
En este artículo se presentaron algunas de las nuevas API disponibles en Android 4,4 (nivel de API 19) y se han
descrito prácticas recomendadas para la transición de una aplicación a KitKat. Se describen los cambios en las API
que afectan a la experiencia del usuario, incluido el marco de transición ylas nuevas opciones para la misma. A
continuación, se presentó el marco y DocumentsProvider la clase de acceso al almacenamiento, así como las nuevas
API de impresión. Exploró la emulación de la tarjeta basada en host NFC y cómo trabajar con sensores de baja
energía, incluidos dos nuevos sensores para realizar un seguimiento de los pasos del usuario. Por último, ha
demostrado la captura de demostraciones en tiempo real de aplicaciones con grabación de pantallay proporciona
una lista detallada de los cambios y las adiciones de la API de kitkat.

Vínculos relacionados
Ejemplo de KitKat
API de Android 4,4
KitKat de Android
Características de Jale Bean
16/08/2019 • 24 minutes to read • Edit Online

En este documento se proporciona información general de alto nivel de las nuevas características para los
desarrolladores que se introdujeron en Android 4,1. Estas características incluyen: notificaciones mejoradas,
actualizaciones para el rayo de Android para compartir archivos de gran tamaño, actualizaciones a multimedia,
detección de redes punto a punto, animaciones y nuevos permisos.

Información general
Android 4,1 (nivel de API 16), también conocido como "Jaleis", se publicó el 9 de julio de 2012. En este artículo se
proporciona una introducción de alto nivel a algunas de las nuevas características de Android 4,1 para
desarrolladores que usan Xamarin. Android. Algunas de estas nuevas características introducidas son mejoras en
las animaciones para iniciar una actividad, nuevos sonidos para una cámara y compatibilidad mejorada con la
navegación por la pila de aplicaciones. Ahora es posible cortar y pegar con intenciones.
La estabilidad de las aplicaciones Android se ha mejorado con la capacidad de aislar la dependencia en los
proveedores de contenido inestables. Los servicios también pueden estar aislados, de modo que solo sean
accesibles por la actividad que los inició.
Se ha agregado compatibilidad con la detección de servicios de red mediante Bonjour, UPnP o servicios basados
en DNS de multidifusión. Ahora es posible para las notificaciones más enriquecidas que tienen texto con formato,
botones de acción e imágenes grandes.
Por último, se han agregado varios permisos nuevos en Android 4,1.

Requisitos
Para desarrollar aplicaciones de Xamarin. Android con el Bean de jale, se requiere Xamarin. Android 4.2.6 o
posterior y Android 4,1 (nivel de API 16) se instala a través del administrador de Android SDK como se muestra
en la siguiente captura de pantalla:
Novedades
Animaciones
Las actividades se pueden iniciar mediante animaciones de zoom o animaciones personalizadas mediante la
ActivityOptions clase. Se proporcionan los siguientes métodos nuevos para admitir estas animaciones:

MakeScaleUpAnimation : De esta forma, se crea una animación que escala verticalmente una ventana de actividad
a partir de una posición inicial y un tamaño en la pantalla.
MakeThumbnailScaleUpAnimation : Esto creará una animación que se escala verticalmente desde una imagen en
miniatura desde la posición especificada en la pantalla.
MakeCustomAnimation : Crea una animación a partir de los recursos de la aplicación. Hay una animación para
cuando se abre la actividad y otra para cuando se detiene la actividad.
La nueva TimeAnimator clase proporciona una interfaz TimeAnimator.ITimeListener que puede notificar a una
aplicación cada vez que un fotograma cambia en una animación. Por ejemplo, considere la siguiente
implementación de TimeAnimator.ITimeListener :
class MyTimeListener : Java.Lang.Object, TimeAnimator.ITimeListener
{
public void OnTimeUpdate(TimeAnimator animation, long totalTime, long deltaTime)
{
Log.Debug("Activity1", "totalTime={0}, deltaTime={1}", totalTime, deltaTime);
}
}

Y ahora se usa la clase, se crea una TimeAnimator instancia de y se establece el agente de escucha:

var animator = new TimeAnimator();


animator.SetTimeListener(new MyTimeListener());
animator.Start();

A medida TimeAnimator que se ejecuta la instancia, se ITimeAnimator.ITimeListener invocará, que después


registrará el tiempo durante el que se ha estado ejecutando el animador y cuánto tiempo ha transcurrido desde la
última vez que se ha invocado el método.
Navegación por la pila de aplicaciones
Android 4,1 mejora la navegación de la pila de aplicaciones que se presentó en Android 3,0. Al especificar la
ParentName propiedad ActivityAttribute de, Android puede abrir la actividad primaria adecuada cuando el
usuario presiona el botón subir en la barra de acciones: Android creará una instancia de la actividad especificada
por ParentName la propiedad. Esto permite a las aplicaciones conservar la jerarquía de actividades que realizan una
tarea determinada.
Para la mayoría de las ParentName aplicaciones, la configuración de en la actividad es suficiente información para
que Android proporcione el comportamiento correcto para navegar por la pila de la aplicación. Android sintetizará
la pila de retroceso necesaria creando una serie de intentos para cada actividad primaria. Sin embargo, dado que
se trata de una pila de aplicaciones artificial, cada actividad sintética no tendrá el estado guardado que tendría una
actividad natural. Para proporcionar el estado guardado a una actividad primaria sintética, una actividad puede
invalidar el OnPrepareNavigationUpTaskStack método. Este método recibe una TaskStackBuilder instancia de que
tendrá una colección de objetos de intención que Android usará para crear la pila de reserva. La actividad puede
modificar estos intentos, de modo que, a medida que se crea la actividad sintética, recibirá la información de estado
adecuada.
En escenarios más complejos, hay nuevos métodos en la clase de actividad que se pueden usar para controlar el
comportamiento de la navegación hacia arriba y construir la pila de retroceso:
OnNavigateUp : Al invalidar este método, es posible realizar una acción personalizada cuando se presiona el
botón subir .
NavigateUpTo : Si se llama a este método, la aplicación navega de la actividad actual a la actividad especificada
por un intento determinado.
ParentActivityIntent : Se usa para obtener un intento que iniciará la actividad primaria de la actividad actual.
ShouldUpRecreateTask : Este método se utiliza para consultar si se debe crear la pila de retroceso sintética para
navegar hasta una actividad primaria. Devuelve true si se debe crear la pila sintética.
FinishAffinity : La llamada a este método finalizará la actividad actual y todas las actividades inferiores en la
tarea actual que tengan la misma afinidad de tarea.
OnCreateNavigateUpTaskStack : Este método se reemplaza cuando es necesario tener un control completo sobre
cómo se crea la pila sintética.
Cámara
Hay una nueva interfaz, Camera.IAutoFocusMoveCallback , que se puede usar para detectar cuándo se ha iniciado o
detenido el desplazamiento automático. En el siguiente fragmento de código puede verse un ejemplo de esta
nueva interfaz:

public class AutoFocusCallbackActivity : Activity, Camera.IAutoFocusCallback


{
public void OnAutoFocus(bool success, Camera camera)
{
// camera is an instance of the camera service object.

if (success)
{
// Auto focus was successful - do something here.
}
else
{
// Auto focus didn't happen for some reason - react to that here.
}
}
}

La nueva clase MediaActionSound proporciona un conjunto de API para generar sonidos para las diversas acciones
multimedia. Hay varias acciones que se pueden producir con una cámara, que se definen mediante la enumeración
Android.Media.MediaActionSoundType :

MediaActionSoundType.FocusComplete : Este sonido se reproduce cuando se ha completado el enfoque.


MediaActionSoundType.ShutterClick : Este sonido se reproducirá cuando se tome una imagen de imagen fija.
MediaActionSoundType.StartVideoRecording : Este sonido indica el inicio de la grabación de vídeo.
MediaActionSoundType.StopVideoRecording : Este sonido se reproducirá para indicar el final de la grabación de
vídeo.
Un ejemplo de cómo usar la MediaActionSound clase puede verse en el siguiente fragmento de código:

var mediaActionPlayer = new MediaActionSound();

// Preload the sound for a shutter click.


mediaActionPlayer.Load(MediaActionSoundType.ShutterClick);
var button = FindViewById<Button>(Resource.Id.MyButton);

// Play the sound on a button click.


button.Click += (sender, args) => mediaActionPlayer.Play(MediaActionSoundType.ShutterClick);

// This releases the preloaded resources. Don’t make any calls on


// mediaActionPlayer after this.
mediaActionPlayer.Release();

Conectividad
Android Beam
El rayo de Android es una tecnología basada en NFC que permite que dos dispositivos Android se comuniquen
entre sí. Android 4,1 proporciona una mejor compatibilidad para la transferencia de archivos grandes. Cuando use
el nuevo método NfcAdapter.SetBeamPushUris() , Android cambiará entre mecanismos de transporte alternativos
(como Bluetooth) para lograr una velocidad de transferencia rápida.
Detección de Network Services
Android 4,1 contiene nuevas API para la detección de servicios basada en DNS de multidifusión. Esto permite a
una aplicación detectar y conectarse a través de Wi-Fi a otros dispositivos, como impresoras, cámaras y
dispositivos multimedia. Estas nuevas API se encuentran en el Android.Net.Nsd paquete.
Para crear un servicio que puede ser consumido por otros servicios, NsdServiceInfo se usa la clase para crear un
objeto que defina las propiedades de un servicio. A continuación, este objeto se NsdManager.RegisterService()
proporciona junto con una implementación NsdManager.ResolveListener de. Las implementaciones
NsdManager.ResolveListener de se usan para notificar un registro correcto y anular el registro del servicio.

Para detectar servicios en la red y la implementación de Nsd.DiscoveryListener que se


NsdManager.discoverServices() pasa a.

Uso de red
Un nuevo método ConnectivityManager.IsActiveNetworkMetered permite que un dispositivo Compruebe si está
conectado a una red de uso medido. Este método se puede usar para ayudar a administrar el uso de datos al
informar a los usuarios de forma precisa de que puede haber costosos en las operaciones de datos.
Detección de servicios Wi-Fi Direct
La WifiP2pManager clase se presentó en Android 4,0 para admitir Zeroconf. Zeroconf (ninguna red de
configuración) es un conjunto de técnicas que permite a los dispositivos (equipos, impresoras, teléfonos)
conectarse a las redes automáticamente, con la intervención de los operadores de red humana o de los servidores
de configuración especiales.
En jale Bean, WifiP2pManager puede detectar dispositivos cercanos mediante Bonjour o UPnP. Bonjour es la
implementación de Zeroconf de Apple. UPnP es un conjunto de protocolos de red que también admite Zeroconf.
Los métodos siguientes agregados a WiFiP2pManager para admitir la detección de servicios Wi-Fi:
AddLocalService() : Este método se usa para anunciar una aplicación como servicio a través de Wi-Fi para la
detección por parte de los equipos del mismo nivel.
AddServiceRequest( ): Este método es para enviar una solicitud de detección de servicios al marco. Se usa para
inicializar la detección del servicio Wi-Fi.
SetDnsSdResponseListeners() : Este método se usa para registrar devoluciones de llamada que se van a invocar
al recibir una respuesta a las solicitudes de detección de Bonjour.
SetUpnpServiceResponseListener() : Este método se usa para registrar devoluciones de llamada que se van a
invocar al recibir una respuesta a las solicitudes de detección UPnP.
Proveedores de contenido
La ContentResolver clase ha recibido un nuevo método, AcquireUnstableContentProvider . Este método permite a
una aplicación adquirir un proveedor de contenido "inestable". Normalmente, cuando una aplicación adquiere un
proveedor de contenido y ese proveedor de contenido se bloquea, lo hará la aplicación. Con esta llamada al
método, una aplicación no se bloqueará si el proveedor de contenido se bloquea. En su lugar
Android.OS.DeadObjectionException , se producirá desde las llamadas en el proveedor de contenido para informar a
una aplicación de que el proveedor de contenido ha desaparecido. Un proveedor de contenido "inestable" es útil al
interactuar con proveedores de contenido de otras aplicaciones; es menos probable que el código erróneo de otra
aplicación afecte a otra aplicación.
Copiar y pegar con intenciones
La Intent clase ahora puede tener un ClipData objeto asociado a ella a través Intent.ClipData de la propiedad.
Este método permite que se transmitan datos adicionales desde el Portapapeles con el intento. Una instancia de
ClipData puede contener uno o más ClipData.Item . ClipData.Item son elementos de los siguientes tipos:

Texto : cadena de texto, HTML o cualquier cadena cuyo formato sea compatible con los intervalos de estilo
integrados de Android.
Intención : cualquier Intent objeto.
URI : puede ser cualquier URI, como un marcador http o el URI a un proveedor de contenido.
Servicios aislados
Un servicio aislado es un servicio que se ejecuta bajo su propio proceso especial y no tiene permisos propios. La
única comunicación con el servicio es cuando se inicia el servicio y se enlaza a él a través de la API de servicio. Es
posible declarar un servicio como aislado estableciendo la propiedad IsolatedProcess="true" ServiceAttribute en
que adorna una clase de servicio.
Multimedia
La nueva Android.Media.MediaCodec clase proporciona una API a los códecs multimedia de bajo nivel. Las
aplicaciones pueden consultar el sistema para averiguar qué códecs de nivel inferior están disponibles en el
dispositivo.
Las nuevas Android.Media.Audiofx.AudioEffect subclases se han agregado para admitir el procesamiento previo de
audio adicional en el audio capturado:
Android.Media.Audiofx.AcousticEchoCanceler : Esta clase se usa para el procesamiento previo de audio para
quitar la señal de una parte remota de una señal de audio capturada. Por ejemplo, quitar el eco de una
aplicación de comunicación de voz.
Android.Media.Audiofx.AutomaticGainControl : Esta clase se usa para normalizar la señal capturada aumentando
o reduciendo una señal de entrada para que la señal de salida sea constante.
Android.Media.Audiofx.NoiseSuppressor : Esta clase quitará el ruido de fondo de la señal capturada.

No todos los dispositivos admiten estos efectos. Una aplicación AudioEffect.IsAvailable debe llamar al método
para ver si se admite el efecto de audio en cuestión en el dispositivo que ejecuta la aplicación.
La MediaPlayer clase ahora admite la reproducción de sin huecos SetNextMediaPlayer() con el método. Este
nuevo método especifica el siguiente MediaPlayer que se va a iniciar cuando el reproductor multimedia actual
termine de reproducirse.
Las siguientes clases nuevas proporcionan mecanismos y la interfaz de usuario estándar para seleccionar dónde se
reproducirá el medio:
MediaRouter : Esta clase permite a las aplicaciones controlar el enrutamiento de canales multimedia desde un
dispositivo a altavoces externos u otros dispositivos.
MediaRouterActionProvider y MediaRouteButton : estas clases ayudan a proporcionar una interfaz de usuario
coherente para seleccionar y reproducir elementos multimedia.
Notificaciones
Android 4,1 permite que las aplicaciones tengan más flexibilidad y control con la visualización de notificaciones.
Ahora, las aplicaciones pueden mostrar notificaciones más grandes y mejores a los usuarios. Un nuevo método,
NotificationBuilder.SetStyle() permite que uno de los nuevos tres nuevos estilos se establezca en las
notificaciones:
Notification.BigPictureStyle : Se trata de una clase auxiliar que generará notificaciones que incluirán una
imagen en ellas. La imagen siguiente muestra un ejemplo de una notificación con una imagen grande:
Notification.BigTextStyle : Se trata de una clase auxiliar que generará notificaciones que tendrán varias líneas
de texto, como el correo electrónico. En la siguiente captura de pantalla se puede consultar un ejemplo de este
nuevo estilo de notificación:

: Se trata de una clase auxiliar que generará notificaciones que contienen una lista de
Notification.InboxStyle
cadenas, como fragmentos de código de un mensaje de correo electrónico, tal como se muestra en esta captura
de pantalla:

Es posible agregar hasta dos botones de acción en la parte inferior de un mensaje de notificación cuando la
notificación esté usando el estilo normal o mayor. Un ejemplo de esto se puede ver en la siguiente captura de
pantalla, donde los botones de acción están visibles en la parte inferior de la notificación:
La Notification clase ha recibido nuevas constantes que permiten al desarrollador especificar uno de los cinco
niveles de prioridad para una notificación. Se pueden establecer en una notificación mediante la Priority
propiedad.
Permisos
Se han agregado los siguientes permisos nuevos:
READ_EXTERNAL_STORAGE -La aplicación requiere acceso de solo lectura al almacenamiento externo. Actualmente,
todas las aplicaciones tienen acceso de lectura de forma predeterminada, pero las versiones futuras de Android
requerirán que las aplicaciones soliciten explícitamente el acceso de lectura.
READ_USER_DICTIONARY : Permite el acceso de lectura al Diccionario de palabras del usuario.
READ_CALL_LOG : Permite que una aplicación obtenga información sobre las llamadas entrantes y salientes
leyendo el registro de llamadas.
WRITE_CALL_LOG : Permite que una aplicación escriba en el registro de llamadas del teléfono.
WRITE_USER_DICTIONARY : Permite que una aplicación escriba en el Diccionario de palabras del usuario.

Un cambio importante a tener READ_EXTERNAL_STORAGE en cuenta: Actualmente, Android concede automáticamente


este permiso. Las versiones futuras de Android requerirán que una aplicación solicite este permiso antes de que se
le conceda el permiso.

Resumen
En este artículo se presentaron algunas de las nuevas API que están disponibles en Android 4,1 (nivel de API 16).
Resaltó algunos cambios para animaciones y animando el lanzamiento de una actividad, e incorporó las nuevas
API para la detección de redes de otros dispositivos mediante protocolos como Bonjour o UPnP. También se
resaltan otros cambios en la API, como la capacidad de cortar y pegar datos a través de la intención, la capacidad
de usar los servicios aislados o los proveedores de contenido "inestables".
Este artículo se ha pasado a presentar las actualizaciones a las notificaciones y se han explicado algunos de los
nuevos permisos que se han introducido en Android 4,1

Vínculos relacionados
Ejemplo de animación de tiempo (ejemplo)
API de Android 4,1
Tareas y pilas de retroceso
Navegación con atrás y arriba
Características del bocadillo de helado
16/08/2019 • 6 minutes to read • Edit Online

En este artículo se describen algunas de las nuevas características disponibles para los desarrolladores de
aplicaciones con la API de Android 4, el bocadillo de helado. Abarca varias nuevas tecnologías de interfaz de
usuario y, a continuación, examina una variedad de nuevas funcionalidades que Android 4 ofrece para compartir
datos entre aplicaciones y entre dispositivos.

Información general
La versión 4,0 del SO Android (nivel de API 14) representa un retrabajo importante del sistema operativo Android
e incluye una serie de cambios importantes y actualizaciones, entre los que se incluyen:
Interfaz de usuario actualizada : varias características nuevas de la interfaz de usuario proporcionan a los
desarrolladores más capacidad y flexibilidad cuando crean interfaces de usuario de la aplicación. Estas nuevas
características incluyen: GridLayout , PopupMenu , Switch widget y TextureView .
Mejor aceleración de hardware : ahora, la representación en 2D tiene lugar en la GPU para todos los
controles de Android. Además, la aceleración de hardware está activada de forma predeterminada en todas las
aplicaciones desarrolladas para Android 4,0.
Nuevas API de datos : hay un nuevo acceso a los datos a los que no se podía tener acceso oficialmente, como
los datos de calendario y el perfil de usuario del propietario del dispositivo.
Uso compartido de datos de aplicaciones: compartir datos entre aplicaciones y dispositivos es ahora más fácil
que nunca mediante ShareActionProvider tecnologías como, lo que facilita la creación de una acción de uso
compartido desde un barra de acciones y el haz de Android para el campo Near Communications (NFC ) , que
lo convierte en un complemento para compartir datos entre dispositivos en estrecha proximidad entre sí.
En este artículo, vamos a explorar estas características y otros cambios que se han realizado en la API de Android
4,0 y explicaremos cómo usar cada característica con Xamarin. Android.

Características de la interfaz de usuario


Hay una variedad de nuevas tecnologías de interfaz de usuario disponibles con Android 4, entre las que se
incluyen:
GridLayout : admite el diseño de cuadrícula 2D de los controles.
Widget de conmutador : permite alternar entre activado o desactivado.
TextureView : habilita el contenido de vídeo y OpenGL en una vista.
Barra de navegación : contiene botones virtuales para la parte posterior, la Página principal y la multitarea.
Además, se han mejorado otros elementos de la
<a href"/guides/android/user_interface/popup_menus">PopupMenu</a> interfaz de usuario, como, que ahora es más
fácil de trabajar, y pestañas, que tienen un aspecto más pulido.

Compartir características
Android 4 incluye varias tecnologías nuevas que nos permiten compartir datos entre dispositivos y aplicaciones.
También proporciona acceso a varios tipos de datos que no estaban disponibles anteriormente, como información
de calendario y el perfil de usuario del propietario del dispositivo. En esta sección, examinaremos una variedad de
características que ofrece Android 4 que abordan estas áreas, entre las que se incluyen:
Carretera de Android : permite el uso compartido de datos a través de NFC.
ShareActionProvider : crea un proveedor que permite a los desarrolladores especificar acciones de uso
compartido desde el barra de acciones.
Perfil de usuario : proporciona acceso a los datos de perfil del propietario del dispositivo.
Calendar API : proporciona acceso a los datos de calendario desde el proveedor de calendario.

Emuladores x86
ICS todavía no admite el desarrollo con un emulador de x86. los emuladores x86 solo se admiten con Android
2.3.3, nivel de API 10. Para obtener más información, consulte configuración del emulador de x86 .

Resumen
En este artículo se han tratado varias tecnologías nuevas que ahora están disponibles con Android 4. Hemos
revisado nuevas características de la interfaz de usuario, como GridLayout, popupMenuy Switch widget. También
analizamos parte de la nueva compatibilidad para controlar la interfaz de usuario del sistema, así como cómo
trabajar con TextureView. A continuación, analizamos una serie de nuevas tecnologías de uso compartido. Hemos
explicado cómo el haz de Android permite compartir información entre dispositivos que usan NFC, se ha
EXPLICAdo la nueva API de calendarioy también se ha mostrado cómo usar la ShareActionProviderintegrada. Por
último, hemos examinado cómo usar el proveedor ContactsContract para acceder a los datos de Perfil de usuario.

Vínculos relacionados
Ejemplos de sandwich de helado
TextureViewDemo (sample)
CalendarDemo (ejemplo)
Tutorial de diseño de pestañas
Bocadillo de helado
Plataforma Android 4,0
Introducción a ContentProviders
31/07/2019 • 4 minutes to read • Edit Online

El sistema operativo Android usa proveedores de contenido para facilitar el acceso a datos compartidos, como
archivos multimedia, contactos e información de calendario. En este artículo se presenta la clase ContentProvider
y se proporcionan dos ejemplos de cómo usarla.

Introducción a los proveedores de contenido


Un ContentProvider encapsula un repositorio de datos y proporciona una API para acceder a él. El proveedor
existe como parte de una aplicación de Android que normalmente también proporciona una interfaz de usuario
para mostrar o administrar los datos. La principal ventaja de utilizar un proveedor de contenido es que permite a
otras aplicaciones acceder fácilmente a los datos encapsulados mediante un objeto de cliente de proveedor
(denominado ContentResolver devuelvan). Juntos, un proveedor de contenido y un solucionador de contenido
ofrecen una API coherente entre aplicaciones para el acceso a los datos que es fácil de compilar y consumir.
Cualquier aplicación puede optar por ContentProviders usar para administrar datos internamente y también para
exponerlo a otras aplicaciones.
También ContentProvider es necesario que la aplicación proporcione sugerencias de búsqueda personalizadas, o
bien, si desea proporcionar la capacidad de copiar datos complejos desde la aplicación para pegarlos en otras
aplicaciones. En este documento se muestra cómo obtener acceso ContentProviders y compilar con Xamarin.
Android.
La estructura de esta sección es la siguiente:
Cómo funciona Información general de ContentProvider lo que se ha diseñado para y cómo funciona. –
Consumir un proveedor de contenido – Ejemplo de acceso a la lista de contactos.
Uso de ContentProvider para compartir datos Escribir y consumir ContentProvider en la misma
aplicación. –
ContentProviders y los cursores que operan sobre sus datos se suelen usar para rellenar los controles ListView.
Consulte la Guía de ListView y adaptadores para obtener más información sobre cómo usar esas clases.
ContentProviders expuesto por Android (u otras aplicaciones) es una manera fácil de incluir datos de otros
orígenes en la aplicación. Permiten obtener acceso y presentar datos como la lista de contactos, fotos o eventos de
calendario desde dentro de la aplicación, y dejar que el usuario interactúe con los datos.
Personalizar ContentProviders es una manera cómoda de empaquetar los datos para su uso en su propia
aplicación, o para su uso por parte de otras aplicaciones (incluidos los usos especiales como la búsqueda
personalizada y copiar y pegar).
En los temas de esta sección se proporcionan algunos ejemplos sencillos del uso ContentProvider y la escritura de
código.

Vínculos relacionados
Demostración de ContactsAdapter (ejemplo)
SimpleContentProvider (ejemplo)
Guía para desarrolladores de proveedores de contenido
Referencia de la clase ContentProvider
Referencia de la clase ContentResolver devuelvan
Referencia de clases de ListView
CursorAdapter (referencia de clase)
Referencia de la clase UriMatcher
Android.Provider
Referencia de la clase ContactsContract
Cómo funcionan los proveedores de contenido
16/08/2019 • 6 minutes to read • Edit Online

Hay dos clases implicadas en una ContentProvider interacción:


ContentProvider – Implementa una API que expone un conjunto de datos de forma estándar. Los métodos
principales son Query, INSERT, Update y DELETE.
ContentResolver devuelvan Proxy estático que se comunica con un ContentProvider para tener acceso a
sus datos, desde dentro de la misma aplicación o desde otra aplicación. –
Normalmente, un proveedor de contenido está respaldado por una base de datos de SQLite, pero la API significa
que no es necesario que el código de consumo sepa nada sobre el SQL subyacente. Las consultas se realizan a
través de un URI mediante el uso de constantes para hacer referencia a nombres de columna (para reducir las
dependencias ICursor de la estructura de datos subyacente) y se devuelve una para que el código de consumo
realice la iteración.

Consumir un ContentProvider
ContentProviders exponga su funcionalidad a través de un URI que esté registrado en el archivo
AndroidManifest. XML de la aplicación que publica los datos. Existe una Convención en la que el URI y las
columnas de datos que se exponen deben estar disponibles como constantes para facilitar el enlace a los datos. La
funcionalidad integrada ContentProviders de Android proporciona clases útiles con constantes que hacen
referencia a la estructura de datos en Android.Providers el espacio de nombres.
Proveedores integrados
Android ofrece acceso a una amplia gama de datos de usuario y del ContentProviders sistema mediante:
Explorador de marcadores e historial del explorador (requiere permisos READ_HISTORY_BOOKMARKS y/o
WRITE_HISTORY_BOOKMARKS ). –

CallLog – llamadas recientes realizadas o recibidas con el dispositivo.


Contactos de – información detallada de la lista de contactos del usuario, que incluye personas, teléfonos,
fotos & grupos.
Mediastore – contenido del dispositivo del usuario: audio (álbumes, intérpretes, géneros, listas de
reproducción), imágenes (incluidas las miniaturas) & vídeo.
Configuración de – opciones y preferencias de configuración de dispositivos en todo el sistema.
UserDictionary – contenido del diccionario definido por el usuario que se usa para la entrada de texto
predictivo.
Correo de voz – historial de mensajes de correo de voz.

Información general sobre clases


A continuación se muestran las clases principales que ContentProvider se usan al trabajar con un:
En este diagrama, ContentProvider implementa las consultas y registra el URI del URI que otras aplicaciones usan
para buscar datos. Actúa como ' proxy ' ContentProvider para (métodos de consulta, inserción, actualización y
eliminación). ContentResolver Contiene SQLiteOpenHelper los datos que usa, ContentProvider pero no se expone
directamente a las aplicaciones de consumo. Pasa el cursor devuelto ContentResolver por que se va a mostrar
ListView en. CursorAdapter UriMatcher Es una clase auxiliar que analiza los URI al procesar las consultas.

A continuación se describe el propósito de cada clase:


ContentProvider – Implemente los métodos de esta clase abstracta para exponer los datos. La API se pone
a disposición de otras clases y aplicaciones a través del atributo URI que se agrega a la definición de clase.
SQLiteOpenHelper Ayuda a implementar el almacén de almacenes de los almacenes de ContentProvider
los mismos que expone. –
UriMatcher – Use en UriMatcher su ContentProvider implementación de para ayudar a administrar los URI
que se usan para consultar el contenido.
ContentResolver devuelvan El uso de código utiliza ContentResolver un para tener ContentProvider
acceso a una instancia de. – Las dos clases se encargan de los problemas de comunicación entre procesos, lo
que permite que los datos se compartan fácilmente entre las aplicaciones. El consumo de código nunca crea
ContentProvider una clase explícita; en su lugar, se obtiene acceso a los datos mediante la creación de un
cursor basado en un ContentProvider URI expuesto por la aplicación.
CursorAdapter – ContentProvider Use CursorAdapter o paramostrarlosdatosalosquesetiene
SimpleCursorAdapter acceso a través de.

La ContentProvider API permite a los consumidores realizar una serie de operaciones en los datos, como:
Consultar los datos para devolver listas o registros individuales.
Modifique los registros individuales.
Agregar nuevos registros.
Eliminar registros.
Este documento contiene un ejemplo que usa un proporcionado ContentProvider por el sistema, así como un
ejemplo simple de solo lectura que implementa un personalizado. ContentProvider
Uso de ContentProvider de contactos
16/08/2019 • 9 minutes to read • Edit Online

El código que utiliza los datos de Access ContentProvider expuestos por no requiere una referencia
ContentProvider a la clase. En su lugar, se usa un URI para crear un cursor sobre los datos expuestos por
ContentProvider . Android usa el URI para buscar en el sistema la aplicación que expone un ContentProvider con
ese identificador. El URI es una cadena, normalmente en un formato DNS inverso como
com.android.contacts/data .

En lugar de que los desarrolladores recuerden esta cadena, el proveedor de contactos de Android expone sus
android.provider.ContactsContract metadatos en la clase. Esta clase se usa para determinar el URI de
ContentProvider , así como los nombres de las tablas y columnas que se pueden consultar.

Algunos tipos de datos también requieren permisos especiales para obtener acceso a. La lista de contactos
integrada requiere el android.permission.READ_CONTACTS permiso en el archivo archivo AndroidManifest. XML .
Hay tres maneras de crear un cursor a partir del URI:
1. ManagedQuery () El enfoque preferido en Android 2,3 (nivel de API 10) y versiones anteriores
ManagedQuery , devuelve un cursor y también administra automáticamente la actualización de los datos y el
cierre del cursor. – Este método está en desuso en Android 3,0 (nivel de API 11).
2. ContentResolver devuelvan. Query () – Devuelve un cursor no administrado, lo que significa que debe
actualizarse y cerrarse explícitamente en el código.
3. CursorLoader (). LoadInBackground () – introducido en Android 3,0 (nivel de API 11) CursorLoader , es
ahora ContentProvider la manera preferida de usar. CursorLoader``ContentResolver consulta en un
subproceso en segundo plano para que la interfaz de usuario no se bloquee. Se puede tener acceso a esta
clase en versiones anteriores de Android mediante la biblioteca de compatibilidad de V4.
Cada uno de estos métodos tiene el mismo conjunto básico de entradas:
Identificador URI – Nombre completo ContentProvider del.
Proyección de – Especificación de las columnas que se van a seleccionar para el cursor.
Selección de Similar a una cláusula WHERE SQL. –
SelectionArgs – Parámetros que se van a sustituir en la selección.
SortOrder – Columnas por las que se va a ordenar.

Crear entradas para una consulta


El ContactsProvider código de ejemplo realiza una consulta muy sencilla en el proveedor de contactos integrado
de Android. No es necesario conocer los nombres de columna o URI reales; toda la información necesaria para
consultar los contactos ContentProvider está disponible como constantes expuestas por la ContactsContract clase.
Independientemente del método que se use para recuperar el cursor, estos mismos objetos se utilizan como
parámetros como se muestra en el archivo ContactsProvider/ContactsAdapter. CS :
var uri = ContactsContract.Contacts.ContentUri;
string[] projection = {
ContactsContract.Contacts.InterfaceConsts.Id,
ContactsContract.Contacts.InterfaceConsts.DisplayName,
ContactsContract.Contacts.InterfaceConsts.PhotoId,
};

En este ejemplo selection ,, selectionArgs y sortOrder se omitirán estableciéndolo en null .

Crear un cursor a partir de un URI del proveedor de contenido


Una vez creados los objetos de parámetro, se pueden usar en una de las tres maneras siguientes:
Usar una consulta administrada
Las aplicaciones que tienen como destino Android 2,3 (nivel de API 10) o una versión anterior deben usar este
método:

var cursor = activity.ManagedQuery(uri, projection, null, null, null);

Este cursor será administrado por Android, por lo que no es necesario cerrarlo.
Usar ContentResolver devuelvan
El acceso ContentProvider directo a para obtener un cursor en puede realizarse de la siguiente manera:
ContentResolver

var cursor = activity.ContentResolver(uri, projection, null, null, null);

Este cursor no está administrado, por lo que debe cerrarse cuando ya no se necesite. Asegúrese de que el código
cierra un cursor abierto; de lo contrario, se producirá un error.

cursor.Close();

Como alternativa, puede llamar StartManagingCursor() a y StopManagingCursor() a "administrar" el cursor. Los


cursores administrados se desactivan automáticamente y se vuelven a consultar cuando se detienen y reinician las
actividades.
Usar CursorLoader
Las aplicaciones compiladas para Android 3,0 (nivel de API 11) o más recientes deben usar este método:

var loader = new CursorLoader (activity, uri, projection, null, null, null);
var cursor = (ICursor)loader.LoadInBackground();

El CursorLoader garantiza que todas las operaciones de cursor se realicen en un subproceso en segundo plano y
puede volver a usar de forma inteligente un cursor existente entre instancias de actividad cuando se reinicie una
actividad (por ejemplo, debido a un cambio en la configuración) en lugar de volver a cargar los datos de nuevo.
Las versiones anteriores de Android también pueden CursorLoader usar la clase mediante las bibliotecas de
compatibilidad de V4.

Mostrar los datos del cursor con un adaptador personalizado


Para mostrar la imagen de contacto, usaremos un adaptador personalizado para que podamos resolver
manualmente la PhotoId referencia a una ruta de acceso al archivo de imagen.
Para mostrar los datos con un adaptador personalizado, en el ejemplo CursorLoader se usa para recuperar todos
los datos de contacto en una colección local en el método FillContacts de ContactsProvider/ContactsAdapter.
CS:

void FillContacts ()
{
var uri = ContactsContract.Contacts.ContentUri;
string[] projection = {
ContactsContract.Contacts.InterfaceConsts.Id,
ContactsContract.Contacts.InterfaceConsts.DisplayName,
ContactsContract.Contacts.InterfaceConsts.PhotoId
};
// CursorLoader introduced in Honeycomb (3.0, API11)
var loader = new CursorLoader(activity, uri, projection, null, null, null);
var cursor = (ICursor)loader.LoadInBackground();
contactList = new List<Contact> ();
if (cursor.MoveToFirst ()) {
do {
contactList.Add (new Contact{
Id = cursor.GetLong (cursor.GetColumnIndex (projection [0])),
DisplayName = cursor.GetString (cursor.GetColumnIndex (projection [1])),
PhotoId = cursor.GetString (cursor.GetColumnIndex (projection [2]))
});
} while (cursor.MoveToNext());
}
}

A continuación, implemente los métodos de contactList BaseAdapter mediante la colección. El adaptador se


implementa tal como lo haría con cualquier otra colección – , por lo que no hay ningún control especial en este
caso porque los datos proceden de un: ContentProvider
Activity activity;
public ContactsAdapter (Activity activity)
{
this.activity = activity;
FillContacts ();
}
public override int Count {
get { return contactList.Count; }
}
public override Java.Lang.Object GetItem (int position)
{
return null; // could wrap a Contact in a Java.Lang.Object to return it here if needed
}
public override long GetItemId (int position)
{
return contactList [position].Id;
}
public override View GetView (int position, View convertView, ViewGroup parent)
{
var view = convertView ?? activity.LayoutInflater.Inflate (Resource.Layout.ContactListItem, parent, false);
var contactName = view.FindViewById<TextView> (Resource.Id.ContactName);
var contactImage = view.FindViewById<ImageView> (Resource.Id.ContactImage);
contactName.Text = contactList [position].DisplayName;
if (contactList [position].PhotoId == null) {
contactImage = view.FindViewById<ImageView> (Resource.Id.ContactImage);
contactImage.SetImageResource (Resource.Drawable.ContactImage);
} else {
var contactUri = ContentUris.WithAppendedId (ContactsContract.Contacts.ContentUri, contactList
[position].Id);
var contactPhotoUri = Android.Net.Uri.WithAppendedPath (contactUri, Contacts.Photos.ContentDirectory);
contactImage.SetImageURI (contactPhotoUri);
}
return view;
}

Se muestra la imagen (si existe) mediante el URI del archivo de imagen en el dispositivo. La aplicación tiene el
siguiente aspecto:
Con un patrón de código similar, la aplicación puede acceder a una amplia variedad de datos del sistema, como
fotos, vídeos y música del usuario. Algunos tipos de datos requieren permisos especiales para ser solicitados en el
archivo archivo AndroidManifest. XMLdel proyecto.

Mostrar los datos del cursor con un SimpleCursorAdapter


También se puede mostrar el cursor con un SimpleCursorAdapter (aunque solo se mostrará el nombre, no la foto).
Este código muestra cómo usar un ContentProvider con SimpleCursorAdapter (este código no aparece en el
ejemplo):

var uri = ContactsContract.Contacts.ContentUri;


string[] projection = {
ContactsContract.Contacts.InterfaceConsts.Id,
ContactsContract.Contacts.InterfaceConsts.DisplayName
};
var loader = new CursorLoader (this, uri, projection, null, null, null);
var cursor = (ICursor)loader.LoadInBackground();
var fromColumns = new string[] {ContactsContract.Contacts.InterfaceConsts.DisplayName};
var toControlIds = new int[] {Android.Resource.Id.Text1};
adapter = new SimpleCursorAdapter (this, Android.Resource.Layout.SimpleListItem1, cursor, fromColumns,
toControlsIds);
listView.Adapter = adapter;

Consulte los adaptadores y los controles ListView para obtener más información sobre la SimpleCursorAdapter
implementación de.

Vínculos relacionados
Demostración de ContactsAdapter (ejemplo)
Creación de un ContentProvider personalizado
31/07/2019 • 16 minutes to read • Edit Online

En la sección anterior se mostró cómo consumir datos de una implementación de ContentProvider integrada. En
esta sección se explicará cómo crear un ContentProvider personalizado y, a continuación, utilizar sus datos.

Acerca de ContentProviders
Una clase de proveedor de contenido debe ContentProvider heredar de. Debe constar de un almacén de datos
interno que se utiliza para responder a las consultas y debe exponer los URI y los tipos MIME como constantes
para ayudar a utilizar el código para realizar solicitudes válidas de datos.
URI (autoridad)
ContentProviders se tiene acceso a ellos en Android mediante un URI. Una aplicación que expone un
ContentProvider establece los identificadores URI a los que responderá en su archivo archivo AndroidManifest.
XML . Cuando se instala la aplicación, estos URI se registran para que otras aplicaciones puedan tener acceso a
ellos.
En mono para Android, la clase de proveedor de contenido debe [ContentProvider] tener un atributo para
especificar el URI (o URI) que se debe agregar a archivo AndroidManifest. XML.
Tipo MIME
El formato típico de los tipos MIME consta de dos partes. Android ContentProviders suele usar estas dos cadenas
para la primera parte del tipo MIME:
1. vnd.android.cursor.item para representar una sola fila, use la ContentResolver.CursorItemBaseType constante
en el código. –
2. vnd.android.cursor.dir en el caso de varias filas ContentResolver.CursorDirBaseType , utilice la constante en
el código. –
La segunda parte del tipo MIME es específica de la aplicación y debe usar un estándar DNS inverso con un vnd.
prefijo. En el código de vnd.com.xamarin.sample.Vegetables ejemplo se usa.
Metadatos del modelo de datos
El consumo de aplicaciones necesita construir consultas URI para tener acceso a diferentes tipos de datos. El URI
base se puede expandir para hacer referencia a una tabla de datos determinada y también puede incluir
parámetros para filtrar los resultados. También se deben declarar las columnas y cláusulas utilizadas con el cursor
resultante para mostrar los datos.
Para asegurarse de que solo se construyen las consultas URI válidas, es un valor personalizado para proporcionar
las cadenas válidas como valores constantes. Esto facilita el ContentProvider acceso a porque hace que los valores
se puedan detectar a través de la finalización del código y evita errores tipográficos en las cadenas.
En el ejemplo anterior, android.provider.ContactsContract la clase exponía los metadatos de los datos de contactos.
En nuestro Custom ContentProvider , solo se expondrán las constantes de la propia clase.

Implementación
Hay tres pasos para crear y utilizar un personalizado ContentProvider :
1. Crear una clase de base de datos – Implemente SQLiteOpenHelper .
2. Cree una ContentProvider clase – que ContentProvider implemente con una instancia de la base de datos,
metadatos expuestos como métodos y valores constantes para tener acceso a los datos.
3. El ContentProvider acceso a a través de su URI – rellena ContentProvider un CursorAdapter mediante el,
al que se tiene acceso a través de su URI.
Tal y como se ContentProviders ha explicado anteriormente, se puede usar desde otras aplicaciones que no sean
donde están definidas. En este ejemplo, los datos se consumen en la misma aplicación, pero tenga en cuenta que
otras aplicaciones también pueden tener acceso a él siempre que conozcan el URI e información sobre el esquema
(que normalmente se expone como valores constantes).

Crear una base de datos


La ContentProvider mayoría de las implementaciones se basarán en una SQLite base de datos. El código de base
de datos de ejemplo de SimpleContentProvider/VegetableDatabase. CS crea una base de datos de dos
columnas muy simple, como se muestra a continuación:

class VegetableDatabase : SQLiteOpenHelper {


const string create_table_sql =
"CREATE TABLE [vegetables] ([_id] INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL UNIQUE, [name] TEXT NOT NULL
UNIQUE)";
const string DatabaseName = "vegetables.db";
const int DatabaseVersion = 1;

public VegetableDatabase(Context context) : base(context, DatabaseName, null, DatabaseVersion) { }


public override void OnCreate(SQLiteDatabase db)
{
db.ExecSQL(create_table_sql);
// seed with data
db.ExecSQL("INSERT INTO vegetables (name) VALUES ('Vegetables')");
db.ExecSQL("INSERT INTO vegetables (name) VALUES ('Fruits')");
db.ExecSQL("INSERT INTO vegetables (name) VALUES ('Flower Buds')");
db.ExecSQL("INSERT INTO vegetables (name) VALUES ('Legumes')");
db.ExecSQL("INSERT INTO vegetables (name) VALUES ('Bulbs')");
db.ExecSQL("INSERT INTO vegetables (name) VALUES ('Tubers')");
}
public override void OnUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
throw new NotImplementedException();
}
}

La implementación de base de datos en sí no necesita ninguna consideración especial que se ContentProvider


exponga con, sin embargo, si piensa ContentProvider's enlazar los ListView datos a un control, una columna de
_id entero única denominada debe formar parte de la conjunto de resultados. Vea el documento sobre ListView y
adaptadores para obtener más detalles sobre el uso ListView del control.

Crear ContentProvider
En el resto de esta sección se proporcionan instrucciones paso a paso sobre cómo se compiló la clase de ejemplo
SimpleContentProvider/VegetableProvider. CS .
Inicializar la base de datos
El primer paso es crear una subclase ContentProvider y agregar la base de datos que se va a utilizar.
public class VegetableProvider : ContentProvider
{
VegetableDatabase vegeDB;
public override bool OnCreate()
{
vegeDB = new VegetableDatabase(Context);
return true;
}
}

El resto del código formará la implementación del proveedor de contenido real que permite detectar y consultar los
datos.

Agregar metadatos para consumidores


Hay cuatro tipos diferentes de metadatos que se van a exponer en la ContentProvider clase. Solo se requiere la
autoridad; el resto se realiza por Convención.
Entidad de certificación El atributo se debe agregar a la clase para que se registre con Android cuando se
instale la aplicación. – ContentProvider
Identificador URI – Seexponecomounaconstanteparaqueseafácilde CONTENT_URI usar en el código. Debe
coincidir con la autoridad, pero incluir el esquema y la ruta de acceso base.
Tipos MIME – Las listas de resultados y los resultados únicos se tratan como tipos de contenido diferentes,
por lo que definimos dos tipos MIME para representarlos.
InterfaceConsts – Proporcione un valor constante para cada nombre de columna de datos, de modo que el
código utilizado pueda detectar fácilmente y hacer referencia a ellos sin arriesgarse a que se produzcan
errores tipográficos.
En este código se muestra cómo se implementa cada uno de estos elementos y se agregan a la definición de la
base de datos del paso anterior:

[ContentProvider(new string[] { CursorTableAdapter.VegetableProvider.AUTHORITY })]


public class VegetableProvider : ContentProvider
{
public const string AUTHORITY = "com.xamarin.sample.VegetableProvider";
static string BASE_PATH = "vegetables";
public static readonly Android.Net.Uri CONTENT_URI = Android.Net.Uri.Parse("content://" + AUTHORITY + "/" +
BASE_PATH);
// MIME types used for getting a list, or a single vegetable
public const string VEGETABLES_MIME_TYPE = ContentResolver.CursorDirBaseType +
"/vnd.com.xamarin.sample.Vegetables";
public const string VEGETABLE_MIME_TYPE = ContentResolver.CursorItemBaseType +
"/vnd.com.xamarin.sample.Vegetables";
// Column names
public static class InterfaceConsts {
public const string Id = "_id";
public const string Name = "name";
}
VegetableDatabase vegeDB;
public override bool OnCreate()
{
vegeDB = new VegetableDatabase(Context);
return true;
}
}
Implementar la aplicación auxiliar de análisis de URI
Dado que el código de consumo utiliza los URI para realizar ContentProvider solicitudes de un, es necesario poder
analizar esas solicitudes para determinar qué datos se deben devolver. La UriMatcher clase puede ayudar a
analizar los URI, una vez que se ha inicializado con los patrones de ContentProvider URI que admite.
UriMatcher En el ejemplo se inicializará con dos URI:
1. "com. Xamarin. sample. VegetableProvider/verduras" – solicitud para devolver la lista completa de verduras.
2. "com. Xamarin. sample. VegetableProvider/verduras/#" – , donde # es un marcador de posición para un
parámetro numérico _id (el de la fila de la base de datos). También se puede usar un*marcador de posición
de asterisco ("") para hacer coincidir un parámetro de texto.
En el código usamos las constantes para hacer referencia a los valores de metadatos como la autoridad_y la ruta de
acceso base. Los códigos de retorno se utilizarán en métodos que realizan análisis de URI, para determinar qué
datos se devuelven.

const int GET_ALL = 0; // return code when list of Vegetables requested


const int GET_ONE = 1; // return code when a single Vegetable is requested by ID
static UriMatcher uriMatcher = BuildUriMatcher();
static UriMatcher BuildUriMatcher()
{
var matcher = new UriMatcher(UriMatcher.NoMatch);
// Uris to match, and the code to return when matched
matcher.AddURI(AUTHORITY, BASE_PATH, GET_ALL); // all vegetables
matcher.AddURI(AUTHORITY, BASE_PATH + "/#", GET_ONE); // specific vegetable by numeric ID
return matcher;
}

Este código es privado para la ContentProvider clase. Consulte la documentación de UriMatcher de Google para
obtener más información.

Implementación de QueryMethod
El ContentProvider método más sencillo para implementar es el Query método. UriMatcher En la implementación
siguiente se usa para analizar uri el parámetro y llamar al método de base de datos correcto. Si contiene un
parámetro de identificador, se analiza el entero (mediante LastPathSegment ) y se usa en la consulta de la base de
datos. uri
public override Android.Database.ICursor Query(Android.Net.Uri uri, string[] projection, string selection,
string[] selectionArgs, string sortOrder)
{
switch (uriMatcher.Match(uri)) {
case GET_ALL:
return GetFromDatabase();
case GET_ONE:
var id = uri.LastPathSegment;
return GetFromDatabase(id); // the ID is the last part of the Uri
default:
throw new Java.Lang.IllegalArgumentException("Unknown Uri: " + uri);
}
}
Android.Database.ICursor GetFromDatabase()
{
return vegeDB.ReadableDatabase.RawQuery("SELECT _id, name FROM vegetables", null);
}
Android.Database.ICursor GetFromDatabase(string id)
{
return vegeDB.ReadableDatabase.RawQuery("SELECT _id, name FROM vegetables WHERE _id = " + id, null);
}

También GetType se debe reemplazar el método. Se puede llamar a este método para determinar el tipo de
contenido que se devolverá para un URI determinado. Esto puede indicar a la aplicación que lo consume cómo
controlar los datos.

public override String GetType(Android.Net.Uri uri)


{
switch (uriMatcher.Match(uri)) {
case GET_ALL:
return VEGETABLES_MIME_TYPE; // list
case GET_ONE:
return VEGETABLE_MIME_TYPE; // single item
default:
throw new Java.Lang.IllegalArgumentExceptoin ("Unknown Uri: " + uri);
}
}

Implementar las otras invalidaciones


Nuestro sencillo ejemplo no permite la edición o eliminación de datos, pero los métodos INSERT, Update y
DELETE deben implementarse de modo que se agreguen sin una implementación:

public override int Delete(Android.Net.Uri uri, string selection, string[] selectionArgs)


{
throw new Java.Lang.UnsupportedOperationException();
}
public override Android.Net.Uri Insert(Android.Net.Uri uri, ContentValues values)
{
throw new Java.Lang.UnsupportedOperationException();
}
public override int Update(Android.Net.Uri uri, ContentValues values, string selection, string[] selectionArgs)
{
throw new Java.Lang.UnsupportedOperationException();
}

Esto completa la implementación básica ContentProvider . Una vez instalada la aplicación, los datos que expone
estarán disponibles tanto dentro de la aplicación como en cualquier otra aplicación que conozca el URI para hacer
referencia a ella.
Acceso a ContentProvider
VegetableProvider Una vez implementado, el acceso a él se realiza del mismo modo que el proveedor de contactos
al principio de este documento: obtener un cursor con el URI especificado y, a continuación, utilizar un adaptador
para tener acceso a los datos.

Enlazar un control ListView a un ContentProvider


Para rellenar un ListViewcon datos, usamos el URI que corresponde a la lista sin filtrar de verduras. En el código,
usamos el valor VegetableProvider.CONTENT_URI constante, que sabemos que se resuelve como.
com.xamarin.sample.vegetableprovider/vegetables Nuestra VegetableProvider.Query implementación devolverá un
cursor que se puede enlazar ListView a.
El código de SimpleContentProvider/HomeScreen.cs muestra lo sencillo que es mostrar los datos de un
ContentProvider :

listView = FindViewById<ListView>(Resource.Id.List);
string[] projection = new string[] { VegetableProvider.InterfaceConsts.Id,
VegetableProvider.InterfaceConsts.Name} ;
string[] fromColumns = new string[] { VegetableProvider.InterfaceConsts.Name };
int[] toControlIds = new int[] { Android.Resource.Id.Text1 };

// CursorLoader introduced in Honeycomb (3.0, API_11)


var loader = new CursorLoader(this,
VegetableProvider.CONTENT_URI, projection, null, null, null);
cursor = (ICursor)loader.LoadInBackground();

// Create a SimpleCursorAdapter
adapter = new SimpleCursorAdapter(this, Android.Resource.Layout.SimpleListItem1, cursor, fromColumns,
toControlIds);
listView.Adapter = adapter;

La aplicación resultante tiene el siguiente aspecto:


Recuperar un único elemento de un ContentProvider
Una aplicación consumidora también podría querer tener acceso a filas de datos individuales, lo que se puede
hacer mediante la construcción de un URI diferente que haga referencia a una fila concreta (por ejemplo,).
Use ContentResolver directamente para tener acceso a un único elemento, mediante la creación de un URI Id con
el requerido.

Uri.WithAppendedPath(VegetableProvider.CONTENT_URI, id.ToString());

El método completo tiene el siguiente aspecto:

protected void OnListItemClick(object sender, AdapterView.ItemClickEventArgs e)


{
var id = e.Id;
string[] projection = new string[] { "name" };
var uri = Uri.WithAppendedPath(VegetableProvider.CONTENT_URI, id.ToString());
ICursor vegeCursor = ContentResolver.Query(uri, projection, null, new string[] { id.ToString() }, null);
string text = "";
if (vegeCursor.MoveToFirst()) {
text = vegeCursor.GetInt(0) + " " + vegeCursor.GetString(1);
Android.Widget.Toast.MakeText(this, text, Android.Widget.ToastLength.Short).Show();
}
vegeCursor.Close();
}

Vínculos relacionados
SimpleContentProvider (ejemplo)
Asignaciones y ubicación en Android
27/07/2019 • 2 minutes to read • Edit Online

Servicios de ubicación
En esta guía se presenta el reconocimiento de la ubicación en las aplicaciones de Android y se muestra cómo
obtener la ubicación del usuario mediante la API del servicio de ubicación de Android, así como el proveedor de
ubicaciones con fusibles disponible con Google Location Services API.

Mapas
En este artículo se describe cómo usar las asignaciones y la ubicación con Xamarin. Android. Abarca todo, desde el
aprovechamiento de la aplicación de mapas integrada hasta el uso de Google Maps Android API V2 directamente.
Además, se explica cómo usar una sola API para trabajar con los servicios de ubicación, lo que permite a una
aplicación obtener correcciones de ubicación a través de la ubicación de la torre de celda, Wi-Fi o GPS.
Servicios de ubicación en Android
16/08/2019 • 27 minutes to read • Edit Online

En esta guía se presenta el reconocimiento de ubicación en las aplicaciones de Android y se muestra cómo obtener
la ubicación del usuario mediante la API del servicio de ubicación de Android, así como el proveedor de
ubicaciones con fusibles disponible con Google Location Services API.
Android proporciona acceso a varias tecnologías de ubicación como la ubicación de la torre de celda, Wi-Fi y GPS.
Los detalles de cada tecnología de ubicación se abstraen a través de los proveedores de ubicación, lo que permite
que las aplicaciones obtengan ubicaciones de la misma manera, independientemente del proveedor que se use. En
esta guía se presenta el proveedor de ubicación con fusibles, una parte de la Google Play Services, que determina
de forma inteligente la mejor manera de obtener la ubicación de los dispositivos en función de qué proveedores
están disponibles y cómo se usa el dispositivo. API del servicio de ubicación de Android y muestra cómo
comunicarse con el servicio de ubicación LocationManager del sistema mediante. La segunda parte de la guía
explora el Location Services API Android mediante LocationManager .
Como norma general, las aplicaciones prefieren usar el proveedor de ubicación con fusibles, revirtiendo la antigua
API del servicio de ubicación de Android solo cuando sea necesario.

Aspectos básicos de la ubicación


En Android, independientemente de la API que elija para trabajar con los datos de ubicación, varios conceptos
siguen siendo los mismos. En esta sección se presentan los proveedores de ubicación y los permisos relacionados
con la ubicación.
Proveedores de ubicación
Se usan varias tecnologías internamente para identificar la ubicación del usuario. El hardware utilizado depende
del tipo de proveedor de ubicación seleccionado para el trabajo de recopilación de datos. Android usa tres
proveedores de Ubicación:
Proveedor de GPS – GPS ofrece la ubicación más precisa, usa la mayor potencia y funciona mejor en el
exterior. Este proveedor usa una combinación de GPS y GPS asistido (AGPS ), que devuelve los datos de
GPS recopilados por las torres de telefonía móvil.
Proveedor de red – Proporciona una combinación de datos de Wi-Fi y móviles, incluidos los datos de
AGPS recopilados por los Torres de celdas. Utiliza menos energía que el proveedor de GPS, pero devuelve
datos de ubicación de precisión variable.
Proveedor pasivo – Una opción "superpuesta" mediante proveedores solicitados por otras aplicaciones o
servicios para generar datos de ubicación en una aplicación. Esta es una opción menos confiable pero de
ahorro de energía ideal para aplicaciones que no requieren que funcionen las actualizaciones de ubicación
constantes.
Los proveedores de ubicación no están siempre disponibles. Por ejemplo, es posible que quieramos usar GPS para
nuestra aplicación, pero GPS podría estar desactivado en la configuración o el dispositivo podría no tener GPS. Si
un proveedor específico no está disponible, la elección del proveedor podría null devolver.
Permisos de ubicación
Una aplicación con reconocimiento de ubicación necesita tener acceso a los sensores de hardware de un
dispositivo para recibir datos de GPS, Wi-Fi y móviles. El acceso se controla a través de los permisos adecuados en
el manifiesto de Android de la aplicación. Hay dos permisos disponibles – en función de los requisitos de la
aplicación y de la elección de la API, por lo que querrá permitir uno:
ACCESS_FINE_LOCATION – Permite a una aplicación tener acceso a GPS. Necesario para las opciones proveedor
de GPS y proveedor pasivo (elproveedor pasivo necesita permiso para acceder a los datos de GPS
recopilados por otra aplicación o servicio). Permiso opcional para el proveedor de red.
ACCESS_COARSE_LOCATION – Permite el acceso de una aplicación a la ubicación de red de telefonía móvil y Wi-
Fi. Requerido para el proveedor de ACCESS_FINE_LOCATION red si no se ha establecido.
En el caso de las aplicaciones que tienen como destino la versión 21 de la API (Android ACCESS_FINE_LOCATION 5,0
Lollipop) o superior, puede habilitar y seguir ejecutando en dispositivos que no tienen hardware GPS. Si su
aplicación requiere hardware GPS, debe agregar explícitamente un android.hardware.location.gps uses-feature
elemento al manifiesto de Android. Para obtener más información, consulte la referencia de elementos de
características de uso de Android.
Para establecer los permisos, expanda la carpeta propiedades en el Panel de solución y haga doble clic en
archivo AndroidManifest. XML. Los permisos se enumerarán en permisos necesarios:

Establecer cualquiera de estos permisos indica a Android que la aplicación necesita permiso del usuario para
acceder a los proveedores de ubicación. Los dispositivos que ejecutan el nivel de API 22 (Android 5,1) o inferior le
pedirán al usuario que conceda estos permisos cada vez que se instale la aplicación. En los dispositivos que
ejecutan el nivel de API 23 (Android 6,0) o superior, la aplicación debe realizar una comprobación de permisos en
tiempo de ejecución antes de realizar una solicitud del proveedor de ubicación.

NOTE
Nota: La ACCESS_FINE_LOCATION configuración implica el acceso a los datos de ubicación aproximados y finos. Nunca debe
tener que establecer ambos permisos, solo el permiso mínimo que requiere la aplicación para que funcione.

Este fragmento de código es un ejemplo de cómo comprobar que una aplicación tiene permiso para
ACCESS_FINE_LOCATION el permiso:
if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.AccessFineLocation) == Permission.Granted)
{
StartRequestingLocationUpdates();
isRequestingLocationUpdates = true;
}
else
{
// The app does not have permission ACCESS_FINE_LOCATION
}

Las aplicaciones deben ser tolerantes del escenario en el que el usuario no conceda el permiso (o que haya
revocado el permiso) y tenga una manera de solucionar correctamente esa situación. Consulte la Guía de permisos
para obtener más detalles sobre cómo implementar comprobaciones de permisos en tiempo de ejecución en
Xamarin. Android.

Usar el proveedor de ubicaciones con fusibles


El proveedor de ubicaciones fusionadas es el método preferido para que las aplicaciones de Android reciban
actualizaciones de ubicación del dispositivo, ya que de forma eficaz seleccionará el proveedor de ubicación durante
el tiempo de ejecución para proporcionar la mejor información de ubicación de manera eficaz. Por ejemplo, un
usuario que recorre el exterior obtiene la mejor ubicación de lectura con GPS. Si, a continuación, el usuario se
dirige a las puertas, donde el GPS funciona de forma deficiente (si se hace en absoluto), el proveedor de ubicación
con fusibles puede cambiar automáticamente a Wi-Fi, lo que funciona mejor en el interior.
La API del proveedor de ubicación con fusibles proporciona una variedad de otras herramientas para proporcionar
a las aplicaciones compatibles con la ubicación, incluidas la geovalla y la supervisión de actividades. En esta
sección, nos centraremos en los aspectos básicos de la configuración de, el LocationClient establecimiento de
proveedores y la obtención de la ubicación del usuario.
El proveedor de ubicaciones con fusibles forma parte de Google Play Services. El paquete de Google Play Services
debe instalarse y configurarse correctamente en la aplicación para que funcione la API del proveedor de ubicación
con fusibles, y el dispositivo debe tener instalado el Google Play Services APK.
Antes de que una aplicación de Xamarin. Android pueda usar el proveedor de ubicaciones con fusibles, debe
agregar el paquete Xamarin. GooglePlayServices. Maps al proyecto. Además, se deben agregar using las
siguientes instrucciones a cualquier archivo de código fuente que haga referencia a las clases que se describen a
continuación:

using Android.Gms.Common;
using Android.Gms.Location;

Comprobando si Google Play Services está instalado


Un Xamarin. Android se bloqueará si intenta usar el proveedor de ubicación con fusibles Cuando Google Play
Services no está instalado (o no está actualizado), de lo contrario, se produciría una excepción en tiempo de
ejecución. Si Google Play Services no está instalado, la aplicación debería revertir al servicio de ubicación de
Android descrito anteriormente. Si Google Play Services no está actualizado, la aplicación podría mostrar un
mensaje al usuario pidiéndole que actualice la versión instalada de Google Play Services.
Este fragmento de código es un ejemplo de cómo una actividad de Android puede comprobar mediante
programación si se ha instalado Google Play Services:
bool IsGooglePlayServicesInstalled()
{
var queryResult = GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(this);
if (queryResult == ConnectionResult.Success)
{
Log.Info("MainActivity", "Google Play Services is installed on this device.");
return true;
}

if (GoogleApiAvailability.Instance.IsUserResolvableError(queryResult))
{
// Check if there is a way the user can resolve the issue
var errorString = GoogleApiAvailability.Instance.GetErrorString(queryResult);
Log.Error("MainActivity", "There is a problem with Google Play Services on this device: {0} - {1}",
queryResult, errorString);

// Alternately, display the error to the user.


}

return false;
}

FusedLocationProviderClient
Para interactuar con el proveedor de ubicaciones con fusibles, una aplicación de Xamarin. Android debe tener
FusedLocationProviderClient una instancia de. Esta clase expone los métodos necesarios para suscribirse a las
actualizaciones de ubicación y recuperar la última ubicación conocida del dispositivo.
El método de una actividad es un lugar adecuado para obtener una referencia
OnCreate
FusedLocationProviderClient a, tal y como se muestra en el siguiente fragmento de código:

public class MainActivity: AppCompatActivity


{
FusedLocationProviderClient fusedLocationProviderClient;

protected override void OnCreate(Bundle bundle)


{
fusedLocationProviderClient = LocationServices.GetFusedLocationProviderClient(this);
}
}

Obtener la última ubicación conocida


El FusedLocationProviderClient.GetLastLocationAsync() método proporciona una manera sencilla y sin bloqueo
para que una aplicación de Xamarin. Android obtenga rápidamente la última ubicación conocida del dispositivo
con una sobrecarga de codificación mínima.
Este fragmento de código muestra cómo usar GetLastLocationAsync el método para recuperar la ubicación del
dispositivo:
async Task GetLastLocationFromDevice()
{
// This method assumes that the necessary run-time permission checks have succeeded.
getLastLocationButton.SetText(Resource.String.getting_last_location);
Android.Locations.Location location = await fusedLocationProviderClient.GetLastLocationAsync();

if (location == null)
{
// Seldom happens, but should code that handles this scenario
}
else
{
// Do something with the location
Log.Debug("Sample", "The latitude is " + location.Latitude);
}
}

Suscripción a actualizaciones de ubicación


Una aplicación de Xamarin. Android también puede suscribirse a las actualizaciones de ubicación del proveedor de
FusedLocationProviderClient.RequestLocationUpdatesAsync ubicaciones fusionadas mediante el método, tal como se
muestra en este fragmento de código:

await fusedLocationProviderClient.RequestLocationUpdatesAsync(locationRequest, locationCallback);

Este método toma dos parámetros:


Android.Gms.Location.LocationRequest – Un LocationRequest objeto es la forma en que una aplicación de
Xamarin. Android pasa los parámetros en la forma en que el proveedor de la ubicación fusionada debe
funcionar. LocationRequest Contiene información como la frecuencia con que se deben realizar las
solicitudes o la importancia de una actualización de ubicación precisa. Por ejemplo, una solicitud de
ubicación importante hará que el dispositivo use el GPS y, por consiguiente, más potencia, al determinar la
ubicación. Este fragmento de código muestra cómo crear un LocationRequest para una ubicación con una
precisión alta, comprobando aproximadamente cada cinco minutos para una actualización de ubicación
(pero no antes de dos minutos entre solicitudes). El proveedor LocationRequest de ubicaciones con fusibles
usará como guía el proveedor de ubicación que se va a usar al intentar determinar la ubicación del
dispositivo:

LocationRequest locationRequest = new LocationRequest()


.SetPriority(LocationRequest.PriorityHighAccuracy)
.SetInterval(60 * 1000 * 5)
.SetFastestInterval(60 * 1000 * 2);

Android.Gms.Location.LocationCallback Para recibir actualizaciones de ubicación, una aplicación de Xamarin.


Android debe subclase de LocationProvider la clase abstracta. – Esta clase expone dos métodos que es
posible que el proveedor de ubicación con fusibles invoque para actualizar la aplicación con información de
ubicación. Esto se tratará con más detalle a continuación.
Para notificar a una aplicación de Xamarin. Android de una actualización de ubicación, el proveedor de
LocationCallBack.OnLocationResult(LocationResult result) ubicación con fusible invocará el. El
Android.Gms.Location.LocationResult parámetro contendrá la información de la ubicación de actualización.

Cuando el proveedor de ubicación con fusible detecta un cambio en la disponibilidad de los datos de ubicación,
llamará al LocationProvider.OnLocationAvailability(LocationAvailability locationAvailability) método. Si la
LocationAvailability.IsLocationAvailable propiedad devuelve true , se puede suponer que los resultados de
ubicación del dispositivo notificados por OnLocationResult son tan precisos y actualizados según sea necesario
LocationRequest . Si IsLocationAvailable es false, no se devolverá ningún resultado de OnLocationResult la
ubicación.
Este fragmento de código es una implementación de ejemplo LocationCallback del objeto:

public class FusedLocationProviderCallback : LocationCallback


{
readonly MainActivity activity;

public FusedLocationProviderCallback(MainActivity activity)


{
this.activity = activity;
}

public override void OnLocationAvailability(LocationAvailability locationAvailability)


{
Log.Debug("FusedLocationProviderSample", "IsLocationAvailable:
{0}",locationAvailability.IsLocationAvailable);
}

public override void OnLocationResult(LocationResult result)


{
if (result.Locations.Any())
{
var location = result.Locations.First();
Log.Debug("Sample", "The latitude is :" + location.Latitude);
}
else
{
// No locations to work with.
}
}
}

Uso de la API de servicio de ubicación de Android


El servicio de ubicación de Android es una API anterior para usar información de ubicación en Android. Los
sensores de hardware recopilan los datos de ubicación y los recopila un servicio de sistema, al que se tiene acceso
LocationManager en la aplicación ILocationListener con una clase y un.

El servicio de ubicación es más adecuado para las aplicaciones que se deben ejecutar en dispositivos que no tienen
Google Play Services instalado.
Location Service es un tipo especial de servicio administrado por el sistema. Un servicio del sistema interactúa con
el hardware del dispositivo y siempre se está ejecutando. Para aprovechar las actualizaciones de ubicación en
nuestra aplicación, suscribiremos a las actualizaciones de ubicación del servicio de ubicación del LocationManager
sistema mediante RequestLocationUpdates una llamada a y.
Para obtener la ubicación del usuario mediante el servicio de ubicación de Android, debe realizar varios pasos:
1. Obtiene una referencia al LocationManager servicio.
2. Implemente ILocationListener la interfaz y controle los eventos cuando cambie la ubicación.
3. LocationManager Utilice para solicitar actualizaciones de ubicación para un proveedor especificado. El
ILocationListener del paso anterior se utilizará para recibir devoluciones LocationManager de llamada de.
4. Detener las actualizaciones de ubicación cuando la aplicación ya no sea adecuada para recibir actualizaciones.
Administrador de ubicación
Se puede tener acceso al servicio de ubicación del sistema con una LocationManager instancia de la clase.
LocationManager es una clase especial que nos permite interactuar con el servicio de ubicación del sistema y llamar
a métodos en él. Una aplicación puede obtener una referencia a llamando LocationManager a GetSystemService y
pasando un tipo de servicio, como se muestra a continuación:

LocationManager locationManager = (LocationManager) GetSystemService(Context.LocationService);

OnCreate es un buen lugar para obtener una referencia a LocationManager . Se recomienda mantener
LocationManager como una variable de clase, de modo que podamos llamarlo en varios puntos del ciclo de vida de
la actividad.
Actualización de la ubicación de la solicitud desde LocationManager
Una vez que la aplicación tiene una referencia LocationManager a, debe indicar a qué LocationManager tipo de
información de ubicación se requiera y con qué frecuencia se actualizará la información. Para ello, llame
RequestLocationUpdates a en LocationManager el objeto y pase algunos criterios para las actualizaciones y una
devolución de llamada que recibirá las actualizaciones de la ubicación. Esta devolución de llamada es un tipo que
debe ILocationListener implementar la interfaz (se describe con más detalle más adelante en esta guía).
El RequestLocationUpdates método indica al servicio de ubicación del sistema que la aplicación desea empezar a
recibir actualizaciones de ubicación. Este método permite especificar el proveedor, así como los umbrales de
tiempo y distancia para controlar la frecuencia de actualización. Por ejemplo, el método siguiente solicita
actualizaciones de ubicación del proveedor de ubicación de GPS cada 2000 milisegundos y solo cuando la
ubicación cambia más de 1 metro:

// For this example, this method is part of a class that implements ILocationListener, described below
locationManager.RequestLocationUpdates(LocationManager.GpsProvider, 2000, 1, this);

Una aplicación debe solicitar actualizaciones de ubicación solo con la frecuencia necesaria para que la aplicación
funcione correctamente. Esto conserva la duración de la batería y crea una mejor experiencia para el usuario.
Responder a las actualizaciones de LocationManager
Una vez que una aplicación ha solicitado actualizaciones LocationManager desde el, puede recibir información del
servicio implementando la ILocationListener interfaz. Esta interfaz proporciona cuatro métodos para escuchar el
servicio de ubicación y el proveedor de ubicación OnLocationChanged ,. El sistema llamará OnLocationChanged
cuando la ubicación del usuario cambie lo suficiente como para calificarse como un cambio de ubicación según los
criterios establecidos al solicitar actualizaciones de ubicación.
En el código siguiente se muestran los métodos ILocationListener de la interfaz:
public class MainActivity : AppCompatActivity, ILocationListener
{
TextView latitude;
TextView longitude;

public void OnLocationChanged (Location location)


{
// called when the location has been updated.
}

public OnProviderDisabled(string locationProvider)


{
// called when the user disables the provider
}

public OnProviderEnabled(string locationProvider)


{
// called when the user enables the provider
}

public OnStatusChanged(string locationProvider, Availability status, Bundle extras)


{
// called when the status of the provider changes (there are a variety of reasons for this)
}
}

Cancelar la suscripción a las actualizaciones de LocationManager


Para conservar los recursos del sistema, una aplicación debe cancelar la suscripción a las actualizaciones de
ubicación lo antes posible. El RemoveUpdates método indica a LocationManager que detenga el envío de
actualizaciones a la aplicación. Por ejemplo, una actividad puede llamar a RemoveUpdates en el OnPause método
para que podamos ahorrar energía si una aplicación no necesita actualizaciones de ubicación mientras su actividad
no está en la pantalla:

protected override void OnPause ()


{
base.OnPause ();
locationManager.RemoveUpdates (this);
}

Si la aplicación necesita obtener actualizaciones de ubicación en segundo plano, querrá crear un servicio
personalizado que se suscriba al servicio de ubicación del sistema. Consulte la guía de procesamiento en segundo
plano con servicios Android para obtener más información.
Determinar el mejor proveedor de ubicación para el LocationManager
La aplicación anterior establece GPS como proveedor de ubicación. Sin embargo, es posible que GPS no esté
disponible en todos los casos, por ejemplo, si el dispositivo es interior o no tiene un receptor de GPS. Si es así, el
resultado es un null valor devuelto por el proveedor.
Para que la aplicación funcione cuando GPS no esté disponible, use el método para GetBestProvider solicitar el
mejor proveedor de ubicación disponible (compatible con el dispositivo y habilitado para el usuario) en el inicio de
la aplicación. En lugar de pasar un proveedor concreto, puede indicar GetBestProvider los requisitos del proveedor,
como la precisión y la potencia de un Criteria objeto. GetBestProvider Devuelve el mejor proveedor para los
criterios especificados.
En el código siguiente se muestra cómo obtener el mejor proveedor disponible y usarlo al solicitar actualizaciones
de Ubicación:
Criteria locationCriteria = new Criteria();
locationCriteria.Accuracy = Accuracy.Coarse;
locationCriteria.PowerRequirement = Power.Medium;

locationProvider = locationManager.GetBestProvider(locationCriteria, true);

if(locationProvider != null)
{
locationManager.RequestLocationUpdates (locationProvider, 2000, 1, this);
}
else
{
Log.Info(tag, "No location providers available");
}

NOTE
Si el usuario ha deshabilitado todos los GetBestProvider proveedores de null ubicación, devolverá. Para ver cómo
funciona este código en un dispositivo real, asegúrese de habilitar las redes GPS, Wi-Fi y telefonía móvil en configuración de
Google > el modo de ubicación > como se muestra en esta captura de pantalla:

En la captura de pantalla siguiente se muestra la GetBestProvider aplicación de ubicación que se ejecuta mediante:
Tenga en cuenta que GetBestProvider no cambia el proveedor dinámicamente. En su lugar, determina el mejor
proveedor disponible una vez durante el ciclo de vida de la actividad. Si el estado del proveedor cambia después de
que se haya establecido, la aplicación requerirá código adicional ILocationListener en – los OnProviderDisabled
métodos OnProviderEnabled , OnStatusChanged y – para controlar todas las posibilidades relacionadas con el
modificador de proveedor.

Resumen
En esta guía se ha tratado la obtención de la ubicación del usuario mediante el servicio de ubicación de Android y
el proveedor de ubicación con fusible de Google Location Services API.

Vínculos relacionados
Ubicación (ejemplo)
FusedLocationProvider (ejemplo)
Google Play Services
Clase de criterios
Clase LocationManager
Clase LocationListener
API de LocationClient
API de LocationListener
API de LocationRequest
Cómo usar las asignaciones y la ubicación de Google
con Xamarin. Android
16/08/2019 • 2 minutes to read • Edit Online

En este artículo se describe cómo usar las asignaciones y la ubicación con Xamarin. Android. Abarca todo, desde el
aprovechamiento de la aplicación de mapas integrada hasta el uso de Google Maps Android API V2
directamente.

Información general de Maps


Las tecnologías de asignación son un complemento omnipresente para dispositivos móviles. Los equipos de
escritorio y portátiles no tienden a tener un conocimiento de la ubicación integrado. Por otro lado, los dispositivos
móviles usan estas aplicaciones para localizar dispositivos y Mostrar información de ubicación cambiante. Android
tiene tecnología integrada y eficaz que muestra los datos de ubicación en mapas mediante hardware de ubicación
que puede estar disponible en el dispositivo. En este artículo se describe un espectro de lo que las aplicaciones de
Maps en Xamarin. Android deben ofrecer, incluido:
Usar la aplicación de mapas integrada para agregar rápidamente funcionalidad de asignación.
Trabajar con la API de Maps para controlar la presentación de un mapa.
Usar diversas técnicas para agregar superposiciones gráficas.
Los temas de esta sección cubren una amplia gama de características de asignación. En primer lugar, se explica
cómo aprovechar la aplicación de mapas integrada de Android y cómo mostrar una vista panorámica de una
ubicación. A continuación, se explica cómo usar la API de Maps para incorporar características de asignación
directamente dentro de una aplicación, que abarcan cómo controlar la posición y la presentación de un mapa,
además de cómo agregar superposiciones gráficas.

Vínculos relacionados
MapsAndLocationDemo_v3 (ejemplo)
Ciclo de vida de la actividad
Obtención de una clave de la API de Google Maps
Lista de intentos: Invocar aplicaciones de Google en dispositivos Android
Ubicación y asignaciones
Inicio de la aplicación Maps
16/08/2019 • 5 minutes to read • Edit Online

La manera más sencilla de trabajar con mapas en Xamarin. Android es aprovechar la aplicación de mapas
integrada que se muestra a continuación:
Cuando se usa la aplicación Maps, la asignación no formará parte de la aplicación. En su lugar, la aplicación iniciará
la aplicación Maps y cargará el mapa externamente. En la siguiente sección se examina cómo usar Xamarin.
Android para iniciar mapas como el anterior.

Crear el intento
Trabajar con la aplicación Maps es tan sencillo como crear una intención con un URI adecuado, establecer la acción
en ActionView y llamar al método StartActivity. Por ejemplo, el código siguiente inicia la aplicación Maps centrada
en una latitud y longitud determinada:

var geoUri = Android.Net.Uri.Parse ("geo:42.374260,-71.120824");


var mapIntent = new Intent (Intent.ActionView, geoUri);
StartActivity (mapIntent);

Este código es todo lo que se necesita para iniciar el mapa que se muestra en la captura de pantalla anterior.
Además de especificar la latitud y la longitud, el esquema de URI para Maps admite otras opciones.

Esquema de URI geo


El código anterior usaba el esquema geográfico para crear un URI. Este esquema de URI admite varios formatos,
como se muestra a continuación:
geo:latitude,longitude – Abre la aplicación Maps centrada en lat/lon.
geo:latitude,longitude?z=zoom – Abre la aplicación de mapas centrada en una lat/lon y se amplía al nivel
especificado. El nivel de zoom puede oscilar entre 1 y 23: 1 muestra toda la tierra y 23 es el nivel de zoom
más cercano.
geo:0,0?q=my+street+address – Abre la aplicación Maps en la ubicación de una dirección postal.
geo:0,0?q=business+near+city – Abre la aplicación Maps y muestra los resultados de la búsqueda anotados.

Las versiones del URI que toman una consulta (es decir, la dirección postal o los términos de búsqueda) usan el
servicio de webencoder de Google para recuperar la ubicación que se muestra en el mapa. Por ejemplo, el URI
geo:0,0?q=coop+Cambridge da como resultado el mapa que se muestra a continuación:
Para obtener más información sobre los esquemas de URI geográfico, consulte Mostrar una ubicación en un mapa.
Vista de calle
Además del esquema geográfico, Android también admite la carga de vistas de calles desde un intento. A
continuación se muestra un ejemplo de la aplicación calle View iniciada desde Xamarin. Android:
Para iniciar una vista de calle, simplemente use google.streetview el esquema de URI, como se muestra en el
código siguiente:

var streetViewUri = Android.Net.Uri.Parse (


"google.streetview:cbll=42.374260,-71.120824&cbp=1,90,,0,1.0&mz=20");
var streetViewIntent = new Intent (Intent.ActionView, streetViewUri);
StartActivity (streetViewIntent);

El esquema de URI de Google. streetview usado anteriormente tiene el formato siguiente:

google.streetview:cbll=lat,lng&cbp=1,yaw,,pitch,zoom&mz=mapZoom

Como puede ver, se admiten varios parámetros, como se muestra a continuación:


lat – La latitud de la ubicación que se va a mostrar en la vista de la calle.
lng – Longitud de la ubicación que se va a mostrar en la vista de la calle.
pitch – Ángulo de la panorámica de la vista de calle, medido desde el centro en grados, donde 90 grados es
recto y-90 grados es recto.
yaw– Centro de vista de la panorámica de la vista de la calle, medido en el sentido de las agujas del reloj en
grados desde el norte.
– Multiplicador del zoom para la panorámica de la vista de calle, donde 1,0 = zoom normal, 2,0 =
zoom
zoom 2x, 3,0 = zoom 4x, etc.
mz – El nivel de zoom del mapa que se usará cuando vaya a la aplicación Maps desde la vista calle.

Trabajar con la aplicación de mapas integrada o la vista de calle es una manera fácil de agregar rápidamente
compatibilidad con las asignaciones. Sin embargo, la API de Maps de Android ofrece un mayor control sobre la
experiencia de asignación.
Uso de la API de Google Maps en su aplicación
11/07/2019 • 36 minutes to read • Edit Online

El uso de la aplicación mapas es excelente, pero a veces van a incluir asignaciones directamente en la aplicación.
Además de los integrados se asigna la aplicación, Google también ofrece un API nativas de asignación para
Android. La API de mapas es adecuada para los casos donde desee mantienen más control sobre la experiencia de
asignación. Cosas que son posibles con la API de Maps incluyen:
Cambiar mediante programación el punto de vista del mapa.
Cómo agregar y personalizar los marcadores.
Anotar un mapa con superposiciones.
A diferencia de la versión 1 ahora está en desuso API de Android de Google Maps, API de Android de Google
Maps v2 es parte de Google Play Services. Una aplicación de Xamarin.Android debe cumplir algunos requisitos
previos obligatorios antes de que se puede usar la API de Android de Google Maps.

Requisitos previos de la API de Google Maps


Varios pasos deben realizarse antes de poder usar la API de Maps, incluidos:
Obtener una clave de API de mapas
Instale el SDK de Google Play Services
Instale el paquete de Xamarin.GooglePlayServices.Maps de NuGet
Especifique los permisos necesarios
Opcionalmente, puede crear un emulador con las APIs de Google
Obtener una clave de API de Google Maps
El primer paso es obtener una clave de API de Google Maps (tenga en cuenta que no se puede reutilizar una clave
de API de la API heredada de v1 de Google Maps). Para obtener información acerca de cómo obtener y usar la
clave de API con Xamarin.Android, consulte clave de API de obtención A Google Maps.
Instale el SDK de Google Play Services
Google Play Services es una tecnología de Google que permite a las aplicaciones Android aprovechar las ventajas
de las distintas características de Google como Google +, de facturación en la aplicación y asignaciones. Estas
características son accesibles en dispositivos Android como servicios en segundo plano, que se encuentran en el
APK de Google Play Services.
Las aplicaciones de Android interactúan con Google Play Services a través de la biblioteca de cliente de Google
Play Services. Esta biblioteca contiene las interfaces y clases de los servicios individuales, como los mapas. El
diagrama siguiente muestra la relación entre una aplicación de Android y Google Play Services:
La API de mapas de Android se proporciona como parte de Google Play Services. Antes de que una aplicación de
Xamarin.Android puede usar la API de mapas, el SDK de Google Play Services debe instalarse con la Android SDK
Manager. Captura de pantalla siguiente muestra dónde en el cliente de servicios de Google Play se puede
encontrar Android SDK Manager:

NOTE
Los servicios de Google Play APK es un producto con licencia que no puede estar presente en todos los dispositivos. Si no
está instalado, Google Maps no funcionará en el dispositivo.

Instale el paquete de Xamarin.GooglePlayServices.Maps de NuGet


El Xamarin.GooglePlayServices.Maps paquete contiene los enlaces de Xamarin.Android para la API de mapas de
Google Play Services. Para agregar el paquete de mapa de Google Play Services, haga clic en el referencias
carpeta del proyecto en el Explorador de soluciones y haga clic en administrar paquetes NuGet... :
Se abrirá el Administrador de paquetes de NuGet. Haga clic en examinar y escriba Xamarin Google Play
Services Maps en el campo de búsqueda. Seleccione Xamarin.GooglePlayServices.Maps y haga clic en
instalar. (Si hubiera instalado previamente este paquete, haga clic en Update.):

Tenga en cuenta que también están instalados los siguientes paquetes de dependencia:
Xamarin.GooglePlayServices.Base
Xamarin.GooglePlayServices.Basement
Xamarin.GooglePlayServices.Tasks
Especifique los permisos necesarios
Las aplicaciones deben identificar los requisitos de hardware y el permiso para usar la API de Google Maps.
Algunos permisos se conceden automáticamente mediante el SDK de Google Play Services, y no es necesario
agregarlos de forma explícita a un desarrollador AndroidManfest.XML:
Acceso al estado de la red – la API de mapas debe ser capaz de comprobar si pueden descargar los
mosaicos de mapa.
Acceso a Internet – acceso a Internet es necesario descargar los mosaicos de mapa y comunicarse con los
servidores de Google Play para el acceso de API.
Se deben especificar los siguientes permisos y las características en el AndroidManifest.XML para la API de
Android de Google Maps:
OpenGL ES v2 – la aplicación debe declarar el requisito para la versión de OpenGL ES 2.
Clave de API de Google Maps – la clave de API se usa para confirmar que la aplicación se registra y
autorización para usar Google Play Services. Consulte obtener una clave de API de Google Maps para
obtener más información acerca de esta clave.
El cliente heredado de Apache HTTP de solicitud – las aplicaciones destinadas a Android 9.0 (API nivel
28) o posterior debe especificar que el cliente heredado de Apache HTTP es una biblioteca opcional que se
usará.
Acceso a los servicios basados en Web de Google – la aplicación necesita permisos para tener acceso a
los servicios web de Google que realizar una copia de la API de mapas de Android.
Permisos para las notificaciones de Google Play Services – la aplicación debe tener permiso para
recibir notificaciones remotas de Google Play Services.
Acceso a los proveedores de ubicación – son permisos opcionales. Permitirá la GoogleMap clase para
mostrar la ubicación del dispositivo en el mapa.
Además, 9 Android quitó la biblioteca de cliente Apache HTTP desde el bootclasspath, y por lo que no está
disponible para las aplicaciones destinadas a API 28 o superior. Se debe agregar la siguiente línea a la application
nodo de su AndroidManifest.xml archivo seguir usando el cliente HTTP de Apache en las aplicaciones
destinadas a API 28 o superior:

<application ...>
...
<uses-library android:name="org.apache.http.legacy" android:required="false" />
</application>

NOTE
Las versiones muy anteriores de SDK de Google Play requieren una aplicación para solicitar el WRITE_EXTERNAL_STORAGE
permiso. Este requisito ya no es necesario con los enlaces de Xamarin recientes de Google Play Services.

El fragmento de código siguiente es un ejemplo de la configuración que debe agregarse a AndroidManifest.XML:


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="4.5"
package="com.xamarin.docs.android.mapsandlocationdemo2" android:versionCode="6">
<uses-sdk android:minSdkVersion="23" android:targetSdkVersion="28" />

<!-- Google Maps for Android v2 requires OpenGL ES v2 -->


<uses-feature android:glEsVersion="0x00020000" android:required="true" />

<!-- Necessary for apps that target Android 9.0 or higher -->
<uses-library android:name="org.apache.http.legacy" android:required="false" />

<!-- Permission to receive remote notifications from Google Play Services -->
<!-- Notice here that we have the package name of our application as a prefix on the permissions. -->
<uses-permission android:name="<PACKAGE NAME>.permission.MAPS_RECEIVE" />
<permission android:name="<PACKAGE NAME>.permission.MAPS_RECEIVE" android:protectionLevel="signature" />

<!-- These are optional, but recommended. They will allow Maps to use the My Location provider. -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

<application android:label="@string/app_name">
<!-- Put your Google Maps V2 API Key here. -->
<meta-data android:name="com.google.android.maps.v2.API_KEY" android:value="YOUR_API_KEY" />
<meta-data android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<!-- Necessary for apps that target Android 9.0 or higher -->
<uses-library android:name="org.apache.http.legacy" android:required="false" />
</application>
</manifest>

Además de solicitar los permisos AndroidManifest.XML, una aplicación también debe realizar comprobaciones
de permisos en tiempo de ejecución para el ACCESS_COARSE_LOCATION y ACCESS_FINE_LOCATION permisos. Consulte la
Xamarin.Android permisos guía para obtener más información sobre la realización de comprobaciones de permiso
de tiempo de ejecución.
Creación de un emulador con API de Google
En caso de que un dispositivo Android físico con Google Play services no está instalado, es posible crear una
imagen del emulador para el desarrollo. Para obtener más información, consulte el Device Manager.

La clase GoogleMap
Una vez que se cumplen los requisitos previos, es el momento de empezar a desarrollar la aplicación y usar la API
de mapas de Android. El GoogleMap clase es la API principal que usará una aplicación de Xamarin.Android para
mostrar e interactuar con un Google Maps para Android. Esta clase tiene las siguientes responsabilidades:
Interactuar con los servicios de Google Play y autorizar la aplicación con el servicio web de Google.
Descargar, almacenamiento en caché y mostrar los iconos de mapa.
Mostrar controles de interfaz de usuario, como realizar una panorámica y zoom para el usuario.
Marcadores de dibujo y formas geométricas en mapas.
El GoogleMap se agrega a una actividad en uno de dos maneras:
MapFragment : la MapFragment es un fragmento especializado que actúa como host para el GoogleMap
objeto. El MapFragment requiere el nivel de API de Android 12 o superior. Pueden usar las versiones
anteriores de Android el SupportMapFragment. Esta guía se centra en usar la MapFragment clase.
MapView : la MapView es una subclase especializada de la vista, que puede actuar como un host para un
GoogleMap objeto. Los usuarios de esta clase deben reenviar todos los métodos de ciclo de vida de actividad
a la MapView clase.
Cada uno de estos contenedores expone un Map propiedad que devuelve una instancia de GoogleMap . Preferencia
debería proporcionarse a los MapFragment clase ya que es una API más sencilla que reduce el código reutilizable
de cantidad que un desarrollador deberá implementar manualmente.
Agregar un MapFragment a una actividad
Captura de pantalla siguiente es un ejemplo de una sencilla MapFragment :
Al igual que otras clases de fragmentos, hay dos maneras de agregar un MapFragment a una actividad:
Mediante declaración : la MapFragment se pueden agregar mediante el archivo de diseño XML para la
actividad. El fragmento XML siguiente muestra un ejemplo de cómo usar el fragment elemento:

<?xml version="1.0" encoding="utf-8"?>


<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="com.google.android.gms.maps.MapFragment" />

Mediante programación : la MapFragment puede crearse mediante programación utilizando la


MapFragment.NewInstance método y, a continuación, se agrega a una actividad. Este fragmento de código
muestra la manera más sencilla de crear una instancia de un MapFragment de objeto y agregar a una
actividad:

var mapFrag = MapFragment.NewInstance();


activity.FragmentManager.BeginTransaction()
.Add(Resource.Id.map_container, mapFrag, "map_fragment")
.Commit();

Es posible configurar el MapFragment pasando un GoogleMapOptions objeto NewInstance . Esto se explica en


la sección GoogleMap propiedades que aparece más adelante en esta guía.
El MapFragment.GetMapAsync método se usa para inicializar el GoogleMap que está hospedado en el fragmento y
obtener una referencia al objeto de mapa que está hospedado por el MapFragment . Este método toma un objeto
que implementa el IOnMapReadyCallback interfaz.
Esta interfaz tiene un único método, IMapReadyCallback.OnMapReady(MapFragment map) que se invocará cuando es
posible que la aplicación interactuar con el GoogleMap objeto. El siguiente fragmento de código muestra cómo se
puede inicializar una actividad de Android un MapFragment e implemente el IOnMapReadyCallback interfaz:
public class MapWithMarkersActivity : AppCompatActivity, IOnMapReadyCallback
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.MapLayout);

var mapFragment = (MapFragment) FragmentManager.FindFragmentById(Resource.Id.map);


mapFragment.GetMapAsync(this);

// remainder of code omitted


}

public void OnMapReady(GoogleMap map)


{
// Do something with the map, i.e. add markers, move to a specific location, etc.
}
}

Tipos de mapa
Hay cinco tipos diferentes de asignaciones de la API de mapas de Google:
Normal -éste es el tipo de asignación predeterminado. Muestra las carreteras y características naturales
importante junto con algunos puntos artificiales de interés (por ejemplo, edificios y puentes).
Satélite -esta asignación muestra la fotografía de satélite.
Híbrido : esta asignación muestra la fotografía satélite y mapas de carreteras.
Terreno -principalmente muestra características topográficas con algunas carreteras.
Ninguno -esta asignación no carga ningún mosaico, se representa como una cuadrícula vacía.
La siguiente imagen muestra tres de los diferentes tipos de mapas, de izquierda a derecha (normal, híbrido,
terreno):

El GoogleMap.MapType propiedad se utiliza para establecer o cambiar el tipo de asignación se muestra. El fragmento
de código siguiente muestra cómo mostrar un mapa de satélite.
public void OnMapReady(GoogleMap map)
{
map.MapType = GoogleMap.MapTypeHybrid;
}

Propiedades de GoogleMap
GoogleMap define varias propiedades que pueden controlar la funcionalidad y la apariencia del mapa. Una manera
de configurar el estado inicial de un GoogleMap consiste en pasar un GoogleMapOptions objeto cuando se crea un
MapFragment . El fragmento de código siguiente es un ejemplo del uso de un GoogleMapOptions objeto cuando se
crea un MapFragment :

GoogleMapOptions mapOptions = new GoogleMapOptions()


.InvokeMapType(GoogleMap.MapTypeSatellite)
.InvokeZoomControlsEnabled(false)
.InvokeCompassEnabled(true);

FragmentTransaction fragTx = FragmentManager.BeginTransaction();


mapFragment = MapFragment.NewInstance(mapOptions);
fragTx.Add(Resource.Id.map, mapFragment, "map");
fragTx.Commit();

La otra forma de configurar un GoogleMap está manipulando las propiedades en el UiSettings del objeto map. El
ejemplo de código siguiente muestra cómo configurar un GoogleMap para mostrar los controles de zoom y una
brújula:

public void OnMapReady(GoogleMap map)


{
map.UiSettings.ZoomControlsEnabled = true;
map.UiSettings.CompassEnabled = true;
}

Interactuar con el GoogleMap


La API de mapas de Android proporciona API que permiten que una actividad para cambiar el punto de vista,
agregar marcadores, coloque las superposiciones personalizadas o dibujar formas geométricas. En esta sección se
describe cómo realizar algunas de estas tareas en Xamarin.Android.
Cambiar el punto de vista
Mapas se modelan como un plano sin formato en la pantalla, en función de la proyección Mercator. La vista del
mapa es el de un cámara atractivo hacia abajo en este plano. La posición de la cámara puede controlarse mediante
la modificación de la ubicación, zoom, inclinación y afecta. El CameraUpdate clase se utiliza para mover la
ubicación de la cámara. CameraUpdate no son instancias de los objetos directamente, en su lugar, proporciona la
API de Maps la CameraUpdateFactory clase.
Una vez un CameraUpdate se ha creado el objeto, se pasa como parámetro a cualquiera la
GoogleMap.MoveCamera o GoogleMap.AnimateCamera métodos. El MoveCamera método actualiza el mapa al
instante durante la AnimateCamera método proporciona una transición suave y animada.
Este fragmento de código es un ejemplo sencillo de cómo usar el CameraUpdateFactory para crear un CameraUpdate
que aumentará el nivel de zoom del mapa por nivel de uno zoom:
MapFragment mapFrag = (MapFragment) FragmentManager.FindFragmentById(Resource.Id.my_mapfragment_container);
mapFrag.GetMapAsync(this);
...

public void OnMapReady(GoogleMap map)


{
map.MoveCamera(CameraUpdateFactory.ZoomIn());
}

La API de Maps proporciona un CameraPosition que realizará la agregación de todos los valores posibles para la
posición de la cámara. Una instancia de esta clase se puede proporcionar a los
CameraUpdateFactory.NewCameraPosition método que devolverá un CameraUpdate objeto. La API de Maps
incluye también la CameraPosition.Builder clase que proporciona una API fluida para crear CameraPosition
objetos. El fragmento de código siguiente muestra un ejemplo de creación de un CameraUpdate desde un
CameraPosition y usarlo para cambiar la posición de la cámara en una GoogleMap :

public void OnMapReady(GoogleMap map)


{
LatLng location = new LatLng(50.897778, 3.013333);

CameraPosition.Builder builder = CameraPosition.InvokeBuilder();


builder.Target(location);
builder.Zoom(18);
builder.Bearing(155);
builder.Tilt(65);

CameraPosition cameraPosition = builder.Build();

CameraUpdate cameraUpdate = CameraUpdateFactory.NewCameraPosition(cameraPosition);

map.MoveCamera(cameraUpdate);
}

En el fragmento de código anterior, una ubicación específica en el mapa se representa mediante el LatLng clase. El
nivel de zoom se establece a 18, que es una medida arbitraria de zoom utilizado por Google Maps. La relación es la
medida brújula las agujas del reloj desde el norte. La propiedad inclinación controla el ángulo de visión y especifica
un ángulo de 25 grados desde la vertical. La siguiente captura de pantalla muestra la GoogleMap después de
ejecutar el código anterior:
Dibujo del mapa
La API de mapas de Android proporciona la API para dibujar los siguientes elementos en un mapa:
Marcadores : estos son los iconos especiales que se usan para identificar una sola ubicación en un mapa.
Las superposiciones -se trata de una imagen que puede usarse para identificar una colección de
ubicaciones o área en el mapa.
Líneas, polígonos y círculos -se trata de API que permiten a las actividades agregar formas a un mapa.
Markers
La API de Maps proporciona un marcador clase que encapsula todos los datos sobre una sola ubicación en un
mapa. De forma predeterminada, el marcador de clase utiliza un icono estándar proporcionado por Google Maps.
Es posible personalizar la apariencia de un marcador y responder a clics de usuario.
A gr egar u n m ar c ado r
Para agregar un marcador a un mapa, es necesario crear un nuevo MarkerOptions objeto y, a continuación, llame a
la AddMarker método en un GoogleMap instancia. Este método devolverá un marcador objeto.

public void OnMapReady(GoogleMap map)


{
MarkerOptions markerOpt1 = new MarkerOptions();
markerOpt1.SetPosition(new LatLng(50.379444, 2.773611));
markerOpt1.SetTitle("Vimy Ridge");

map.AddMarker(markerOpt1);
}

Se mostrará el título del marcador en un ventana información cuando el usuario puntea en el marcador. Captura
de pantalla siguiente muestra el aspecto de este marcador:
P e r so n a l i z a c i ó n d e u n m a r c a d o r

Es posible personalizar el icono utilizado por el marcador mediante una llamada a la MarkerOptions.InvokeIcon
método al agregar el marcador al mapa. Este método toma un BitmapDescriptor objeto que contiene los datos
necesarios para representar el icono. El BitmapDescriptorFactory clase proporciona algunos métodos auxiliares
para simplificar la creación de un BitmapDescriptor . En la lista siguiente presenta algunos de estos métodos:
DefaultMarker(float colour) – Utilice el marcador de Google Maps predeterminado, pero cambie el color.
FromAsset(string assetName) – Usar un icono personalizado desde el archivo especificado en la carpeta de
recursos.
FromBitmap(Bitmap image) – Use el mapa de bits especificado como el icono.
FromFile(string fileName) – Crear el icono personalizado desde el archivo en la ruta de acceso especificada.
FromResource(int resourceId) – Crear un icono personalizado desde el recurso especificado.

El fragmento de código siguiente muestra un ejemplo de cómo crear un marcador predeterminado de color
aguamarina:

public void OnMapReady(GoogleMap map)


{
MarkerOptions markerOpt1 = new MarkerOptions();
markerOpt1.SetPosition(new LatLng(50.379444, 2.773611));
markerOpt1.SetTitle("Vimy Ridge");

var bmDescriptor = BitmapDescriptorFactory.DefaultMarker (BitmapDescriptorFactory.HueCyan);


markerOpt1.InvokeIcon(bmDescriptor);

map.AddMarker(markerOpt1);
}

Ventanas de información
Windows info son ventanas especiales ese cuadro emergente para mostrar información al usuario cuando pulse un
marcador concreto. De forma predeterminada, la ventana de información mostrará el contenido del título del
marcador. Si no se ha asignado el título, no aparecerá ninguna ventana de información. Sólo una ventana de
información puede mostrarse a la vez.
Es posible personalizar la ventana de información mediante la implementación de la
GoogleMap.IInfoWindowAdapter interfaz. Hay dos métodos importantes de esta interfaz:
public View GetInfoWindow(Marker marker) – Este método se llama para obtener una ventana de información
personalizada para un marcador. Si devuelve null , entonces se usará la representación predeterminada de
la ventana. Si este método devuelve una vista, esa vista se colocarán dentro del marco de ventana de
información.
public View GetInfoContents(Marker marker) – Este método solo se llamará si GetInfoWindow devuelve
null . Este método puede devolver un null valor si es la representación predeterminada, el contenido de
la ventana de información que se usará. En caso contrario, este método debe devolver una vista con el
contenido de la ventana de información.
Una ventana de información no es una vista dinámica: en su lugar Android convertirá la vista de un mapa de bits
estático y mostrar en la imagen. Esto significa que una ventana de información no puede responder a los eventos
de toque o gestos, ni actualizará automáticamente propio. Para actualizar una ventana de información, es necesario
llamar a la GoogleMap.ShowInfoWindow método.
La siguiente imagen muestra algunos ejemplos de algunas ventanas de información personalizada. La imagen de
la izquierda tiene su contenido personalizado, mientras que la imagen de la derecha tiene su ventana y el contenido
personalizado con esquinas redondeadas:

GroundOverlays
A diferencia de los marcadores, que identifican una ubicación específica en un mapa, una GroundOverlay es una
imagen que se usa para identificar una colección de ubicaciones o a un área en el mapa.
A gr egar u n Gr o u n d O ver l ay

Agregar una superposición de cero a una asignación es similar a agregar un marcador a un mapa. En primer lugar,
un GroundOverlayOptions se crea el objeto. Este objeto, a continuación, se pasa como parámetro a la
GoogleMap.AddGroundOverlay método, que devolverá un GroundOverlay objeto. Este fragmento de código es un
ejemplo de cómo agregar una superposición de cero a un mapa:
BitmapDescriptor image = BitmapDescriptorFactory.FromResource(Resource.Drawable.polarbear);
GroundOverlayOptions groundOverlayOptions = new GroundOverlayOptions()
.Position(position, 150, 200)
.InvokeImage(image);
GroundOverlay myOverlay = googleMap.AddGroundOverlay(groundOverlayOptions);

Captura de pantalla siguiente muestra esta superposición en un mapa:


Líneas, círculos y polígonos
Hay tres tipos simples de figuras geométricas que pueden agregarse a un mapa:
Polyline -se trata de una serie de segmentos de línea conectados. Puede marcar una ruta de acceso en un
mapa o crear una forma geométrica.
Círculo -dibujará un círculo en el mapa.
Polígono -se trata de una forma cerrada para marcar las áreas en un mapa.
Po l i l í n eas

Un Polyline es una lista de consecutivos LatLng objetos que especifican los vértices de cada segmento de línea. Se
crea una polilínea creando primero un PolylineOptions objeto y agregarle los puntos. El PolylineOption objeto, a
continuación, se pasa a un GoogleMap objeto mediante una llamada a la AddPolyline método.

PolylineOption rectOptions = new PolylineOption();


rectOptions.Add(new LatLng(37.35, -122.0));
rectOptions.Add(new LatLng(37.45, -122.0));
rectOptions.Add(new LatLng(37.45, -122.2));
rectOptions.Add(new LatLng(37.35, -122.2));
rectOptions.Add(new LatLng(37.35, -122.0)); // close the polyline - this makes a rectangle.

googleMap.AddPolyline(rectOptions);

Cí r c u l os

Se crean los círculos creando primero un CircleOption objeto que se especificará el centro y el radio del círculo en
metros. El círculo se dibuja en el mapa mediante una llamada a GoogleMap.AddCircle. El fragmento de código
siguiente muestra cómo dibujar un círculo:

CircleOptions circleOptions = new CircleOptions ();


circleOptions.InvokeCenter (new LatLng(37.4, -122.1));
circleOptions.InvokeRadius (1000);

googleMap.AddCircle (circleOptions);

Polígonos

Polygon son similares a Polyline s, sin embargo, no estén abiertos finalizó. Polygon s son un bucle cerrado y su
interior rellena. Polygon se crean en la misma manera como un Polyline , excepto el GoogleMap.AddPolygon
método invocado.
A diferencia de un Polyline , un Polygon es de autocierre. El polígono se cerrarán desactivada por el AddPolygon
método al dibujar una línea que conecta los puntos primeros y últimos. El siguiente fragmento de código creará un
rectángulo sólido a través de la misma área que el fragmento de código anterior en el Polyline ejemplo.
PolygonOptions rectOptions = new PolygonOptions();
rectOptions.Add(new LatLng(37.35, -122.0));
rectOptions.Add(new LatLng(37.45, -122.0));
rectOptions.Add(new LatLng(37.45, -122.2));
rectOptions.Add(new LatLng(37.35, -122.2));
// notice we don't need to close off the polygon

googleMap.AddPolygon(rectOptions);

Responder a eventos de usuario


Hay tres tipos de interacciones que un usuario pudiera haber suscrito con un mapa:
Haga clic en de marcador -el usuario hace clic en un marcador.
Arrastre marcador -hizo clic el usuario long-en una mparger
Ventana de información haga clic en -el usuario hace clic en una ventana de información.
Cada uno de estos eventos se explicará más detalladamente a continuación.
Marcador de eventos de clic
El MarkerClicked evento se desencadena cuando el usuario puntea en un marcador. Este evento acepta un
GoogleMap.MarkerClickEventArgs objeto como parámetro. Esta clase contiene dos propiedades:

GoogleMap.MarkerClickEventArgs.Handled – Esta propiedad debe establecerse en true para indicar que el


controlador de eventos ha consumido el evento. Si se establece en false , a continuación, se producirá el
comportamiento predeterminado además el comportamiento del controlador de eventos personalizado.
Marker – Esta propiedad es una referencia al marcador de que ha provocado la MarkerClick eventos.

Este fragmento de código muestra un ejemplo de un MarkerClick que cambiará la posición de la cámara a una
nueva ubicación en el mapa:

void MapOnMarkerClick(object sender, GoogleMap.MarkerClickEventArgs markerClickEventArgs)


{
markerClickEventArgs.Handled = true;

var marker = markerClickEventArgs.Marker;


if (marker.Id.Equals(gotMauiMarkerId))
{
LatLng InMaui = new LatLng(20.72110, -156.44776);

// Move the camera to look at Maui.


PositionPolarBearGroundOverlay(InMaui);
googleMap.AnimateCamera(CameraUpdateFactory.NewLatLngZoom(InMaui, 13));
gotMauiMarkerId = null;
polarBearMarker.Remove();
polarBearMarker = null;
}
else
{
Toast.MakeText(this, $"You clicked on Marker ID {marker.Id}", ToastLength.Short).Show();
}
}

Eventos de arrastre de marcador


Este evento se desencadena cuando el usuario desea arrastrar el marcador. De forma predeterminada, los
marcadores no son arrastrables. Un marcador se puede establecer como arrastrable estableciendo el
Marker.Draggable propiedad true o invocando la MarkerOptions.Draggable método con true como un
parámetro.
Para arrastrar el marcador, el usuario debe primero larga, haga clic en el marcador y, a continuación, su dedo debe
permanecer en el mapa. Cuando los dedos del usuario se arrastran alrededor de la pantalla, se moverá el marcador.
Cuando se levanta el dedo del usuario fuera de la pantalla, el marcador permanecerá en su lugar.
En la lista siguiente se describe los distintos eventos que se generan para un marcador arrastrable:
GoogleMap.MarkerDragStart(object sender, GoogleMap.MarkerDragStartEventArgs e) – Este evento se
desencadena cuando el usuario arrastra primero el marcador.
GoogleMap.MarkerDrag(object sender, GoogleMap.MarkerDragEventArgs e) – Este evento se desencadena como
el marcador se está arrastrando.
GoogleMap.MarkerDragEnd(object sender, GoogleMap.MarkerDragEndEventArgs e) – Este evento se desencadena
cuando finaliza el usuario arrastra el marcador.
Cada uno de los EventArgs contiene una propiedad única denominada P0 que es una referencia a la Marker de
objeto que se está arrastrando.
Eventos de ventana, haga clic en información
Sólo una ventana de información se puede mostrar a la vez. Cuando el usuario hace clic en una ventana de
información en un mapa, el objeto de mapa, se producirá un InfoWindowClick eventos. El fragmento de código
siguiente muestra cómo enlazar un controlador al evento:

public void OnMapReady(GoogleMap map)


{
map.InfoWindowClick += MapOnInfoWindowClick;
}

private void MapOnInfoWindowClick (object sender, GoogleMap.InfoWindowClickEventArgs e)


{
Marker myMarker = e.Marker;
// Do something with marker.
}

Recuerde que una ventana de información es estático View que se representa como una imagen en el mapa. Los
widgets, como botones, casillas de verificación o las vistas de texto que se colocan dentro de la ventana de
información serán inertes y no pueden responder a cualquiera de sus eventos de usuario integral.

Vínculos relacionados
SimpleMapDemo
Google Play Services
Mapas de Google Android API v2
Google Play Services APK
Obtención de una clave de API de Google Maps
uses-library
uses-feature
Obtención de una clave de la API de Google Maps
16/08/2019 • 12 minutes to read • Edit Online

Para usar la funcionalidad de Google Maps en Android, debe registrarse para obtener una clave de API de Maps
con Google. Hasta que lo haga, solo verá una cuadrícula en blanco en lugar de una asignación en sus
aplicaciones. Debe obtener una clave de las claves de Android API V2 de Google Maps de la antigua clave de API
de Android de Google Maps no funcionará.
La obtención de una clave de Maps API V2 implica los siguientes pasos:
1. Recupere la huella digital SHA-1 del almacén de claves que se usa para firmar la aplicación.
2. Cree un proyecto en la consola de API de Google.
3. Obtención de la clave de API.

Obtención de la huella digital de clave de firma


Para solicitar una clave de API de Maps de Google, debe conocer la huella digital SHA-1 del almacén de claves
que se usa para firmar la aplicación. Normalmente, esto significa que tendrá que determinar la huella digital
SHA-1 para el almacén de claves de depuración y, a continuación, la huella digital SHA-1 para el almacén de
claves que se usa para firmar la aplicación para su lanzamiento.
Visual Studio
Visual Studio para Mac
De forma predeterminada, el almacén de claves que se usa para firmar las versiones de depuración de una
aplicación de Xamarin. Android se puede encontrar en la siguiente ubicación:
C:\usuarios\[nombre de\usuario\]\AppData\local Xamarin mono\for Android Debug. keystore
La información acerca de un almacén de claves se obtiene ejecutando el comando keytool desde el JDK. Esta
herramienta se encuentra normalmente en el directorio bin de Java:
C:\archivos de programa (x86\)\Java JDK [versión\]\bin keytool. exe
Ejecute keytool con el siguiente comando (con las rutas de acceso de archivo que se muestran arriba):

keytool -list -v -keystore [STORE FILENAME] -alias [KEY NAME] -storepass [STORE PASSWORD] -keypass [KEY
PASSWORD]

Ejemplo de Debug. keystore


Para la clave de depuración predeterminada (que se crea automáticamente para su depuración), use este
comando:
Visual Studio
Visual Studio para Mac

keytool.exe -list -v -keystore "C:\Users\[USERNAME]\AppData\Local\Xamarin\Mono for Android\debug.keystore" -


alias androiddebugkey -storepass android -keypass android

Claves de producción
Al implementar una aplicación en Google Play, debe estar firmada con una clave privada. keytool Tendrá que
ejecutarse con los detalles de la clave privada y la huella digital de SHA-1 resultante utilizada para crear una clave
de API de Google Maps de producción. Recuerde actualizar el archivo archivo AndroidManifest. XML con la
clave de API de Google Maps correcta antes de la implementación.
Salida de keytool
Debería ver algo parecido a la siguiente salida en la ventana de la consola:

Alias name: androiddebugkey


Creation date: Jan 01, 2016
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=Android Debug, O=Android, C=US
Issuer: CN=Android Debug, O=Android, C=US
Serial number: 4aa9b300
Valid from: Mon Jan 01 08:04:04 UTC 2013 until: Mon Jan 01 18:04:04 PST 2033
Certificate fingerprints:
MD5: AE:9F:95:D0:A6:86:89:BC:A8:70:BA:34:FF:6A:AC:F9
SHA1: BB:0D:AC:74:D3:21:E1:43:07:71:9B:62:90:AF:A1:66:6E:44:5D:75
Signature algorithm name: SHA1withRSA
Version: 3

En esta guía, usará la huella digital SHA-1 (enumerada después de SHA1).

Creación de un proyecto de API


Una vez que haya recuperado la huella digital SHA-1 del almacén de claves de firma, es necesario crear un nuevo
proyecto en la consola de API de Google (o agregar el servicio Google Maps Android API V2 a un proyecto
existente).
1. En un explorador, vaya al Panel de Google Developers Console API & Services y haga clic en seleccionar
un proyecto. Haga clic en un nombre de proyecto o cree uno nuevo haciendo clic en nuevo proyecto:

2. Si ha creado un proyecto nuevo, escriba el nombre del proyecto en el cuadro de diálogo nuevo proyecto
que se muestra. Este cuadro de diálogo fabricará un identificador de proyecto único basado en el nombre
del proyecto. A continuación, haga clic en el botón crear , tal como se muestra en este ejemplo:
3. Después de un minuto, se crea el proyecto y se le dirigirá a la página Panel del proyecto. Desde allí, haga
clic en Habilitar API y servicios:

4. En la página biblioteca de API , haga clic en Maps SDK for Android. En la página siguiente, haga clic en
Habilitar para activar el servicio para este proyecto:
En este momento se ha creado el proyecto de API y se le ha agregado Google Maps API de Android v2. Sin
embargo, no puede usar esta API en el proyecto hasta que cree las credenciales para ella. En la sección siguiente
se explica cómo crear una clave de API y una lista en blanco una aplicación de Xamarin. Android para que esté
autorizada para usar esta clave.

Obtención de la clave de API


Una vez creado el proyecto de API de Google Developer Console , es necesario crear una clave de API de
Android. Las aplicaciones de Xamarin. Android deben tener una clave de API antes de que se les conceda acceso
a Android Map API V2.
1. En la página mapas SDK para Android que se muestra (después de hacer clic en Habilitar en el paso
anterior), vaya a la pestaña credenciales y haga clic en el botón crear credenciales :
2. Haga clic en clave de API:

3. Después de hacer clic en este botón, se genera la clave de API. A continuación, es necesario restringir esta
clave para que solo la aplicación pueda llamar a las API con esta clave. Haga clic en restringir clave:
4. Cambie el campo de nombre de la clave de API 1 a un nombre que le ayude a recordar para qué se usa
la clave (XamarinMapsDemoKey se usa en este ejemplo). A continuación, haga clic en el botón de radio
aplicaciones Android :
5. Para agregar la huella digital SHA-1, haga clic en + Agregar nombre de paquete y huella digital:

6. Escriba el nombre del paquete de la aplicación y escriba la huella digital del certificado Sha- keytool 1
(obtenida a través de como se explicó anteriormente en esta guía). En el ejemplo siguiente, se escribe el
nombre XamarinMapsDemo del paquete para, seguido de la huella digital del certificado SHA-1 obtenida de
Debug. keystore:
7. Tenga en cuenta que, en orden para el APK tener acceso a Google Maps, debe incluir las huellas digitales
de SHA-1 y empaquetar los nombres para cada almacén de claves (debug y release) que usó para firmar el
APK. Por ejemplo, si usa un equipo para depuración y otro equipo para generar el APK de lanzamiento,
debe incluir la huella digital de certificado de SHA-1 desde el almacén de claves de depuración del primer
equipo y la huella digital de certificado de SHA-1 desde el almacén de claves de la versión de el segundo
equipo. Haga clic en + Agregar nombre de paquete y huella digital para agregar otra huella digital y el
nombre del paquete, tal como se muestra en este ejemplo:

8. Haga clic en el botón Guardar para guardar los cambios. A continuación, se le devolverá a la lista de claves
de API. Si tiene otras claves de API que ha creado anteriormente, también se mostrarán aquí. En este
ejemplo, solo se muestra una clave de API (creada en los pasos anteriores):

Conectar el proyecto a una cuenta facturable


A partir del 11 de junio de 2018, la clave de API no funcionará si el proyecto no está conectado a una cuenta
facturable (aunque el servicio siga siendo gratuito para aplicaciones móviles).
1. Haga clic en el botón del menú hamburguesa y seleccione la página facturación :
2. Para vincular el proyecto a una cuenta de facturación, haga clic en vincular una cuenta de facturación
seguida de crear cuenta de facturación en el menú emergente mostrado (si no tiene una cuenta, se le
guiará para crear una nueva):

Agregar la clave al proyecto


Por último, agregue esta clave de API al archivo archivo AndroidManifest. XML de la aplicación de Xamarin.
Android. En el ejemplo siguiente, YOUR_API_KEY se reemplazará por la clave de API generada en los pasos
anteriores:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionName="4.10" package="com.xamarin.docs.android.mapsandlocationdemo"
android:versionCode="10">
...
<application android:label="@string/app_name">
<!-- Put your Google Maps V2 API Key here. -->
<meta-data android:name="com.google.android.maps.v2.API_KEY" android:value="YOUR_API_KEY" />
<meta-data android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
</application>
</manifest>

Vínculos relacionados
Consola de API de Google
La clave de API de Google Maps
keytool
Voz de Android
31/07/2019 • 17 minutes to read • Edit Online

En este artículo se tratan los aspectos básicos del uso del espacio de nombres de Android. Speech muy eficaz.
Desde su inicio, Android ha podido reconocer la voz y enviarla como texto. Es un proceso relativamente sencillo.
En el caso de texto a voz, sin embargo, el proceso es más complicado, ya que no solo es necesario tener en cuenta
el motor de voz, sino también los idiomas disponibles e instalados desde el sistema de texto a voz (TTS ).

Información general sobre voz


El hecho de tener un sistema, que "comprenda" la voz humana y la enunciates, lo que se va a escribir (voz a texto y
Text to Speech) es un área en constante crecimiento en el desarrollo móvil a medida que aumenta la demanda de
comunicación natural con nuestros dispositivos. Hay muchos casos en los que tener una característica que
convierte texto en voz, o viceversa, es una herramienta muy útil para incorporar a la aplicación Android.
Por ejemplo, con la abrazadera en el uso del teléfono móvil durante la conducción, los usuarios quieren una forma
gratuita de trabajar con sus dispositivos. La gran cantidad de factores de forma de Android diferentes, como el
desgaste de Android, y la inclusión en constante ampliación de aquellos que pueden usar dispositivos Android
(como tabletas y paneles de notas), ha creado un enfoque más grande en aplicaciones TTS excelentes.
Google proporciona al desarrollador un amplio conjunto de API en el espacio de nombres de Android. Speech
para abarcar la mayoría de las instancias de hacer que el dispositivo "tenga en cuenta la voz" (por ejemplo, el
software diseñado para la persiana). El espacio de nombres incluye la utilidad para permitir que el texto se traduzca
Android.Speech.Tts en voz a través, control sobre el motor usado para realizar la traducción, así como
RecognizerIntent un número de s que permiten convertir la voz en texto.

Aunque las instalaciones están allí para que se entienda la voz, existen limitaciones basadas en el hardware usado.
Es poco probable que el dispositivo interprete correctamente todo lo que se le diga en cada idioma disponible.

Requisitos
No hay ningún requisito especial para esta guía, aparte del dispositivo que tiene un micrófono y un altavoz.
El núcleo de un dispositivo Android que interpreta la voz es el uso de Intent un con un OnActivityResult
correspondiente. Sin embargo, es importante reconocer que la voz no se entiende, pero se interpreta como texto.
La diferencia es importante.
La diferencia entre entender e interpretar
Una definición simple de entender es que puede determinar por tono y contexto el significado real de lo que se
está diciendo. Para interpretar solo significa que se tomen las palabras y se generen en otro formato.
Considere el siguiente ejemplo sencillo que se usa en la conversación diaria:
¿Hola cómo estás?

Sin inflexión (énfasis en determinadas palabras o partes de palabras), se trata de una pregunta sencilla. Sin
embargo, si se aplica un ritmo lento a la línea, la persona que realiza escuchas detectará que el autor de la pregunta
no está demasiado satisfecho y quizás sea necesario que se ponga en contacto con él. Si el énfasis se coloca en
"es", la persona que solicita está normalmente más interesada en la respuesta.
Sin un procesamiento de audio bastante eficaz para hacer uso de la inflexión y un grado de inteligencia artificial
(AI) para comprender el contexto, el software no puede incluso empezar a comprender lo que se dijo; lo más
sencillo es convertir la voz en texto.

Configuración
Antes de usar el sistema de voz, siempre es aconsejable comprobar para asegurarse de que el dispositivo tiene un
micrófono. En un panel de notas de Kindle o Google, no hay ningún micrófono instalado.
En el ejemplo de código siguiente se muestra cómo consultar si un micrófono está disponible y, si no, para crear
una alerta. Si no hay micrófono disponible en este momento, se cerrará la actividad o se deshabilitará la capacidad
de grabar la voz.

string rec = Android.Content.PM.PackageManager.FeatureMicrophone;


if (rec != "android.hardware.microphone")
{
var alert = new AlertDialog.Builder(recButton.Context);
alert.SetTitle("You don't seem to have a microphone to record with");
alert.SetPositiveButton("OK", (sender, e) =>
{
return;
});
alert.Show();
}

Crear el intento
La intención del sistema de voz utiliza un tipo determinado de intento denominado RecognizerIntent . Esta
intención controla un gran número de parámetros, incluido el tiempo que se debe esperar con el silencio hasta que
la grabación se considere, cualquier lenguaje adicional que se reconozca y se genere, y Intent cualquier texto que
se incluya en el cuadro de diálogo modal de la instrucción. En este fragmento de VOICE código, readonly int se
usa para el OnActivityResult reconocimiento en.

var voiceIntent = new Intent(RecognizerIntent.ActionRecognizeSpeech);


voiceIntent.PutExtra(RecognizerIntent.ExtraLanguageModel, RecognizerIntent.LanguageModelFreeForm);
voiceIntent.PutExtra(RecognizerIntent.ExtraPrompt,
Application.Context.GetString(Resource.String.messageSpeakNow));
voiceIntent.PutExtra(RecognizerIntent.ExtraSpeechInputCompleteSilenceLengthMillis, 1500);
voiceIntent.PutExtra(RecognizerIntent.ExtraSpeechInputPossiblyCompleteSilenceLengthMillis, 1500);
voiceIntent.PutExtra(RecognizerIntent.ExtraSpeechInputMinimumLengthMillis, 15000);
voiceIntent.PutExtra(RecognizerIntent.ExtraMaxResults, 1);
voiceIntent.PutExtra(RecognizerIntent.ExtraLanguage, Java.Util.Locale.Default);
StartActivityForResult(voiceIntent, VOICE);

Conversión de la voz
El texto que se interpreta de la voz se entregará Intent en, que se devuelve cuando se ha completado la actividad y
se tiene acceso GetStringArrayListExtra(RecognizerIntent.ExtraResults) a ella a través de. Esto devolverá
IList<string> una, de la que se puede usar y mostrar el índice, en función del número de idiomas solicitados en el
intento del autor de la llamada RecognizerIntent.ExtraMaxResults (y especificados en). A pesar de cualquier lista,
merece la pena comprobar para asegurarse de que hay datos que se van a mostrar.
Al escuchar el valor devuelto de StartActivityForResult , se debe proporcionar el OnActivityResult método.
En el ejemplo siguiente, textBox es un TextBox que se usa para la salida de lo que se ha dictado. Se podría usar
igualmente para pasar el texto a algún tipo de intérprete y, desde allí, la aplicación puede comparar el texto y la
bifurcación con otra parte de la aplicación.
protected override void OnActivityResult(int requestCode, Result resultVal, Intent data)
{
if (requestCode == VOICE)
{
if (resultVal == Result.Ok)
{
var matches = data.GetStringArrayListExtra(RecognizerIntent.ExtraResults);
if (matches.Count != 0)
{
string textInput = textBox.Text + matches[0];
textBox.Text = textInput;
switch (matches[0].Substring(0, 5).ToLower())
{
case "north":
MovePlayer(0);
break;
case "south":
MovePlayer(1);
break;
}
}
else
{
textBox.Text = "No speech was recognised";
}
}
base.OnActivityResult(requestCode, resultVal, data);
}
}

Text to Speech
El texto a voz no es bastante inverso a la voz del texto y se basa en dos componentes clave: un motor de texto a voz
instalado en el dispositivo y un idioma que se está instalando.
En gran medida, los dispositivos Android tienen instalado el servicio de TTS predeterminado de Google y al menos
un idioma. Esto se establece cuando el dispositivo se configura por primera vez y se basará en el lugar en el que se
encuentra el dispositivo (por ejemplo, un teléfono configurado en Alemania instalará el idioma alemán, mientras
que uno en America tendrá inglés americano).
Paso 1: crear una instancia de TextToSpeech
TextToSpeech puede tardar hasta 3 parámetros, los dos primeros son obligatorios, y el tercero es AppContext
opcional IOnInitListener ( engine ,,). El agente de escucha se usa para enlazar con el servicio y probar si hay
errores con el motor como cualquier número de texto Android disponible para los motores de voz. Como mínimo,
el dispositivo tendrá el propio motor de Google.
Paso 2: búsqueda de los idiomas disponibles
La Java.Util.Locale clase contiene un método útil denominado GetAvailableLocales() . Esta lista de idiomas
admitidos por el motor de voz se puede probar con los idiomas instalados.
Es una cuestión trivial generar la lista de idiomas "entendidos". Siempre habrá un idioma predeterminado (el
idioma que el usuario estableció al configurar el dispositivo por primera vez), por lo que en este ejemplo
List<string> el tiene el valor "default" como primer parámetro, el resto de la lista se rellenará en función del
resultado textToSpeech.IsLanguageAvailable(locale) de.
var langAvailable = new List<string>{ "Default" };
var localesAvailable = Java.Util.Locale.GetAvailableLocales().ToList();
foreach (var locale in localesAvailable)
{
var res = textToSpeech.IsLanguageAvailable(locale);
switch (res)
{
case LanguageAvailableResult.Available:
langAvailable.Add(locale.DisplayLanguage);
break;
case LanguageAvailableResult.CountryAvailable:
langAvailable.Add(locale.DisplayLanguage);
break;
case LanguageAvailableResult.CountryVarAvailable:
langAvailable.Add(locale.DisplayLanguage);
break;
}
}
langAvailable = langAvailable.OrderBy(t => t).Distinct().ToList();

Este código llama a TextToSpeech. IsLanguageAvailable para comprobar si el paquete de idioma de una
configuración regional determinada ya está presente en el dispositivo. Este método devuelve un
LanguageAvailableResult, que indica si el idioma de la configuración regional que se pasa está disponible. Si
LanguageAvailableResult indica que el idioma es NotSupported , no hay ningún paquete de voz disponible (incluso
para su descarga) para ese idioma. Si LanguageAvailableResult está establecido en MissingData , es posible
descargar un nuevo paquete de idioma, tal y como se explica más adelante en el paso 4.
Paso 3: establecimiento de la velocidad y el paso
Android permite al usuario modificar el sonido de la voz mediante la SpeechRate modificación de y Pitch (la
velocidad de velocidad y el tono de la voz). Esto va de 0 a 1, con la voz "normal" en 1 para ambos.
Paso 4: probar y cargar nuevos idiomas
La descarga de un nuevo lenguaje se realiza mediante Intent un. El resultado de este intento hace que se invoque
el método OnActivityResult . A diferencia del ejemplo de conversión de voz a texto (que usaba RecognizerIntent
como PutExtra parámetro de Intent ), las pruebas y las cargas Intent se Action basan en:
TextToSpeech. Engine. ActionCheckTtsData – inicia una actividad del motor de TextToSpeech plataforma
para comprobar la correcta instalación y disponibilidad de los recursos de idioma en el dispositivo.
TextToSpeech. Engine. ActionInstallTtsData – inicia una actividad que pide al usuario que descargue los
idiomas necesarios.
En el ejemplo de código siguiente se muestra cómo usar estas acciones para probar los recursos de idioma y
descargar un nuevo idioma:

var checkTTSIntent = new Intent();


checkTTSIntent.SetAction(TextToSpeech.Engine.ActionCheckTtsData);
StartActivityForResult(checkTTSIntent, NeedLang);
//
protected override void OnActivityResult(int req, Result res, Intent data)
{
if (req == NeedLang)
{
var installTTS = new Intent();
installTTS.SetAction(TextToSpeech.Engine.ActionInstallTtsData);
StartActivity(installTTS);
}
}
TextToSpeech.Engine.ActionCheckTtsData comprueba la disponibilidad de los recursos de idioma. OnActivityResult
se invoca cuando se completa esta prueba. Si es necesario descargar recursos de idioma, OnActivityResult se
desencadena la TextToSpeech.Engine.ActionInstallTtsData acción de iniciar una actividad que permite al usuario
descargar los idiomas necesarios. Tenga en cuenta OnActivityResult que esta implementación no comprueba
Result el código porque, en este ejemplo simplificado, ya se ha realizado la determinación de que es necesario
descargar el paquete de idioma.
La TextToSpeech.Engine.ActionInstallTtsData acción hace que la actividad de datos de voz de Google TTS se
presente al usuario para elegir los idiomas que se van a descargar:

Por ejemplo, el usuario podría elegir francés y hacer clic en el icono de descarga para descargar datos de voz en
francés:

La instalación de estos datos se produce automáticamente una vez completada la descarga.


Paso 5: IOnInitListener
Para que una actividad pueda convertir el texto en voz, se debe implementar el método OnInit de interfaz (es
decir, el segundo parámetro especificado para la creación de instancias de la TextToSpeech clase). Esto inicializa el
agente de escucha y prueba el resultado.
El agente de OperationResult.Success escucha debe probar y OperationResult.Failure como mínimo. En el
ejemplo siguiente se muestra solo eso:

void TextToSpeech.IOnInitListener.OnInit(OperationResult status)


{
// if we get an error, default to the default language
if (status == OperationResult.Error)
textToSpeech.SetLanguage(Java.Util.Locale.Default);
// if the listener is ok, set the lang
if (status == OperationResult.Success)
textToSpeech.SetLanguage(lang);
}

Resumen
En esta guía hemos analizado los aspectos básicos de la conversión de texto a voz y voz a texto y métodos posibles
de cómo incluirlos en sus propias aplicaciones. Aunque no cubren cada caso determinado, ahora debe tener un
conocimiento básico de cómo se interpreta la voz, cómo instalar nuevos idiomas y cómo aumentar el inclusivity de
las aplicaciones.

Vínculos relacionados
DependencyService de Xamarin. Forms
Text to Speech (ejemplo)
Voz a texto (ejemplo)
Espacio de nombres Android. Speech
Espacio de nombres Android. Speech. TTS
Integración de Java con Xamarin. Android
16/08/2019 • 5 minutes to read • Edit Online

El ecosistema de Java incluye una colección de componentes diversa y inmensa. Muchos de estos componentes se
pueden usar para reducir el tiempo necesario para desarrollar una aplicación de Android. En este documento se
proporciona información general de alto nivel de algunas de las formas en que los desarrolladores pueden usar
estos componentes de Java existentes para mejorar la experiencia de desarrollo de aplicaciones de Xamarin.
Android.

Información general
Dada la extensión del ecosistema Java, es muy probable que cualquier funcionalidad determinada necesaria para
una aplicación de Xamarin. Android ya se haya codificado en Java. Por este motivo, es atractivo probar y volver a
usar estas bibliotecas existentes al crear una aplicación de Xamarin. Android.
Hay tres formas posibles de volver a usar las bibliotecas de Java en una aplicación de Xamarin. Android:
Creación de una biblioteca de enlaces de Java Con esta técnica, se usa un proyecto de Xamarin.
Android para C# crear contenedores alrededor de los tipos de Java. – Una aplicación de Xamarin. Android
puede hacer referencia C# a los contenedores creados por este proyecto y, a continuación .jar , usar el
archivo.
Interfaz nativa de Java C++ C# Java Native Interface (JNI) es un marco de trabajo que permite que el
código que no es Java (como o) llame a o sea llamado por el código de Java que se ejecuta dentro de una
JVM. –
Portar el código Este método implica tomar el código fuente Java y, a continuación, convertirlo en C# –
Esto se puede hacer manualmente o mediante una herramienta automatizada como el enfoque.
En el núcleo de las dos primeras técnicas se encuentra Java Native Interface (JNI). JNI es un marco que permite a
las aplicaciones no escritas en Java interactuar con el código Java que se ejecuta en un Máquina virtual Java.
Xamarin. Android usa JNI para crear enlaces para C# el código.
La primera técnica es un enfoque más automatizado y declarativo para enlazar bibliotecas de Java. Implica el uso
de Visual Studio para Mac o de un tipo de proyecto de Visual Studio proporcionado por Xamarin. – Android en la
biblioteca de enlaces de Java. Para crear correctamente estos enlaces, es posible que una biblioteca de enlaces de
Java siga requiriendo algunas modificaciones manuales, pero no tantas como sea un enfoque de JNI puro. Vea
enlazar una biblioteca de Java para obtener más información sobre las bibliotecas de enlace de Java.
La segunda técnica, con JNI, funciona en un nivel mucho menor, pero puede proporcionar un mayor control y
acceso a los métodos de Java que normalmente no serían accesibles a través de una biblioteca de enlace de Java.
La tercera técnica es radicalmente diferente de las dos anteriores: trasladar el código de Java a C#. Trasladar
código de un idioma a otro puede ser un proceso muy laborioso, pero es posible reducir ese esfuerzo con la ayuda
de una herramienta denominada nitidez. Sharp es una herramienta de código abierto que es una herramienta de
JavaC# a convertidor.

Resumen
En este documento se proporciona información general de alto nivel sobre algunas de las distintas formas en que
las bibliotecas de Java se pueden volver a usar en una aplicación de Xamarin. Android. Se introdujeron los
conceptos de los enlaces y los contenedores a los que se puede llamar administrados, y se explican las opciones
para migrar código Java a C#.

Vínculos relacionados
Arquitectura
Enlace de una biblioteca Java
Trabajar con JNI
Dar nitidez
Interfaz nativa de Java
Contenedores de Android Callable para Xamarin.
Android
16/08/2019 • 6 minutes to read • Edit Online

Los contenedores a los que se puede llamar de Android (ACWs) son necesarios siempre que el tiempo de
ejecución de Android invoca código administrado. Estos contenedores son necesarios porque no hay ninguna
manera de registrar clases con arte (el tiempo de ejecución de Android) en tiempo de ejecución. (Concretamente,
la función DefineClass () de JNI no es compatible con el tiempo de ejecución de Android.} Los contenedores a los
que se puede llamar de Android componen la falta de compatibilidad con el registro de tipo en tiempo de
ejecución.
Cada vez El código de Android necesita ejecutar virtual un método de interfaz o overridden que se
implementa en código administrado, Xamarin. Android debe proporcionar un proxy de Java para que este
método se envíe al tipo administrado adecuado. Estos tipos de proxy Java son código Java que tiene la misma
clase base y la misma lista de interfaces de Java que el tipo administrado, implementando los mismos
constructores y declarando cualquier método de interfaz y clase base invalidado.
Los contenedores a los que se puede llamar de Android se generan mediante el programa monodroid. exe
durante el proceso de compilación: se generan para todos los tipos que heredan (directa o indirectamente) java.
lang. Object.

Nombres de contenedor de Android Callable


Los nombres de paquete de los contenedores a los que se puede llamar de Android se basan en el MD5SUM del
nombre calificado con el ensamblado del tipo que se va a exportar. Esta técnica de nomenclatura permite que el
mismo nombre de tipo completo esté disponible en ensamblados diferentes sin introducir un error de
empaquetado.
Debido a este esquema de nomenclatura de MD5SUM, no puede acceder directamente a los tipos por nombre.
Por ejemplo, el siguiente adb comando no funcionará porque el nombre my.ActivityType de tipo no se genera
de forma predeterminada:

adb shell am start -n My.Package.Name/my.ActivityType

Además, es posible que vea errores como los siguientes si intenta hacer referencia a un tipo por nombre:

java.lang.ClassNotFoundException: Didn't find class "com.company.app.MainActivity"


on path: DexPathList[[zip file "/data/app/com.company.App-1.apk"] ...

Si requiere acceso a los tipos por nombre, puede declarar un nombre para ese tipo en una declaración de
atributo. Por ejemplo, este es el código que declara una actividad con el nombre My.ActivityType completo:

namespace My {
[Activity]
public partial class ActivityType : Activity {
/* ... */
}
}
La ActivityAttribute.Name propiedad se puede establecer para declarar explícitamente el nombre de esta
actividad:

namespace My {
[Activity(Name="my.ActivityType")]
public partial class ActivityType : Activity {
/* ... */
}
}

Una vez agregada la configuración de my.ActivityType esta propiedad, se puede tener acceso a ella por su adb
nombre desde el código externo y desde los scripts. El Name atributo se puede establecer para muchos tipos
diferentes, Activity entre los que BroadcastReceiver se incluyen ContentProvider , Application , Service , y:
ActivityAttribute.Name
ApplicationAttribute.Name
ServiceAttribute.Name
BroadcastReceiverAttribute.Name
ContentProviderAttribute.Name
Los nombres de ACW basados en MD5SUM se introdujeron en Xamarin. Android 5,0. Para obtener más
información sobre la nomenclatura de atributos, vea RegisterAttribute.

Implementar interfaces
Hay ocasiones en las que puede que necesite implementar una interfaz de Android, como Android. Content.
IComponentCallbacks. Dado que todas las clases e interfaces de Android amplían la interfaz de Android.
Runtime. IJavaObject , surge la pregunta: IJavaObject ¿cómo se implementa?
La pregunta se respondió anteriormente: el motivo por el que todos los tipos IJavaObject de Android deben
implementarse es para que Xamarin. Android tenga un contenedor de Android al que se puede llamar para
proporcionar a Android, es decir, un proxy de Java para el tipo especificado. Dado que monodroid. exe solo
busca Java.Lang.Object subclases e Java.Lang.Object implementa IJavaObject, la respuesta es obvia: subclase
Java.Lang.Object :

class MyComponentCallbacks : Java.Lang.Object, Android.Content.IComponentCallbacks {

public void OnConfigurationChanged (Android.Content.Res.Configuration newConfig)


{
// implementation goes here...
}

public void OnLowMemory ()


{
// implementation goes here...
}
}

Detalles de implementación
El resto de esta página proporciona detalles de implementación sujetos a cambios sin previo aviso (y se presenta
aquí solo porque los desarrolladores tendrán curiosidad sobre lo que está ocurriendo).
Por ejemplo, dado el siguiente C# origen:
using System;
using Android.App;
using Android.OS;

namespace Mono.Samples.HelloWorld
{
public class HelloAndroid : Activity
{
protected override void OnCreate (Bundle savedInstanceState)
{
base.OnCreate (savedInstanceState);
SetContentView (R.layout.main);
}
}
}

El programa mandroid. exe generará el siguiente contenedor de Android al que se puede llamar:

package mono.samples.helloWorld;

public class HelloAndroid


extends android.app.Activity
{
static final String __md_methods;
static {
__md_methods = "n_onCreate:(Landroid/os/Bundle;)V:GetOnCreate_Landroid_os_Bundle_Handler\n" + "";
mono.android.Runtime.register (
"Mono.Samples.HelloWorld.HelloAndroid, HelloWorld, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null", HelloAndroid.class, __md_methods);
}

public HelloAndroid ()
{
super ();
if (getClass () == HelloAndroid.class)
mono.android.TypeManager.Activate (
"Mono.Samples.HelloWorld.HelloAndroid, HelloWorld, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null", "", this, new java.lang.Object[] { });
}

@Override
public void onCreate (android.os.Bundle p0)
{
n_onCreate (p0);
}

private native void n_onCreate (android.os.Bundle p0);


}

Observe que se conserva la clase base y native que se proporcionan declaraciones de método para cada
método invalidado en el código administrado.
Trabajo con JNI y Xamarin. Android
16/08/2019 • 92 minutes to read • Edit Online

Xamarin. Android permite escribir aplicaciones Android con C# en lugar de Java. Se proporcionan varios
ensamblados con Xamarin. Android que proporcionan enlaces para las bibliotecas de Java, incluidos mono.
Android. dll y mono. Android. GoogleMaps. dll. Sin embargo, no se proporcionan enlaces para cada posible
biblioteca Java, y los enlaces que se proporcionan no pueden enlazar todos los tipos y miembros de Java. Para
usar tipos y miembros de Java sin enlazar, se puede usar la interfaz nativa de Java (JNI ). En este artículo se
muestra cómo usar JNI para interactuar con tipos y miembros de Java desde aplicaciones de Xamarin. Android.

Información general
No siempre es necesario o no es posible crear un contenedor al que se puede llamar (MCW ) administrado para
invocar código Java. En muchos casos, el JNI "inline" es absolutamente aceptable y útil para el uso único de
miembros de Java sin enlazar. A menudo es más fácil usar JNI para invocar un solo método en una clase de Java
que generar un enlace jar completo.
Xamarin. Android proporciona el Mono.Android.dll ensamblado, que proporciona un enlace para la android.jar
biblioteca de Android. Los tipos y miembros que no Mono.Android.dll están presentes en los tipos android.jar
y que no están presentes en se pueden utilizar para enlazarlos manualmente. Para enlazar tipos y miembros de
Java, se usa la interfaz nativa de Java (JNI ) para buscar tipos, leer y escribir campos e invocar métodos.
La API de JNI en Xamarin. Android es conceptualmente muy similar a System.Reflection la API de .net: permite
buscar tipos y miembros por nombre, leer y escribir valores de campo, invocar métodos, etc. Puede usar JNI y el
Android.Runtime.RegisterAttribute atributo personalizado para declarar métodos virtuales que se pueden
enlazar para admitir el reemplazo. Puede enlazar interfaces para que se puedan implementar en C#.
En este documento se explica:
Cómo JNI hace referencia a los tipos.
Cómo buscar, leer y escribir campos.
Cómo buscar e invocar métodos.
Cómo exponer métodos virtuales para permitir el reemplazo desde código administrado.
Cómo exponer interfaces.

Requisitos
JNI, tal y como se expone a través del espacio de nombres Android. Runtime. JNIEnv, está disponible en todas
las versiones de Xamarin. Android. Para enlazar tipos e interfaces de Java, debe usar Xamarin. Android 4,0 o
posterior.

Contenedores a los que se puede llamar administrados


Un contenedor al que se puede llamar administrado (MCW ) es un enlace para una clase o interfaz de Java
que incluye toda la maquinaria JNI para C# que el código de cliente no tenga que preocuparse por la
complejidad subyacente de JNI. La mayoría Mono.Android.dll de consta de contenedores a los que se puede
llamar administrados.
Los contenedores a los que se puede llamar tienen dos propósitos:
1. Encapsular el uso de JNI para que el código de cliente no tenga que conocer la complejidad subyacente.
2. Permite que los tipos de Java de subclases e implementen interfaces de Java.
El primer propósito es solo por comodidad y encapsulación de complejidad para que los consumidores tengan
un conjunto sencillo y administrado de clases para usar. Esto requiere el uso de los distintos miembros de JNIEnv
tal y como se describe más adelante en este artículo. Tenga en cuenta que los contenedores a los que se puede –
llamar administrados no son estrictamente necesarios "en línea" el uso de JNI es absolutamente aceptable y es
útil para el uso único de miembros de Java sin enlazar. La subclase y la implementación de la interfaz requieren el
uso de contenedores a los que se puede llamar administrados.

Contenedores que se pueden llamar de Android


Los contenedores a los que se puede llamar de Android (ACW ) son necesarios siempre que el tiempo de
ejecución de Android (ART) debe invocar código administrado. Estos contenedores son necesarios porque no hay
ninguna manera de registrar clases con arte en tiempo de ejecución. (En concreto, la función JNI de DefineClass
no es compatible con el tiempo de ejecución de Android. Por lo tanto, los contenedores a los que se puede llamar
de Android constituyen la falta de compatibilidad con el registro de tipos en tiempo de ejecución.
Cada vez que el código de Android necesita ejecutar un método virtual o de interfaz que se invalida o se
implementa en código administrado, Xamarin. Android debe proporcionar un proxy de Java para que este
método se envíe al tipo administrado adecuado. Estos tipos de proxy Java son código Java que tienen la misma
clase base y la misma lista de interfaces de Java que el tipo administrado, implementando los mismos
constructores y declarando cualquier método de interfaz y clase base invalidado.
Los contenedores a los que se puede llamar de Android se generan mediante el programa monodroid. exe
durante el proceso de compilación, y se generan para todos los tipos que heredan (directa o indirectamente) java.
lang. Object.
Implementar interfaces
Hay ocasiones en las que puede que necesite implementar una interfaz de Android (como Android. Content.
IComponentCallbacks).
Todas las clases e interfaces de Android amplían la interfaz de Android. Runtime. IJavaObject. por lo tanto, todos
los tipos IJavaObject de Android deben implementar. Xamarin. Android se aprovecha de este hecho – que usa
IJavaObject para proporcionar Android con un proxy de Java (un contenedor de Android al que se puede
llamar) para el tipo administrado dado. Dado que monodroid. exe solo busca Java.Lang.Object subclases (que
deben implementar IJavaObject ), la subclase Java.Lang.Object nos proporciona una manera de implementar
interfaces en código administrado. Por ejemplo:

class MyComponentCallbacks : Java.Lang.Object, Android.Content.IComponentCallbacks {


public void OnConfigurationChanged (Android.Content.Res.Configuration newConfig) {
// implementation goes here...
}
public void OnLowMemory () {
// implementation goes here...
}
}

Detalles de implementación
En el resto de este artículo se proporcionan detalles de implementación sujetos a cambios sin previo aviso . (y se
presenta aquí solo porque los desarrolladores pueden tener curiosidad sobre lo que está ocurriendo en el capó).
Por ejemplo, dado el siguiente C# origen:
using System;
using Android.App;
using Android.OS;

namespace Mono.Samples.HelloWorld
{
public class HelloAndroid : Activity
{
protected override void OnCreate (Bundle savedInstanceState)
{
base.OnCreate (savedInstanceState);
SetContentView (R.layout.main);
}
}
}

El programa mandroid. exe generará el siguiente contenedor de Android al que se puede llamar:

package mono.samples.helloWorld;

public class HelloAndroid extends android.app.Activity {


static final String __md_methods;
static {
__md_methods =
"n_onCreate:(Landroid/os/Bundle;)V:GetOnCreate_Landroid_os_Bundle_Handler\n" +
"";
mono.android.Runtime.register (
"Mono.Samples.HelloWorld.HelloAndroid, HelloWorld, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null",
HelloAndroid.class,
__md_methods);
}

public HelloAndroid ()
{
super ();
if (getClass () == HelloAndroid.class)
mono.android.TypeManager.Activate (
"Mono.Samples.HelloWorld.HelloAndroid, HelloWorld, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null",
"", this, new java.lang.Object[] { });
}

@Override
public void onCreate (android.os.Bundle p0)
{
n_onCreate (p0);
}

private native void n_onCreate (android.os.Bundle p0);


}

Observe que la clase base se conserva y se proporcionan las declaraciones de método nativo para cada método
que se reemplaza dentro del código administrado.
ExportAttribute y ExportFieldAttribute
Normalmente, Xamarin. Android genera automáticamente el código Java que comprende el ACW; esta
generación se basa en los nombres de clase y método cuando una clase se deriva de una clase de Java e invalida
los métodos de Java existentes. Sin embargo, en algunos escenarios, la generación de código no es adecuada,
como se describe a continuación:
Android admite nombres de acción en los atributos XML de diseño, por ejemplo, el atributo XML Android:
OnClick . Cuando se especifica, la instancia de vista no plana intenta buscar el método Java.
La interfaz java. IO. serializable requiere readObject métodos writeObject y. Dado que no son miembros
de esta interfaz, nuestra implementación administrada correspondiente no expone estos métodos a código
Java.
La interfaz de Android. os. reutilizable espera que una clase de implementación deba tener un CREATOR
campo estático Parcelable.Creator de tipo. El código Java generado requiere algún campo explícito. Con
nuestro escenario estándar, no hay ninguna manera de enviar el campo en código Java desde código
administrado.
Dado que la generación de código no proporciona una solución para generar métodos Java arbitrarios con
nombres arbitrarios, a partir de Xamarin. Android 4,2, ExportAttribute y ExportFieldAttribute se introdujeron
para ofrecer una solución a lo anterior situación. Ambos atributos residen en el Java.Interop espacio de
nombres:
ExportAttribute – especifica un nombre de método y sus tipos de excepción esperados (para proporcionar
"throws" explícitos en Java). Cuando se usa en un método, el método "exporta" un método Java que
genera un código de envío a la invocación de JNI correspondiente al método administrado. Se puede usar
con android:onClick y. java.io.Serializable
ExportFieldAttribute – especifica un nombre de campo. Reside en un método que funciona como
inicializador de campo. Se puede usar con android.os.Parcelable .
El proyecto de ejemplo ExportAttribute muestra cómo utilizar estos atributos.
Solución de problemas de ExportAttribute y ExportFieldAttribute
Se produce un error de empaquetado debido a que falta mono. Android. Export. dll – si usa
ExportAttribute o ExportFieldAttribute en algunos métodos del código o bibliotecas dependientes, tiene
que agregar mono. Android. Export. dll. Este ensamblado está aislado para admitir el código de
devolución de llamada de Java. Es independiente de mono. Android. dll a medida que agrega tamaño
adicional a la aplicación.
En la compilación de versión, se produce – para los métodos de
MissingMethodException
MissingMethodException exportación de la compilación de versión, se produce para los métodos de
exportación. (Este problema se ha corregido en la versión más reciente de Xamarin. Android).
ExportParameterAttribute
ExportAttribute y ExportFieldAttribute proporcionan funcionalidad que el código en tiempo de ejecución de
Java puede usar. Este código en tiempo de ejecución tiene acceso al código administrado a través de los métodos
de JNI generados por esos atributos. Como resultado, no hay ningún método Java existente enlazado por el
método administrado; por lo tanto, el método de Java se genera a partir de una firma de método administrado.
Sin embargo, este caso no es totalmente determinante. En concreto, esto es cierto en algunas asignaciones
avanzadas entre tipos administrados y tipos de Java como:
InputStream
OutputStream
XmlPullParser
XmlResourceParser
Cuando se necesitan tipos como estos para los métodos exportados ExportParameterAttribute , debe usarse para
proporcionar explícitamente el parámetro o valor devuelto correspondiente a un tipo.
Atributo Annotation
En Xamarin. Android 4,2, se han IAnnotation convertido los tipos de implementación en atributos (System.
Attribute) y se ha agregado compatibilidad con la generación de anotaciones en contenedores de Java.
Esto significa que los siguientes cambios direccionales:
El generador de enlaces Java.Lang.DeprecatedAttribute genera java.Lang.Deprecated desde (mientras
debe estar [Obsolete] en código administrado).
Esto no significa que la clase Java.Lang.Deprecated existente desaparecerá. Estos objetos basados en Java
podrían seguir utilizándose como objetos Java usuales (si existe dicho uso). Habrá clases
DeprecatedAttribute y. Deprecated

La Java.Lang.DeprecatedAttribute clase se marca como [Annotation] . Cuando hay un atributo


personalizado que se hereda de este atributo [Annotation] , la tarea MSBuild generará una anotación
Java para ese atributo personalizado (@Deprecated) en el contenedor de Android al que se puede llamar
(ACW ).
Las anotaciones se pueden generar en clases, métodos y campos exportados (que es un método de código
administrado).
Si la clase contenedora (la propia clase anotada o la clase que contiene los miembros anotados) no está
registrada, no se genera ningún origen de la clase Java completa, incluidas las anotaciones. En el
ExportAttribute caso de los métodos, puede especificar para obtener el método generado explícitamente y
anotado. Además, no es una característica para "generar" una definición de clase de anotación de Java. En otras
palabras, si define un atributo administrado personalizado para una anotación determinada, tendrá que agregar
otra biblioteca. jar que contenga la clase de anotación de Java correspondiente. Agregar un archivo de código
fuente de Java que define el tipo de anotación no es suficiente. El compilador de Java no funciona de la misma
manera que apt.
Además, se aplican las siguientes limitaciones:
Este proceso de conversión no tiene @Target en cuenta la anotación en el tipo de anotación hasta ahora.
Los atributos en una propiedad no funcionan. En su lugar, use atributos para captador o establecedor de
propiedad.

Enlace de clases
Enlazar una clase significa escribir un contenedor al que se puede llamar administrado para simplificar la
invocación del tipo Java subyacente.
El enlace de métodos virtuales y abstractos para permitir C# el reemplazo desde requiere Xamarin. Android 4,0.
Sin embargo, cualquier versión de Xamarin. Android puede enlazar métodos no virtuales, métodos estáticos o
métodos virtuales sin admitir invalidaciones.
Normalmente, un enlace contiene los siguientes elementos:
Identificador de JNI para el tipo de Java que se está enlazando.
Identificadores de campo JNI y propiedades para cada campo enlazado.
Identificadores y métodos de método JNI para cada método enlazado.
Si se requiere la subclase, el tipo debe tener un atributo personalizado RegisterAttribute en la declaración
de tipos con RegisterAttribute. DoNotGenerateAcw establecido en true .
Declarar el identificador de tipo
Los métodos de búsqueda de campo y método requieren una referencia de objeto que haga referencia a su tipo
declarativo. Por Convención, se mantiene en un class_ref campo:
static IntPtr class_ref = JNIEnv.FindClass(CLASS);

Vea la sección referencias de tipos de JNI para obtener CLASS más información sobre el token.
Campos de enlace
Los campos de Java se C# exponen como propiedades; por ejemplo, el campo java.lang.System.in de Java se
enlaza como la C# propiedad java.lang.JavaSystem.in. Además, dado que JNI distingue entre los campos
estáticos y los campos de instancia, se usan diferentes métodos al implementar las propiedades.
El enlace de campo implica tres conjuntos de métodos:
1. Método de obtención de identificador de campo . El método Get Field ID es responsable de devolver un
identificador de campo que usarán los métodos Get Field Value y set Field Value . Para obtener el
identificador de campo es necesario conocer el tipo declarativo, el nombre del campo y la firma de tipo
JNI del campo.
2. Métodos de obtención de valor de campo . Estos métodos requieren el identificador de campo y son
responsables de leer el valor del campo desde Java. El método que se va a usar depende del tipo de
campo.
3. Los métodos set Field Value . Estos métodos requieren el identificador de campo y son responsables de
escribir el valor del campo en Java. El método que se va a usar depende del tipo de campo.
Los campos estáticos usan los métodos JNIEnv. GetStaticFieldID, JNIEnv.GetStatic*Field y JNIEnv.
SetStaticField .
Los campos de instancia usan los métodos JNIEnv. GetFieldID, JNIEnv.Get*Field y JNIEnv. SetField .
Por ejemplo, la propiedad JavaSystem.In estática se puede implementar como:

static IntPtr in_jfieldID;


public static System.IO.Stream In
{
get {
if (in_jfieldId == IntPtr.Zero)
in_jfieldId = JNIEnv.GetStaticFieldID (class_ref, "in", "Ljava/io/InputStream;");
IntPtr __ret = JNIEnv.GetStaticObjectField (class_ref, in_jfieldId);
return InputStreamInvoker.FromJniHandle (__ret, JniHandleOwnership.TransferLocalRef);
}
}

Nota: Estamos usando InputStreamInvoker. FromJniHandle para convertir la referencia de JNI en una
System.IO.Stream instancia de y estamos usando JniHandleOwnership.TransferLocalRef porque JNIEnv.
GetStaticObjectField devuelve una referencia local.
Muchos de los tipos de Android. Runtime tienen FromJniHandle métodos que convertirán una referencia de JNI
en el tipo deseado.
Enlace de método
Los métodos de Java se C# exponen C# como métodos y como propiedades. Por ejemplo, el método Java . lang.
Runtime. runFinalizersOnExit se enlaza como el método java. lang. Runtime. runFinalizersOnExit y el método
java. lang. Object. getClass está enlazado como java. lang. Object. class. propiedad.
La invocación de métodos es un proceso de dos pasos:
1. Identificador del método get para el método que se va a invocar. El método Get Method ID es responsable
de devolver un identificador de método que usarán los métodos de invocación de método. Para obtener el
identificador de método es necesario conocer el tipo declarativo, el nombre del método y la firma de tipo
JNI del método.
2. Invoque al método.
Al igual que con los campos, los métodos que se usan para obtener el identificador de método e invocar el
método difieren entre los métodos estáticos y los métodos de instancia.
Los métodos estáticos usan JNIEnv. GetStaticMethodID () para buscar el identificador de método y
JNIEnv.CallStatic*Method usar la familia de métodos para la invocación.

Los métodos de instancia usan JNIEnv. GetMethodID para buscar el identificador de método y
JNIEnv.Call*Method usar JNIEnv.CallNonvirtual*Method las familias de métodos y para la invocación.

El enlace de método es potencialmente más que simplemente invocación de método. El enlace de método
también incluye permitir que un método se invalide (para los métodos abstractos y no finales) o implementado
(para los métodos de interfaz). En la sección herencia, interfaces, se abordan las complejidades de la
compatibilidad de métodos virtuales y métodos de interfaz.
Métodos estáticos
Enlazar un método estático implica JNIEnv.GetStaticMethodID usar para obtener un identificador de método y, a
JNIEnv.CallStatic*Method continuación, utilizar el método adecuado, dependiendo del tipo de valor devuelto del
método. El siguiente es un ejemplo de un enlace para el método Runtime. getRuntime :

static IntPtr id_getRuntime;

[Register ("getRuntime", "()Ljava/lang/Runtime;", "")]


public static Java.Lang.Runtime GetRuntime ()
{
if (id_getRuntime == IntPtr.Zero)
id_getRuntime = JNIEnv.GetStaticMethodID (class_ref,
"getRuntime", "()Ljava/lang/Runtime;");

return Java.Lang.Object.GetObject<Java.Lang.Runtime> (
JNIEnv.CallStaticObjectMethod (class_ref, id_getRuntime),
JniHandleOwnership.TransferLocalRef);
}

Tenga en cuenta que el identificador de método se almacena en un id_getRuntime campo estático,. Se trata de
una optimización del rendimiento, de modo que no es necesario buscar el identificador del método en cada
invocación. No es necesario almacenar en caché el identificador del método de esta manera. Una vez que se
obtiene el identificador del método, se usa JNIEnv. CallStaticObjectMethod para invocar el método.
JNIEnv.CallStaticObjectMethod Devuelve un IntPtr que contiene el identificador de la instancia de Java devuelta.
Java. lang. Object. GetObject<T>(IntPtr, JniHandleOwnership) se usa para convertir el identificador de Java en
una instancia de objeto fuertemente tipado.
Enlace de método de instancia no virtual
Enlazar final un método de instancia o un método de instancia que no requiere invalidar, JNIEnv.GetMethodID
implica el uso de para obtener un identificador de método JNIEnv.Call*Method y, a continuación, utilizar el
método adecuado, dependiendo del tipo de valor devuelto del método. El siguiente es un ejemplo de un enlace
para la Object.Class propiedad:
static IntPtr id_getClass;
public Java.Lang.Class Class {
get {
if (id_getClass == IntPtr.Zero)
id_getClass = JNIEnv.GetMethodID (class_ref, "getClass", "()Ljava/lang/Class;");
return Java.Lang.Object.GetObject<Java.Lang.Class> (
JNIEnv.CallObjectMethod (Handle, id_getClass),
JniHandleOwnership.TransferLocalRef);
}
}

Tenga en cuenta que el identificador de método se almacena en un id_getClass campo estático,. Se trata de una
optimización del rendimiento, de modo que no es necesario buscar el identificador del método en cada
invocación. No es necesario almacenar en caché el identificador del método de esta manera. Una vez que se
obtiene el identificador del método, se usa JNIEnv. CallStaticObjectMethod para invocar el método.
JNIEnv.CallStaticObjectMethod Devuelve un IntPtr que contiene el identificador de la instancia de Java devuelta.
Java. lang. Object. GetObject<T>(IntPtr, JniHandleOwnership) se usa para convertir el identificador de Java en
una instancia de objeto fuertemente tipado.
Constructores de enlace
Los constructores son métodos de Java con "<init>" el nombre. Al igual que con los métodos de
JNIEnv.GetMethodID instancia de Java, se usa para buscar el identificador del constructor. A diferencia de los
métodos de Java, se usan los métodos JNIEnv. NewObject para invocar el identificador del método de
constructor. El valor devuelto JNIEnv.NewObject de es una referencia local de JNI:

int value = 42;


IntPtr class_ref = JNIEnv.FindClass ("java/lang/Integer");
IntPtr id_ctor_I = JNIEnv.GetMethodID (class_ref, "<init>", "(I)V");
IntPtr lrefInstance = JNIEnv.NewObject (class_ref, id_ctor_I, new JValue (value));
// Dispose of lrefInstance, class_ref…

Normalmente, un enlace de clase creará subclases java. lang. Object. Al subclases Java.Lang.Object , una
semántica adicional entra en juego: una Java.Lang.Object instancia mantiene una referencia global a una
instancia de Java a Java.Lang.Object.Handle través de la propiedad.
1. El Java.Lang.Object constructor predeterminado asignará una instancia de Java.
2. Si el tipo tiene un RegisterAttribute , y RegisterAttribute.DoNotGenerateAcw es true , se crea una
instancia del RegisterAttribute.Name tipo a través de su constructor predeterminado.
3. De lo contrario, se crea una instancia del contenedor de this.GetType Android al que se puede llamar
(ACW ) correspondiente a a través de su constructor predeterminado. Los contenedores a los que se puede
llamar de Android se Java.Lang.Object generan durante la creación RegisterAttribute.DoNotGenerateAcw
del paquete para cada true subclase para la que no se establece en.

En el caso de los tipos que no son enlaces de clase, esta es la semántica esperada: la creación de instancias de una
Mono.Samples.HelloWorld.HelloAndroid C# instancia debe construir una instancia de Java
mono.samples.helloworld.HelloAndroid que sea un contenedor de Android al que se puede llamar.

En el caso de los enlaces de clase, puede ser el comportamiento correcto si el tipo de Java contiene un
constructor predeterminado y/o no es necesario invocar ningún otro constructor. De lo contrario, se debe
proporcionar un constructor que realice las siguientes acciones:
1. Invocar java. lang. Object (IntPtr, JniHandleOwnership) en lugar del constructor predeterminado
Java.Lang.Object . Esto es necesario para evitar la creación de una nueva instancia de Java.
2. Compruebe el valor de java. lang. Object. Handle antes de crear cualquier instancia de Java. La
Object.Handle propiedad tendrá un valor distinto de IntPtr.Zero si se construyó un contenedor de
Android al que se puede llamar en código Java, y el enlace de clase se construye para que contenga la
instancia de contenedor de Android al que se puede llamar. Por ejemplo, cuando Android crea una
mono.samples.helloworld.HelloAndroid instancia, primero se creará el contenedor de Android Callable y el
HelloAndroid constructor de Java creará una instancia del Mono.Samples.HelloWorld.HelloAndroid tipo
correspondiente, con Object.Handle la propiedad establezca en la instancia de Java antes de la ejecución
del constructor.
3. Si el tipo en tiempo de ejecución actual no es el mismo que el tipo declarativo, se debe crear una instancia
del contenedor correspondiente de Android al que se puede llamar y usar Object. SetHandle para
almacenar el identificador devuelto por JNIEnv. CreateInstance.
4. Si el tipo en tiempo de ejecución actual es el mismo que el tipo declarativo, invoque el constructor de Java
y use Object. SetHandle para JNIEnv.NewInstance almacenar el identificador devuelto por.
Por ejemplo, considere el constructor java. lang. Integer (int) . Está enlazado como:

// Cache the constructor's method handle for later use


static IntPtr id_ctor_I;

// Need [Register] for subclassing


// RegisterAttribute.Name is always ".ctor"
// RegisterAttribute.Signature is tye JNI type signature of constructor
// RegisterAttribute.Connector is ignored; use ""
[Register (".ctor", "(I)V", "")]
public Integer (int value)
// 1. Prevent Object default constructor execution
: base (IntPtr.Zero, JniHandleOwnership.DoNotTransfer)
{
// 2. Don't allocate Java instance if already allocated
if (Handle != IntPtr.Zero)
return;

// 3. Derived type? Create Android Callable Wrapper


if (GetType () != typeof (Integer)) {
SetHandle (
Android.Runtime.JNIEnv.CreateInstance (GetType (), "(I)V", new JValue (value)),
JniHandleOwnership.TransferLocalRef);
return;
}

// 4. Declaring type: lookup &amp; cache method id...


if (id_ctor_I == IntPtr.Zero)
id_ctor_I = JNIEnv.GetMethodID (class_ref, "<init>", "(I)V");
// ...then create the Java instance and store
SetHandle (
JNIEnv.NewObject (class_ref, id_ctor_I, new JValue (value)),
JniHandleOwnership.TransferLocalRef);
}

Los métodos JNIEnv. CreateInstance son JNIEnv.FindClass auxiliares para realizar, JNIEnv.GetMethodID ,
JNIEnv.NewObject y JNIEnv.DeleteGlobalReference en el valor devuelto de JNIEnv.FindClass . Para obtener más
información, vea la siguiente sección.
Compatibilidad de herencia, interfaces
La creación de subclases de un tipo de Java o la implementación de una interfaz de Java requiere la generación
de contenedores de Android Callable (ACWs) que se generan para cada Java.Lang.Object subclase durante el
proceso de empaquetado. La generación de ACW se controla mediante el atributo personalizado Android.
Runtime. RegisterAttribute .
En C# el caso de [Register] los tipos, el constructor de atributos personalizados requiere un argumento: la
referencia de tipo simplificado de JNI para el tipo de Java correspondiente. Esto permite proporcionar nombres
diferentes entre Java y C#.
Antes de Xamarin. Android 4,0, el [Register] atributo personalizado no estaba disponible para "alias" tipos de
Java existentes. Esto se debe a que el proceso de generación de ACW generaría ACWs para cada
Java.Lang.Object subclase encontrada.

Xamarin. Android 4,0 presentó la propiedad RegisterAttribute. DoNotGenerateAcw . Esta propiedad indica al
proceso de generación de ACW que omita el tipo anotado, lo que permite la declaración de nuevos contenedores
a los que se puede llamar administrados que no producirán la generación de ACWs en el momento de la
creación del paquete. Esto permite enlazar tipos de Java existentes. Por ejemplo, considere la siguiente clase
simple de Java Adder ,, que contiene un método add ,, que se agrega a los enteros y devuelve el resultado:

package mono.android.test;
public class Adder {
public int add (int a, int b) {
return a + b;
}
}

El Adder tipo se puede enlazar como:

[Register ("mono/android/test/Adder", DoNotGenerateAcw=true)]


public partial class Adder : Java.Lang.Object {
static IntPtr class_ref = JNIEnv.FindClass ( "mono/android/test/Adder");

public Adder ()
{
}

public Adder (IntPtr handle, JniHandleOwnership transfer)


: base (handle, transfer)
{
}
}
partial class ManagedAdder : Adder {
}

Aquí, el Adder C# tipo escribe el alias Adder del tipo de Java. El [Register] atributo se usa para especificar el
nombre mono.android.test.Adder de JNI del tipo Java y la DoNotGenerateAcw propiedad se usa para impedir la
generación de ACW. Esto producirá la generación de un ACW para el ManagedAdder tipo, que crea correctamente
subclases del mono.android.test.Adder tipo. Si no RegisterAttribute.DoNotGenerateAcw se hubiera usado la
propiedad, el proceso de compilación de Xamarin. Android habría generado un mono.android.test.Adder nuevo
tipo de Java. Esto produciría errores de compilación, ya que mono.android.test.Adder el tipo se presentaría dos
veces, en dos archivos independientes.
Enlazar métodos virtuales
ManagedAdder subclases del tipo Adder de Java, pero no es especialmente interesante: C# Adder el tipo no define
ningún método virtual, ManagedAdder por lo que no puede invalidar nada.
Los virtual métodos de enlace para permitir el reemplazo por subclases requieren varias cosas que deben
realizarse y que se encuentran en las dos categorías siguientes:
1. Enlace de método
2. Registro de métodos
Enlace de método
Un enlace de método requiere la adición de dos miembros de soporte C# Adder a la ThresholdType definición:
ThresholdClass , y.

T h r e sh o l d T y p e

La ThresholdType propiedad devuelve el tipo actual del enlace:

partial class Adder {


protected override System.Type ThresholdType {
get {
return typeof (Adder);
}
}
}

ThresholdType se utiliza en el enlace de método para determinar cuándo debe realizarse la distribución de
métodos virtuales y no virtuales. Siempre debe devolver una System.Type instancia de que se corresponda con
el C# tipo declarativo.
T h r e sh o l d C l a ss

La ThresholdClass propiedad devuelve la referencia de clase JNI para el tipo enlazado:

partial class Adder {


protected override IntPtr ThresholdClass {
get {
return class_ref;
}
}
}

ThresholdClass se utiliza en el enlace de método al invocar métodos no virtuales.


Implementación de enlace
La implementación de enlace de método es responsable de la invocación en tiempo de ejecución del método
Java. También contiene una [Register] declaración de atributo personalizado que forma parte del registro del
método y se explicará en la sección registro del método:

[Register ("add", "(II)I", "GetAddHandler")]


public virtual int Add (int a, int b)
{
if (id_add == IntPtr.Zero)
id_add = JNIEnv.GetMethodID (class_ref, "add", "(II)I");
if (GetType () == ThresholdType)
return JNIEnv.CallIntMethod (Handle, id_add, new JValue (a), new JValue (b));
return JNIEnv.CallNonvirtualIntMethod (Handle, ThresholdClass, id_add, new JValue (a), new JValue
(b));
}
}

El id_add campo contiene el identificador de método para el método Java que se va a invocar. El id_add valor
se obtiene de JNIEnv.GetMethodID , que requiere la clase declarativa class_ref (), el nombre del método "add"
Java () y la firma JNI del método ( "(II)I" ).
Una vez que se obtiene el identificador GetType de método, ThresholdType se compara con para determinar si
se requiere un envío virtual o no virtual. El envío virtual es necesario GetType cuando ThresholdType coincide,
Handle ya que puede hacer referencia a una subclase asignada por Java que invalida el método.

Cuando GetType no coincide ThresholdType ManagedAdder , Adder se ha subclase (por ejemplo, por) y la
Adder.Add implementación solo se invocará si la subclase se invoca base.Add . Este es el caso de envío no virtual,
que es donde ThresholdClass entra. ThresholdClass Especifica qué clase Java proporcionará la implementación
del método que se va a invocar.
Registro de métodos
Supongamos que tenemos ManagedAdder una definición actualizada que invalida el Adder.Add método:

partial class ManagedAdder : Adder {


public override int Add (int a, int b) {
return (a*2) + (b*2);
}
}

Recuerde que Adder.Add tenía un [Register] atributo personalizado:

[Register ("add", "(II)I", "GetAddHandler")]

El [Register] constructor de atributos personalizados acepta tres valores:


1. Nombre del método Java, "add" en este caso.
2. Firma de tipo JNI del método, "(II)I" en este caso.
3. El método de conector GetAddHandler , en este caso. Los métodos de conector se tratarán más adelante.
Los dos primeros parámetros permiten que el proceso de generación de ACW genere una declaración de
método para invalidar el método. El ACW resultante contendría parte del código siguiente:

public class ManagedAdder extends mono.android.test.Adder {


static final String __md_methods;
static {
__md_methods = "n_add:(II)I:GetAddHandler\n" +
"";
mono.android.Runtime.register (...);
}
@Override
public int add (int p0, int p1) {
return n_add (p0, p1);
}
private native int n_add (int p0, int p1);
// ...
}

Tenga en cuenta @Override que se declara un método, que delega n_ en un método de prefijo con el mismo
nombre. Esto garantiza que ManagedAdder.add cuando se invoque el código Java, ManagedAdder.n_add se invocará,
lo que permitirá que se C# ManagedAdder.Add ejecute el método de reemplazo.
Por lo tanto, la pregunta más importante: ManagedAdder.n_add ¿cómo se enlaza ManagedAdder.Add ?
Los native métodos de Java se registran con el tiempo de ejecución de Java (Android Runtime) a través de la
función RegisterNatives de JNI. RegisterNatives toma una matriz de estructuras que contienen el nombre del
método Java, la firma del tipo JNI y un puntero de función que se va a invocar después de la Convención de
llamada de JNI. El puntero de función debe ser una función que toma dos argumentos de puntero seguidos de
los parámetros de método. El método ManagedAdder.n_add Java debe implementarse a través de una función que
tenga el siguiente prototipo de C:
int FunctionName(JNIEnv *env, jobject this, int a, int b)

Xamarin. Android no expone un RegisterNatives método. En su lugar, ACW y MCW proporcionan la


información necesaria para invocar RegisterNatives : ACW contiene el nombre del método y la firma del tipo
JNI, lo único que falta es un puntero de función que se va a enlazar.
Aquí es donde entra en el método del conector . El tercer [Register] parámetro de atributo personalizado es el
nombre de un método definido en el tipo registrado o una clase base del tipo registrado que no acepta
parámetros y devuelve un System.Delegate . El devuelto System.Delegate a su vez hace referencia a un método
que tiene la firma de la función JNI correcta. Por último, el delegado que devuelve el método del conector debe
tener la raíz para que el GC no lo recopile, ya que el delegado se proporciona a Java.

#pragma warning disable 0169


static Delegate cb_add;
// This method must match the third parameter of the [Register]
// custom attribute, must be static, must return System.Delegate,
// and must accept no parameters.
static Delegate GetAddHandler ()
{
if (cb_add == null)
cb_add = JNINativeWrapper.CreateDelegate ((Func<IntPtr, IntPtr, int, int, int>) n_Add);
return cb_add;
}
// This method is registered with JNI.
static int n_Add (IntPtr jnienv, IntPtr lrefThis, int a, int b)
{
Adder __this = Java.Lang.Object.GetObject<Adder>(lrefThis, JniHandleOwnership.DoNotTransfer);
return __this.Add (a, b);
}
#pragma warning restore 0169

El GetAddHandler método crea un Func<IntPtr, IntPtr, int, int, int> n_Add delegado que hace referencia al
método y, a continuación, invoca JNINativeWrapper. CreateDelegate. JNINativeWrapper.CreateDelegate ajusta el
método proporcionado en un bloque try/catch, de modo que se controlen las excepciones no controladas y
provocarán que se genere el evento AndroidEvent. UnhandledExceptionRaiser . El delegado resultante se
almacena en la variable cb_add estática para que el GC no libere el delegado.
Por último, n_Add el método es responsable de calcular las referencias de los parámetros de JNI en los tipos
administrados correspondientes y, a continuación, delegar la llamada al método.
Nota: Use JniHandleOwnership.DoNotTransfer siempre al obtener un MCW en una instancia de Java. Si se tratan
como una referencia local (y, JNIEnv.DeleteLocalRef por lo tanto, llamando> a)> , se interrumpirán las
transiciones de pila administradas por Java.
Completar enlace de agregador
El enlace administrado completo para el mono.android.tests.Adder tipo es:
[Register ("mono/android/test/Adder", DoNotGenerateAcw=true)]
public class Adder : Java.Lang.Object {

static IntPtr class_ref = JNIEnv.FindClass ("mono/android/test/Adder");

public Adder ()
{
}

public Adder (IntPtr handle, JniHandleOwnership transfer)


: base (handle, transfer)
{
}

protected override Type ThresholdType {


get {return typeof (Adder);}
}

protected override IntPtr ThresholdClass {


get {return class_ref;}
}

#region Add
static IntPtr id_add;

[Register ("add", "(II)I", "GetAddHandler")]


public virtual int Add (int a, int b)
{
if (id_add == IntPtr.Zero)
id_add = JNIEnv.GetMethodID (class_ref, "add", "(II)I");
if (GetType () == ThresholdType)
return JNIEnv.CallIntMethod (Handle, id_add, new JValue (a), new JValue (b));
return JNIEnv.CallNonvirtualIntMethod (Handle, ThresholdClass, id_add, new JValue (a), new JValue
(b));
}

#pragma warning disable 0169


static Delegate cb_add;
static Delegate GetAddHandler ()
{
if (cb_add == null)
cb_add = JNINativeWrapper.CreateDelegate ((Func<IntPtr, IntPtr, int, int, int>) n_Add);
return cb_add;
}

static int n_Add (IntPtr jnienv, IntPtr lrefThis, int a, int b)


{
Adder __this = Java.Lang.Object.GetObject<Adder>(lrefThis, JniHandleOwnership.DoNotTransfer);
return __this.Add (a, b);
}
#pragma warning restore 0169
#endregion
}

Restricciones
Al escribir un tipo que coincida con los criterios siguientes:
1. Subclases Java.Lang.Object

2. Tiene un [Register] atributo personalizado


3. RegisterAttribute.DoNotGenerateAcw es true

A continuación, para la interacción con GC, el tipo no debe tener ningún campo Java.Lang.Object que
Java.Lang.Object pueda hacer referencia a una subclase o en tiempo de ejecución. Por ejemplo, no se permiten
System.Object los campos de tipo y cualquier tipo de interfaz. Se permiten los tipos que Java.Lang.Object no
pueden hacer referencia a las System.String instancias List<int> de, como y. Esta restricción es impedir la
recolección de objetos prematura por parte del GC.
Si el tipo debe contener un campo de instancia que pueda hacer referencia Java.Lang.Object a una instancia de,
el tipo de System.WeakReference campo GCHandle debe ser o.

Enlazar métodos abstractos


Los abstract métodos de enlace son en gran medida idénticos a los métodos virtuales de enlace. Solo hay dos
diferencias:
1. El método abstracto es abstracto. Todavía conserva el [Register] atributo y el registro del método
asociado, el enlace de método simplemente se mueve Invoker al tipo.
2. Se crea un abstract sin Invoker tipo que subclase el tipo abstracto. El Invoker tipo debe reemplazar
todos los métodos abstractos declarados en la clase base y la implementación reemplazada es la
implementación de enlace de método, aunque el caso de envío no virtual se puede omitir.
Por ejemplo, supongamos que mono.android.test.Adder.add el método abstract anterior era. El C# enlace
cambiaría para que Adder.Add fuese abstracto y se definiría un nuevo AdderInvoker tipo que implementaba
Adder.Add :

partial class Adder {


[Register ("add", "(II)I", "GetAddHandler")]
public abstract int Add (int a, int b);

// The Method Registration machinery is identical to the


// virtual method case...
}

partial class AdderInvoker : Adder {


public AdderInvoker (IntPtr handle, JniHandleOwnership transfer)
: base (handle, transfer)
{
}

static IntPtr id_add;


public override int Add (int a, int b)
{
if (id_add == IntPtr.Zero)
id_add = JNIEnv.GetMethodID (class_ref, "add", "(II)I");
return JNIEnv.CallIntMethod (Handle, id_add, new JValue (a), new JValue (b));
}
}

El Invoker tipo solo es necesario cuando se obtienen referencias JNI a instancias creadas por Java.

Interfaces de enlace
Las interfaces de enlace son conceptualmente similares a las clases de enlace que contienen métodos virtuales,
pero muchos de los aspectos específicos difieren en modo sutil (y no tan sutil). Considere la siguiente declaración
de interfaz de Java:

public interface Progress {


void onAdd(int[] values, int currentIndex, int currentSum);
}
Los enlaces de interfaz tienen dos partes: C# la definición de interfaz y una definición de invocador para la
interfaz.
Definición de interfaz
La C# definición de la interfaz debe cumplir los siguientes requisitos:
La definición de interfaz debe tener [Register] un atributo personalizado.
La definición de interfaz debe extender IJavaObject interface el. Si no lo hace, impedirá que ACWs
herede de la interfaz java.
Cada método de interfaz debe contener [Register] un atributo que especifique el nombre del método
Java, la firma de JNI y el método de conector correspondientes.
El método de conector también debe especificar el tipo en el que se puede ubicar el método de conector.
Al abstract enlazar virtual y métodos, se buscaría el método de conector dentro de la jerarquía de herencia
del tipo que se va a registrar. Las interfaces no pueden tener ningún método que contenga cuerpos, por lo que
esto no funciona, por lo que es necesario especificar un tipo que indique dónde se encuentra el método de
conector. El tipo se especifica dentro de la cadena de método de conector, ':' después de dos puntos, y debe ser
el nombre de tipo calificado con el ensamblado del tipo que contiene el invocador.
Las declaraciones de método de interfaz son una traducción del método de Java correspondiente usando tipos
compatibles . En el caso de los tipos integrados de Java, los tipos C# compatibles son los tipos correspondientes
int , C# int por ejemplo, Java es. En el caso de los tipos de referencia, el tipo compatible es un tipo que puede
proporcionar un identificador de JNI del tipo Java adecuado.
Los miembros de interfaz no se invocarán directamente mediante la – invocación de Java se medirán a través del
– tipo de invocador, por lo que se permite cierto grado de flexibilidad.
La interfaz de progreso de Java se puede declarar en de C# la siguiente manera:

[Register ("mono/android/test/Adder$Progress", DoNotGenerateAcw=true)]


public interface IAdderProgress : IJavaObject {
[Register ("onAdd", "([III)V",
"GetOnAddHandler:Mono.Samples.SanityTests.IAdderProgressInvoker, SanityTests, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null")]
void OnAdd (JavaArray<int> values, int currentIndex, int currentSum);
}

Observe en lo anterior que asignamos el parámetro int[] de Java a un<JavaArray>int. Esto no es necesario:
podríamos haber enlazado a un C# int[] , o a IList<int> un, o a algo más completo. Sea cual sea el tipo elegido
Invoker , el debe ser capaz de traducirlo a un int[] tipo de Java para la invocación.

Definición de invocador
La Invoker definición de tipo debe Java.Lang.Object heredar, implementar la interfaz adecuada y proporcionar
todos los métodos de conexión a los que se hace referencia en la definición de interfaz. Hay una sugerencia más
que difiere de un enlace de clase: los class_ref identificadores de campo y de método deben ser miembros de
instancia, no miembros estáticos.
La razón para la preferencia de miembros de instancia tiene JNIEnv.GetMethodID que hacer con el
comportamiento en el tiempo de ejecución de Android. (Esto también puede ser un comportamiento de Java; no
se ha probado). JNIEnv.GetMethodID devuelve null al buscar un método que proviene de una interfaz
implementada y no de la interfaz declarada. Considere la interfaz Java . util.<SortedMap k,> v Java, que
implementa la interfaz java. util. map<k, v> . Map proporciona un método Clear , por lo que una definición
Invoker aparentemente razonable para SortedMap sería:
// Fails at runtime. DO NOT FOLLOW
partial class ISortedMapInvoker : Java.Lang.Object, ISortedMap {
static IntPtr class_ref = JNIEnv.FindClass ("java/util/SortedMap");
static IntPtr id_clear;
public void Clear()
{
if (id_clear == IntPtr.Zero)
id_clear = JNIEnv.GetMethodID(class_ref, "clear", "()V");
JNIEnv.CallVoidMethod(Handle, id_clear);
}
// ...
}

Lo anterior producirá un JNIEnv.GetMethodID error porque null devolverá cuando Map.clear se busque el
SortedMap método a través de la instancia de clase.

Existen dos soluciones: realizar un seguimiento de la interfaz de la que procede cada método y tener class_ref
un para cada interfaz, o bien mantener todo como miembros de instancia y realizar la búsqueda de métodos en el
tipo de clase más derivado, no en el tipo de interfaz. Esto último se hace en mono. Android. dll.
La definición del Invocador tiene seis secciones: el constructor Dispose , el método ThresholdType ,
ThresholdClass los miembros y GetObject , el método, la implementación del método de interfaz y la
implementación del método de conector.
Constructor
El constructor necesita buscar la clase en tiempo de ejecución de la instancia que se está invocando y almacenar
la clase class_ref en tiempo de ejecución en el campo de instancia:

partial class IAdderProgressInvoker {


IntPtr class_ref;
public IAdderProgressInvoker (IntPtr handle, JniHandleOwnership transfer)
: base (handle, transfer)
{
IntPtr lref = JNIEnv.GetObjectClass (Handle);
class_ref = JNIEnv.NewGlobalRef (lref);
JNIEnv.DeleteLocalRef (lref);
}
}

Nota: La Handle propiedad se debe usar en el cuerpo del constructor y no en handle el parámetro, como en
Android v 4.0 handle , el parámetro puede no ser válido después de que el constructor base termine de
ejecutarse.
Dispose (Método)
El Dispose método debe liberar la referencia global asignada en el constructor:

partial class IAdderProgressInvoker {


protected override void Dispose (bool disposing)
{
if (this.class_ref != IntPtr.Zero)
JNIEnv.DeleteGlobalRef (this.class_ref);
this.class_ref = IntPtr.Zero;
base.Dispose (disposing);
}
}

ThresholdType y ThresholdClass
Los ThresholdType miembros ThresholdClass y son idénticos a lo que se encuentra en un enlace de clase:
partial class IAdderProgressInvoker {
protected override Type ThresholdType {
get {
return typeof (IAdderProgressInvoker);
}
}
protected override IntPtr ThresholdClass {
get {
return class_ref;
}
}
}

GetObject (Método)
Se requiere GetObject un método estático para admitir extensions.<JavaCast>T ():

partial class IAdderProgressInvoker {


public static IAdderProgress GetObject (IntPtr handle, JniHandleOwnership transfer)
{
return new IAdderProgressInvoker (handle, transfer);
}
}

Métodos de interfaz
Cada método de la interfaz debe tener una implementación de, que invoca el método Java correspondiente a
través de JNI:

partial class IAdderProgressInvoker {


IntPtr id_onAdd;
public void OnAdd (JavaArray<int> values, int currentIndex, int currentSum)
{
if (id_onAdd == IntPtr.Zero)
id_onAdd = JNIEnv.GetMethodID (class_ref, "onAdd", "([III)V");
JNIEnv.CallVoidMethod (Handle, id_onAdd, new JValue (JNIEnv.ToJniHandle (values)), new JValue
(currentIndex), new JValue (currentSum));
}
}

Métodos del conector


Los métodos de conector y la infraestructura de apoyo son responsables de calcular las referencias de C# los
parámetros de JNI en los tipos adecuados. El parámetro int[] de Java se pasará como JNI jintArray , que es
un IntPtr dentro de C#. Se IntPtr deben calcular las referencias de JavaArray<int> para poder invocar la C#
interfaz:
partial class IAdderProgressInvoker {
static Delegate cb_onAdd;
static Delegate GetOnAddHandler ()
{
if (cb_onAdd == null)
cb_onAdd = JNINativeWrapper.CreateDelegate ((Action<IntPtr, IntPtr, IntPtr, int, int>) n_OnAdd);
return cb_onAdd;
}

static void n_OnAdd (IntPtr jnienv, IntPtr lrefThis, IntPtr values, int currentIndex, int currentSum)
{
IAdderProgress __this = Java.Lang.Object.GetObject<IAdderProgress>(lrefThis,
JniHandleOwnership.DoNotTransfer);
using (var _values = new JavaArray<int>(values, JniHandleOwnership.DoNotTransfer)) {
__this.OnAdd (_values, currentIndex, currentSum);
}
}
}

Si int[] fuera JavaList<int> preferible, se podría usar JNIEnv. GetArray () :

int[] _values = (int[]) JNIEnv.GetArray(values, JniHandleOwnership.DoNotTransfer, typeof (int));

Sin embargo, tenga en JNIEnv.GetArray cuenta que copia toda la matriz entre las máquinas virtuales, por lo que
en el caso de las matrices grandes, esto podría dar lugar a una gran cantidad de presión de GC agregada.
Definición completa del Invocador
La definición de IAdderProgressInvoker completa:
class IAdderProgressInvoker : Java.Lang.Object, IAdderProgress {

IntPtr class_ref;

public IAdderProgressInvoker (IntPtr handle, JniHandleOwnership transfer)


: base (handle, transfer)
{
IntPtr lref = JNIEnv.GetObjectClass (Handle);
class_ref = JNIEnv.NewGlobalRef (lref);
JNIEnv.DeleteLocalRef (lref);
}

protected override void Dispose (bool disposing)


{
if (this.class_ref != IntPtr.Zero)
JNIEnv.DeleteGlobalRef (this.class_ref);
this.class_ref = IntPtr.Zero;
base.Dispose (disposing);
}

protected override Type ThresholdType {


get {return typeof (IAdderProgressInvoker);}
}

protected override IntPtr ThresholdClass {


get {return class_ref;}
}

public static IAdderProgress GetObject (IntPtr handle, JniHandleOwnership transfer)


{
return new IAdderProgressInvoker (handle, transfer);
}

#region OnAdd
IntPtr id_onAdd;
public void OnAdd (JavaArray<int> values, int currentIndex, int currentSum)
{
if (id_onAdd == IntPtr.Zero)
id_onAdd = JNIEnv.GetMethodID (class_ref, "onAdd",
"([III)V");
JNIEnv.CallVoidMethod (Handle, id_onAdd,
new JValue (JNIEnv.ToJniHandle (values)),
new JValue (currentIndex),
new JValue (currentSum));
}

#pragma warning disable 0169


static Delegate cb_onAdd;
static Delegate GetOnAddHandler ()
{
if (cb_onAdd == null)
cb_onAdd = JNINativeWrapper.CreateDelegate ((Action<IntPtr, IntPtr, IntPtr, int, int>) n_OnAdd);
return cb_onAdd;
}

static void n_OnAdd (IntPtr jnienv, IntPtr lrefThis, IntPtr values, int currentIndex, int currentSum)
{
IAdderProgress __this = Java.Lang.Object.GetObject<IAdderProgress>(lrefThis,
JniHandleOwnership.DoNotTransfer);
using (var _values = new JavaArray<int>(values, JniHandleOwnership.DoNotTransfer)) {
__this.OnAdd (_values, currentIndex, currentSum);
}
}
#pragma warning restore 0169
#endregion
}
Referencias del objeto JNI
Muchos métodos JNIEnv devuelven referencias a objetos JNI , que GCHandle son similares a s. JNI proporciona
tres tipos diferentes de referencias de objeto: referencias locales, referencias globales y referencias globales
débiles. Los tres se representan como System.IntPtr , pero (según la sección tipos de función JNI) no todos
IntPtr los que se JNIEnv devuelven desde los métodos son referencias. Por ejemplo, JNIEnv. GetMethodID
devuelve IntPtr , pero no devuelve una referencia jmethodID de objeto. Consulte la documentación de la función
JNI para obtener más información.
La mayoría de los métodos de creación de referencias crean las referencias locales. Android solo permite que
exista un número limitado de referencias locales en un momento dado, normalmente 512. Las referencias locales
se pueden eliminar a través de JNIEnv. DeleteLocalRef. A diferencia de JNI, no todos los métodos JNIEnv de
referencia que devuelven referencias a objetos devuelven referencias locales. JNIEnv. FindClass devuelve una
referencia global . Se recomienda encarecidamente que elimine las referencias locales tan pronto como pueda,
mediante la construcción de un objeto Java. lang. Object alrededor del objeto y la
JniHandleOwnership.TransferLocalRef especificación de java. lang. Object (identificador IntPtr, transferencia
JniHandleOwnership) constructor.
Las referencias globales se crean mediante JNIEnv. NewGlobalRef y JNIEnv. FindClass. Se pueden destruir con
JNIEnv. DeleteGlobalRef. Los emuladores tienen un límite de 2.000 referencias globales pendientes, mientras
que los dispositivos de hardware tienen un límite de aproximadamente 52.000 referencias globales.
Las referencias globales débiles solo están disponibles en Android v 2.2 (Froyo) y versiones posteriores. Las
referencias globales débiles se pueden eliminar con JNIEnv. DeleteWeakGlobalRef.
Trabajar con referencias locales de JNI
Los métodos JNIEnv. GetObjectField, JNIEnv. GetStaticObjectField, JNIEnv. CallObjectMethod, JNIEnv.
CallNonvirtualObjectMethod y JNIEnv. CallStaticObjectMethod devuelven un IntPtr valor contiene una
referencia local de JNI a un objeto de Java IntPtr.Zero o si se null devuelve Java. Debido al número limitado
de referencias locales que pueden estar pendientes a la vez (entradas 512), es conveniente asegurarse de que las
referencias se eliminan a tiempo. Hay tres maneras de tratar las referencias locales: eliminarlas explícitamente,
crear una Java.Lang.Object instancia de para contenerlos y usar Java.Lang.Object.GetObject<T>() para crear un
contenedor administrado al que se puede llamar.
Eliminar explícitamente las referencias locales
JNIEnv. DeleteLocalRef se usa para eliminar referencias locales. Una vez eliminada la referencia local, ya no se
puede usar, por lo que se debe tener cuidado para JNIEnv.DeleteLocalRef asegurarse de que es lo último que se
ha hecho con la referencia local.

IntPtr lref = JNIEnv.CallObjectMethod(instance, methodID);


try {
// Do something with `lref`
}
finally {
JNIEnv.DeleteLocalRef (lref);
}

Ajuste con Java. lang. Object


Java.Lang.Object proporciona un constructor java. lang. Object (identificador IntPtr, JniHandleOwnership
Transfer) que se puede usar para ajustar una referencia JNI de salida. El parámetro JniHandleOwnership
determina cómo se IntPtr debe tratar el parámetro:
JniHandleOwnership. DoNotTransfer – la instancia Java.Lang.Object creada creará una nueva referencia
global desde el handle parámetro y handle no se modificará. El autor de la llamada es responsable de
handle liberar, si es necesario.
JniHandleOwnership. TransferLocalRef – la instancia Java.Lang.Object creada creará una nueva referencia
global desde el handle parámetro y handle se eliminará con JNIEnv. DeleteLocalRef . El autor de la
llamada no handle debe liberar y no debe handle usar una vez que el constructor termine de ejecutarse.
JniHandleOwnership. TransferGlobalRef – Java.Lang.Object la handle instancia creada tomará la
propiedad del parámetro. El autor de la llamada no handle debe liberar.
Dado que los métodos de invocación del método JNI devuelven referencias locales,
JniHandleOwnership.TransferLocalRef se utilizaría normalmente:

IntPtr lref = JNIEnv.CallObjectMethod(instance, methodID);


var value = new Java.Lang.Object (lref, JniHandleOwnership.TransferLocalRef);

La referencia global creada no se liberará hasta que la Java.Lang.Object instancia se recopile como elemento no
utilizado. Si es posible, la eliminación de la instancia liberará la referencia global, con lo que se aceleran las
recolecciones de elementos no utilizados:

IntPtr lref = JNIEnv.CallObjectMethod(instance, methodID);


using (var value = new Java.Lang.Object (lref, JniHandleOwnership.TransferLocalRef)) {
// use value ...
}

Usar Java. lang. Object. GetObject<T>()


Java.Lang.Object proporciona un método java. lang. Object.<GetObject>T (identificador IntPtr,
JniHandleOwnership Transfer) que se puede usar para crear un contenedor invocable administrado del tipo
especificado.
El tipo T debe cumplir los siguientes requisitos:
1. T debe ser un tipo de referencia.
2. T debe implementar la IJavaObject interfaz.
3. Si no es una clase o interfaz abstracta T , debe proporcionar un constructor con los tipos
T
(IntPtr, JniHandleOwnership) de parámetro.

4. Si T es una clase abstracta o una interfaz, debe haber un invocador disponible para T . Un invocador es
un tipo no abstracto que hereda T o T implementa, y tiene el mismo nombre que T con un sufijo de
invocador. Por ejemplo, si T es la interfaz Java.Lang.IRunnable , el tipo Java.Lang.IRunnableInvoker debe
existir y debe contener el constructor necesario (IntPtr, JniHandleOwnership) .
Dado que los métodos de invocación del método JNI devuelven referencias locales,
JniHandleOwnership.TransferLocalRef se utilizaría normalmente:

IntPtr lrefString = JNIEnv.CallObjectMethod(instance, methodID);


Java.Lang.String value = Java.Lang.Object.GetObject<Java.Lang.String>( lrefString,
JniHandleOwnership.TransferLocalRef);

Buscar tipos de Java


Para buscar un campo o método en JNI, primero debe buscar el tipo declarativo del campo o método. El método
Android. Runtime. JNIEnv. FindClass (String)) se usa para buscar tipos de Java. El parámetro String es la
referencia de tipo simplificado o la referencia de tipo completo para el tipo Java. Vea la sección referencias de
tipos de JNI para obtener más información sobre las referencias de tipos completos y simplificados.
Nota: A diferencia de todos JNIEnv los demás métodos que devuelven instancias de objeto, FindClass devuelve
una referencia global, no una referencia local.

Campos de instancia
Los campos se manipulan a través de los identificadores de campo. Los identificadores de campo se obtienen a
través de JNIEnv. GetFieldID, que requiere la clase en la que está definido el campo, el nombre del campo y la
firma de tipo JNI del campo.
No es necesario liberar los identificadores de campo y son válidos siempre que se cargue el tipo de Java
correspondiente. (Android no admite actualmente la descarga de clases).
Existen dos conjuntos de métodos para manipular campos de instancia: uno para leer campos de instancia y otro
para escribir campos de instancia. Todos los conjuntos de métodos requieren un identificador de campo para leer
o escribir el valor del campo.
Leer valores de campo de instancia
El conjunto de métodos para leer valores de campo de instancia sigue el patrón de nomenclatura:

* JNIEnv.Get*Field(IntPtr instance, IntPtr fieldID);

donde * es el tipo del campo:


JNIEnv. GetObjectField – lee el valor de cualquier campo de instancia que no sea un java.lang.Object
tipo integrado, como, por ejemplo, matrices y tipos de interfaz. El valor devuelto es una referencia local de
JNI.
JNIEnv. GetBooleanField – lee el valor de bool los campos de instancia.
JNIEnv. GetByteField – lee el valor de sbyte los campos de instancia.
JNIEnv. GetCharField – lee el valor de char los campos de instancia.
JNIEnv. GetShortField – lee el valor de short los campos de instancia.
JNIEnv. GetIntField – lee el valor de int los campos de instancia.
JNIEnv. GetLongField – lee el valor de long los campos de instancia.
JNIEnv. GetFloatField – lee el valor de float los campos de instancia.
JNIEnv. GetDoubleField – lee el valor de double los campos de instancia.
Escribir valores de campo de instancia
El conjunto de métodos para escribir valores de campo de instancia sigue el patrón de nomenclatura:

JNIEnv.SetField(IntPtr instance, IntPtr fieldID, Type value);

donde Type es el tipo del campo:


JNIEnv. SetField) – escriba el valor de cualquier campo que no sea un java.lang.Object tipo integrado,
como, por ejemplo, matrices y tipos de interfaz. El IntPtr valor puede ser una referencia local de JNI, una
referencia global de JNI, una referencia global IntPtr.Zero no segura null de JNI o (para).
JNIEnv. SetField) – escriba el valor de bool los campos de instancia.
JNIEnv. SetField) – escriba el valor de sbyte los campos de instancia.
JNIEnv. SetField) – escriba el valor de char los campos de instancia.
JNIEnv. SetField) – escriba el valor de short los campos de instancia.
JNIEnv. SetField) – escriba el valor de int los campos de instancia.
JNIEnv. SetField) – escriba el valor de long los campos de instancia.
JNIEnv. SetField) – escriba el valor de float los campos de instancia.
JNIEnv. SetField) – escriba el valor de double los campos de instancia.

Campos estáticos
Los campos estáticos se manipulan a través de los identificadores de campo. Los identificadores de campo se
obtienen a través de JNIEnv. GetStaticFieldID, que requiere la clase en la que está definido el campo, el nombre
del campo y la firma de tipo JNI del campo.
No es necesario liberar los identificadores de campo y son válidos siempre que se cargue el tipo de Java
correspondiente. (Android no admite actualmente la descarga de clases).
Existen dos conjuntos de métodos para manipular campos estáticos: uno para leer campos de instancia y otro
para escribir campos de instancia. Todos los conjuntos de métodos requieren un identificador de campo para leer
o escribir el valor del campo.
Leer valores de campos estáticos
El conjunto de métodos para leer valores de campos estáticos sigue el patrón de nomenclatura:

* JNIEnv.GetStatic*Field(IntPtr class, IntPtr fieldID);

donde * es el tipo del campo:


JNIEnv. GetStaticObjectField – lee el valor de cualquier campo estático que no sea un java.lang.Object
tipo integrado, como, por ejemplo, matrices y tipos de interfaz. El valor devuelto es una referencia local de
JNI.
JNIEnv. GetStaticBooleanField – lee el valor de bool los campos estáticos.
JNIEnv. GetStaticByteField – lee el valor de sbyte los campos estáticos.
JNIEnv. GetStaticCharField – lee el valor de char los campos estáticos.
JNIEnv. GetStaticShortField – lee el valor de short los campos estáticos.
JNIEnv. GetStaticLongField – lee el valor de long los campos estáticos.
JNIEnv. GetStaticFloatField – lee el valor de float los campos estáticos.
JNIEnv. GetStaticDoubleField – lee el valor de double los campos estáticos.
Escribir valores de campo estáticos
El conjunto de métodos para escribir valores de campo estático sigue el patrón de nomenclatura:

JNIEnv.SetStaticField(IntPtr class, IntPtr fieldID, Type value);

donde Type es el tipo del campo:


JNIEnv. SetStaticField) – escriba el valor de cualquier campo estático que no sea un java.lang.Object tipo
integrado, como, por ejemplo, matrices y tipos de interfaz. El IntPtr valor puede ser una referencia local
de JNI, una referencia global de JNI, una referencia global IntPtr.Zero no segura null de JNI o (para).
JNIEnv. SetStaticField) – escriba el valor de bool los campos estáticos.
JNIEnv. SetStaticField) – escriba el valor de sbyte los campos estáticos.
JNIEnv. SetStaticField) – escriba el valor de char los campos estáticos.
JNIEnv. SetStaticField) – escriba el valor de short los campos estáticos.
JNIEnv. SetStaticField) – escriba el valor de int los campos estáticos.
JNIEnv. SetStaticField) – escriba el valor de long los campos estáticos.
JNIEnv. SetStaticField) – escriba el valor de float los campos estáticos.
JNIEnv. SetStaticField) – escriba el valor de double los campos estáticos.

Métodos de instancia
Los métodos de instancia se invocan a través de los identificadores de método. Los identificadores de método se
obtienen a través de JNIEnv. GetMethodID, que requiere el tipo en el que se define el método, el nombre del
método y la firma de tipo JNI del método.
No es necesario liberar los identificadores de método y son válidos siempre que se cargue el tipo de Java
correspondiente. (Android no admite actualmente la descarga de clases).
Hay dos conjuntos de métodos para invocar métodos: uno para invocar métodos de manera virtual, y otro para
invocar métodos de manera no virtual. Ambos conjuntos de métodos requieren un identificador de método para
invocar el método, y la invocación no virtual también requiere que se especifique la implementación de clase que
se debe invocar.
Los métodos de interfaz solo se pueden buscar dentro del tipo declarativo; no se pueden buscar métodos que
proceden de interfaces extendidas o heredadas. Para más información, consulte la sección interfaces de enlace e
invocadores posteriores.
Se puede buscar cualquier método declarado en la clase o en cualquier clase base o interfaz implementada.
Invocación de método virtual
El conjunto de métodos para invocar métodos prácticamente sigue el patrón de nomenclatura:

* JNIEnv.Call*Method( IntPtr instance, IntPtr methodID, params JValue[] args );

donde * es el tipo de valor devuelto del método.


JNIEnv. CallObjectMethod – invoca un método que devuelve un java.lang.Object tipo no integrado,
como matrices e interfaces. El valor devuelto es una referencia local de JNI.
JNIEnv. CallBooleanMethod – invoca un método que devuelve un bool valor.
JNIEnv. CallByteMethod – invoca un método que devuelve un sbyte valor.
JNIEnv. CallCharMethod – invoca un método que devuelve un char valor.
JNIEnv. CallShortMethod – invoca un método que devuelve un short valor.
JNIEnv. CallLongMethod – invoca un método que devuelve un long valor.
JNIEnv. CallFloatMethod – invoca un método que devuelve un float valor.
JNIEnv. CallDoubleMethod – invoca un método que devuelve un double valor.
Invocación de método no virtual
El conjunto de métodos para invocar métodos no casi prácticamente sigue el patrón de nomenclatura:

* JNIEnv.CallNonvirtual*Method( IntPtr instance, IntPtr class, IntPtr methodID, params JValue[] args );

donde * es el tipo de valor devuelto del método. La invocación de métodos no virtuales normalmente se usa
para invocar el método base de un método virtual.
JNIEnv. CallNonvirtualObjectMethod – invocó de forma no virtual un método que devuelve un
java.lang.Object tipo no integrado, como matrices e interfaces. El valor devuelto es una referencia local
de JNI.
JNIEnv. CallNonvirtualBooleanMethod – no virtualmente invoca un método que devuelve un bool valor.
JNIEnv. CallNonvirtualByteMethod – no virtualmente invoca un método que devuelve un sbyte valor.
JNIEnv. CallNonvirtualCharMethod – no virtualmente invoca un método que devuelve un char valor.
JNIEnv. CallNonvirtualShortMethod – no virtualmente invoca un método que devuelve un short valor.
JNIEnv. CallNonvirtualLongMethod – no virtualmente invoca un método que devuelve un long valor.
JNIEnv. CallNonvirtualFloatMethod – no virtualmente invoca un método que devuelve un float valor.
JNIEnv. CallNonvirtualDoubleMethod – no virtualmente invoca un método que devuelve un double
valor.

Métodos estáticos
Los métodos estáticos se invocan a través de los identificadores de método. Los identificadores de método se
obtienen a través de JNIEnv. GetStaticMethodID, que requiere el tipo en el que se define el método, el nombre
del método y la firma de tipo JNI del método.
No es necesario liberar los identificadores de método y son válidos siempre que se cargue el tipo de Java
correspondiente. (Android no admite actualmente la descarga de clases).
Invocación de método estático
El conjunto de métodos para invocar métodos prácticamente sigue el patrón de nomenclatura:

* JNIEnv.CallStatic*Method( IntPtr class, IntPtr methodID, params JValue[] args );

donde * es el tipo de valor devuelto del método.


JNIEnv. CallStaticObjectMethod – invoca un método estático que devuelve un java.lang.Object tipo no
integrado, como matrices e interfaces. El valor devuelto es una referencia local de JNI.
JNIEnv. CallStaticBooleanMethod – invoca un método estático que devuelve un bool valor.
JNIEnv. CallStaticByteMethod – invoca un método estático que devuelve un sbyte valor.
JNIEnv. CallStaticCharMethod – invoca un método estático que devuelve un char valor.
JNIEnv. CallStaticShortMethod – invoca un método estático que devuelve un short valor.
JNIEnv. CallStaticLongMethod – invoca un método estático que devuelve un long valor.
JNIEnv. CallStaticFloatMethod – invoca un método estático que devuelve un float valor.
JNIEnv. CallStaticDoubleMethod – invoca un método estático que devuelve un double valor.

Signaturas de tipo JNI


Las signaturas de tipo JNI son referencias de tipo de JNI (aunque no son referencias de tipo simplificadas),
excepto los métodos. Con los métodos, la signatura de tipo JNI es un paréntesis '(' de apertura, seguido de las
referencias de tipo de todos los tipos de parámetro concatenados (sin comas separadoras ni nada más), seguido
de un ')' paréntesis de cierre. seguido de la referencia de tipo JNI del tipo de valor devuelto del método.
Por ejemplo, dado el método Java:

long f(int n, String s, int[] array);

La signatura de tipo JNI sería:

(ILjava/lang/String;[I)J

En general, se recomienda encarecidamente usar el comando javap para determinar las firmas de JNI. Por
ejemplo, la firma de tipo JNI del método java. lang. Thread. state. valueA (String) es "(Ljava/lang/String;)
Ljava/lang/Thread $ State;", mientras que la firma de tipo JNI del método java. lang. Thread. state. Values es "()
[Ljava/ lang/Thread $ State; ". Vea los signos de punto y coma finales; Estos forman parte de la signatura de tipo
JNI.

Referencias de tipo JNI


Las referencias de tipo JNI son diferentes de las referencias de tipo de Java. No puede usar nombres de tipo Java
completos como java.lang.String con JNI; en su lugar, debe usar las variaciones "java/lang/String" de JNI
"Ljava/lang/String;" o, en función del contexto, para obtener más información. Hay cuatro tipos de referencias
de tipo JNI:
built-in
representaciones
type
array
Referencias de tipos integrados
Las referencias a tipos integrados son un único carácter que se usa para hacer referencia a tipos de valor
integrados. La asignación es la siguiente:
"B" para sbyte .
"S" para short .
"I" para int .
"J" para long .
"F" para float .
"D" para double .
"C" para char .
"Z" para bool .
"V" para void los tipos de valor devueltos del método.
Referencias de tipo simplificado
Las referencias de tipo simplificado solo se pueden usar en JNIEnv. FindClass (cadena)). Hay dos maneras de
derivar una referencia de tipo simplificado:
1. En un nombre de Java completo, reemplace cada uno '.' dentro del nombre del paquete y antes del
nombre del '/' tipo con, '.' y cada uno dentro de '$' un nombre de tipo con.
2. Lea el resultado de 'unzip -l android.jar | grep JavaName' .
Cualquiera de los dos dará lugar a que el tipo Java . lang. Thread. State se asigne a la referencia
java/lang/Thread$State de tipo simplificado.

Referencias de tipo
Una referencia de tipo es una referencia de tipo integrada o una referencia de tipo simplificado 'L' con un
prefijo y un ';' sufijo. Para el tipo de Java java. lang. String, la referencia de tipo "java/lang/String"
simplificado es, mientras que "Ljava/lang/String;" la referencia de tipo es.
Las referencias de tipo se utilizan con referencias de tipo de matriz y con firmas de JNI.
Una manera adicional de obtener una referencia de tipo es leer la salida de
'javap -s -classpath android.jar fully.qualified.Java.Name' . Dependiendo del tipo implicado, puede usar una
declaración de constructor o un tipo de valor devuelto de método para determinar el nombre de JNI. Por
ejemplo:

$ javap -classpath android.jar -s java.lang.Thread.State


Compiled from "Thread.java"

public final class java.lang.Thread$State extends java.lang.Enum{


public static final java.lang.Thread$State NEW;
Signature: Ljava/lang/Thread$State;
public static final java.lang.Thread$State RUNNABLE;
Signature: Ljava/lang/Thread$State;
public static final java.lang.Thread$State BLOCKED;
Signature: Ljava/lang/Thread$State;
public static final java.lang.Thread$State WAITING;
Signature: Ljava/lang/Thread$State;
public static final java.lang.Thread$State TIMED_WAITING;
Signature: Ljava/lang/Thread$State;
public static final java.lang.Thread$State TERMINATED;
Signature: Ljava/lang/Thread$State;
public static java.lang.Thread$State[] values();
Signature: ()[Ljava/lang/Thread$State;
public static java.lang.Thread$State valueOf(java.lang.String);
Signature: (Ljava/lang/String;)Ljava/lang/Thread$State;
static {};
Signature: ()V
}

Thread.State es un tipo de enumeración de Java, por lo que podemos usar valueOf la firma del método para
determinar que la referencia de tipo es Ljava/lang/Thread $ State;.
Referencias de tipos de matriz
Las referencias a tipos '[' de matriz se anteponen a una referencia de tipo JNI. No se pueden usar referencias
de tipo simplificado al especificar matrices.
Por ejemplo, int[] es "[I" , int[][] es "[[I" y es java.lang.Object[] . "[Ljava/lang/Object;"
Genéricos de Java y eliminación de tipos
La mayoría de las veces, como se aprecia a través de JNI, no existengenéricos de Java. Hay algunas "arrugas",
pero esas arrugas están en cómo interactúa Java con los genéricos, no en cómo busca JNI y llama a los
miembros genéricos.
No hay ninguna diferencia entre un tipo o miembro genérico y un tipo o miembro no genérico al interactuar a
través de JNI. Por ejemplo, el tipo genérico java. lang. Class<T> es también el tipo java.lang.Class genérico
"RAW", ambos tienen la misma referencia de tipo simplificada, "java/lang/Class" .

Compatibilidad con la interfaz nativa de Java


Android. Runtime. JNIEnv es un contenedor administrado para Jave Native Interface (JNI). Las funciones JNI se
declaran dentro de la especificación de interfaz nativa de Java, aunque los métodos se JNIEnv* han cambiado
para quitar el parámetro explícito jobject y jclass IntPtr se jmethodID usa en lugar de,,, otros. Por ejemplo,
considere la función de JNI NewObject:

jobject NewObjectA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args);

Esto se expone como el método JNIEnv. NewObject :

public static IntPtr NewObject(IntPtr clazz, IntPtr jmethod, params JValue[] parms);

Trasladar entre las dos llamadas es razonablemente sencillo. En C tendría:

jobject CreateMapActivity(JNIEnv *env)


{
jclass Map_Class = (*env)->FindClass(env, "mono/samples/googlemaps/MyMapActivity");
jmethodID Map_defCtor = (*env)->GetMethodID (env, Map_Class, "<init>", "()V");
jobject instance = (*env)->NewObject (env, Map_Class, Map_defCtor);

return instance;
}

El C# equivalente sería:

IntPtr CreateMapActivity()
{
IntPtr Map_Class = JNIEnv.FindClass ("mono/samples/googlemaps/MyMapActivity");
IntPtr Map_defCtor = JNIEnv.GetMethodID (Map_Class, "<init>", "()V");
IntPtr instance = JNIEnv.NewObject (Map_Class, Map_defCtor);

return instance;
}

Una vez que tenga una instancia de objeto de Java contenida en un IntPtr, es probable que desee hacer algo con
ella. Puede usar métodos de JNIEnv como JNIEnv. CallVoidMethod () para hacerlo, pero si ya existe un
contenedor analógico C# , querrá construir un contenedor a través de la referencia de JNI. Puede hacerlo a través
del método de extensión extensions.<JavaCast T > :
IntPtr lrefActivity = CreateMapActivity();

// imagine that Activity were instead an interface or abstract type...


Activity mapActivity = new Java.Lang.Object(lrefActivity, JniHandleOwnership.TransferLocalRef)
.JavaCast<Activity>();

También puede usar el método de > Java. lang. Object<. GetObject T :

IntPtr lrefActivity = CreateMapActivity();

// imagine that Activity were instead an interface or abstract type...


Activity mapActivity = Java.Lang.Object.GetObject<Activity>(lrefActivity,
JniHandleOwnership.TransferLocalRef);

Además, todas las funciones JNI se han modificado quitando el JNIEnv* parámetro presente en cada función
JNI.

Resumen
Tratar directamente con JNI es una experiencia terrible que debe evitarse a todos los costos.
Desafortunadamente, no siempre se evita. Espero que esta guía le proporcione asistencia cuando alcance los
casos de Java sin enlazar con mono para Android.

Vínculos relacionados
Especificación de interfaz nativa de Java
Funciones de interfaz nativa de Java
Trasladar Java a C# para Xamarin. Android
27/07/2019 • 3 minutes to read • Edit Online

Este enfoque puede ser de interés para organizaciones que:


Está cambiando las pilas de tecnología de Java C#a.
Debe mantener una C# y una versión de Java del mismo producto.
Desea tener una versión de .NET de una biblioteca de Java popular.
Hay dos maneras de trasladar código de Java C#a. La primera forma es migrar el código manualmente. Esto
implica a desarrolladores experimentados que entienden .NET y Java y que están familiarizados con las
expresiones adecuadas para cada idioma. Este enfoque tiene más sentido para pequeñas cantidades de código o
para organizaciones que quieren salir completamente de Java a C#.
La segunda metodología de migración consiste en probar y automatizar el proceso mediante el uso de un
convertidor de código, como el enfoque. Sharp es un convertidor de código abierto desde el que se usó
originalmente para portar el código de DB4O de Java C#a. DB4O es una base de datos orientada a objetos que se
ha desarrollado en Java y, a continuación, se ha migrado a .NET. El uso de un convertidor de código puede tener
sentido para los proyectos que deben existir en ambos lenguajes y que requieran cierta paridad entre los dos.
Un ejemplo de Cuándo tiene sentido una herramienta de conversión de código automatizada puede verse en el
proyecto ngit . Ngit es un puerto del proyecto de Java las jgit. Las jgit es una implementación de Java del sistema
de administración de código fuente de git . Para generar C# código desde Java, los programadores de ngit usan un
sistema automatizado personalizado para extraer el código Java de las jgit, aplicar algunas revisiones para
acomodar el proceso de conversión y, a continuación, C# ejecutar enfoque, lo que genera el código. Esto permite
que el proyecto ngit se beneficie del trabajo continuo continuo realizado en las jgit.
A menudo, hay una cantidad de trabajo que no es trivial con el arranque de una herramienta de conversión de
código automatizada, lo que puede resultar una barrera para su uso. En muchos casos, puede ser más sencillo y
más fácil trasladar Java a C# mano.

Vínculos relacionados
Herramienta de conversión de enfoque
Enlace de una biblioteca Java
16/08/2019 • 16 minutes to read • Edit Online

La comunidad de Android tiene muchas bibliotecas de Java que puede que quiera usar en la aplicación; en esta
guía se explica cómo incorporar bibliotecas de Java a la aplicación de Xamarin. Android mediante la creación
de una biblioteca de enlaces.

Información general
El ecosistema de bibliotecas de terceros para Android es masivo. Por este motivo, a menudo tiene sentido usar
una biblioteca de Android existente que crear una nueva. Xamarin. Android ofrece dos maneras de usar estas
bibliotecas:
Cree una biblioteca de enlaces que ajuste automáticamente la biblioteca con contenedores C# para que
pueda invocar código Java a través C# de llamadas.
Use la interfaz nativa de Java (JNI) para invocar llamadas en el código de la biblioteca de Java
directamente. JNI es un marco de programación que permite a código Java llamar a las aplicaciones o
bibliotecas nativas y llamarlas.
En esta guía se explica la primera opción: Cómo crear una biblioteca de enlaces que incluya una o más
bibliotecas de Java existentes en un ensamblado al que se pueda vincular en la aplicación. Para obtener más
información sobre el uso de JNI, consulte trabajar con JNI.
Xamarin. Android implementa enlaces mediante contenedores a los que se puede llamar (MCW ) administrados.
MCW es un puente de JNI que se usa cuando el código administrado necesita invocar código Java. Los
contenedores a los que se puede llamar administrados también proporcionan compatibilidad para subclases de
tipos de Java y para invalidar métodos virtuales en tipos de Java. Del mismo modo, cada vez que el código de
tiempo de ejecución (ART) de Android quiere invocar código administrado, lo hace a través de otro puente de
JNI conocido como contenedores de Android Calling (ACW ). Esta arquitectura se ilustra en el diagrama
siguiente:

Una biblioteca de enlaces es un ensamblado que contiene contenedores a los que se puede llamar
administrados para tipos de Java. Por ejemplo, este es un tipo de Java MyClass ,, que queremos encapsular en
una biblioteca de enlaces:
package com.xamarin.mycode;

public class MyClass


{
public String myMethod (int i) { ... }
}

Después de generar una biblioteca de enlaces para el archivo . jar que MyClass contiene, podemos crear una
instancia de él y llamar a métodos C#en él desde:

var instance = new MyClass ();

string result = instance.MyMethod (42);

Para crear esta biblioteca de enlaces, use la plantilla biblioteca de enlaces de Java de Xamarin. Android. El
proyecto de enlace resultante crea un ensamblado .NET con las clases de MCW, los archivos . jar y los recursos
para los proyectos de biblioteca Android insertados en él. También puede crear bibliotecas de enlaces para el
archivo Android (. AAR ) y los proyectos de biblioteca de Android para Eclipse. Al hacer referencia al ensamblado
de DLL de la biblioteca de enlaces resultante, puede volver a usar una biblioteca de Java existente en el proyecto
de Xamarin. Android.
Al hacer referencia a los tipos de la biblioteca de enlaces, debe usar el espacio de nombres de la biblioteca de
enlaces. Normalmente, se agrega una using Directiva en la parte superior de C# los archivos de código fuente
que es la versión del espacio de nombres .net del nombre del paquete java. Por ejemplo, si el nombre del
paquete de Java para el archivo Bound . jar es el siguiente:

com.company.package

A continuación, colocaría la using siguiente instrucción en la parte superior C# de los archivos de código fuente
para obtener acceso a los tipos del archivo . jar enlazado:

using Com.Company.Package;

Al enlazar una biblioteca de Android existente, es necesario tener en cuenta los puntos siguientes:
¿Hay dependencias externas para la biblioteca? –Todas las dependencias de Java que requiere la
biblioteca de Android deben incluirse en el proyecto de Xamarin. Android como ReferenceJar o como
EmbeddedReferenceJar. Los ensamblados nativos deben agregarse al proyecto de enlace como un
EmbeddedNativeLibrary.
¿Qué versión de la API de Android es el destino de la biblioteca de Android? –No es posible
"degradar" el nivel de API de Android; Asegúrese de que el proyecto de enlace de Xamarin. Android
tenga como destino el mismo nivel de API (o superior) que la biblioteca de Android.
¿Qué versión del JDK se usó para compilar la biblioteca? –Pueden producirse errores de enlace si la
biblioteca de Android se compiló con una versión de JDK diferente de la que usa Xamarin. Android. Si es
posible, vuelva a compilar la biblioteca de Android con la misma versión del JDK que usa la instalación de
Xamarin. Android.

Acciones de compilación
Cuando se crea una biblioteca de enlaces, se establecen acciones de compilación en el archivo . jar o. Los
archivos AAR que se incorporan en el proyecto – de biblioteca de enlaces cada acción de compilación
determinan cómo . jar o. El archivo AAR se incrustará en la biblioteca de enlaces (o hará referencia a ella). En la
lista siguiente se resumen estas acciones de compilación:
EmbeddedJar Inserta el archivo . jar en la dll de la biblioteca de enlaces resultante como un recurso
incrustado. – Esta es la acción de compilación más sencilla y usada con más frecuencia. Use esta opción
cuando desee que el archivo . jar se compile automáticamente en el código de bytes y se empaquete en la
biblioteca de enlaces.
InputJar No inserta el archivo . jar en la biblioteca de enlaces resultante. – DLL. La biblioteca de enlaces.
DLL tendrá una dependencia de este archivo . jar en tiempo de ejecución. Utilice esta opción si no desea
incluir el archivo . jar en la biblioteca de enlaces (por ejemplo, por motivos de licencia). Si usa esta opción,
debe asegurarse de que el archivo INPUT . jar está disponible en el dispositivo que ejecuta la aplicación.
LibraryProjectZip – Inserta un. Archivo AAR en la biblioteca de enlaces resultante. DLL. Esto es similar a
EmbeddedJar, salvo que puede tener acceso a los recursos (así como al código) en el enlazado. Archivo
AAR. Utilice esta opción si desea incrustar un. AAR en la biblioteca de enlaces.
ReferenceJar Especifica un archivo Reference. jar: un archivo Reference. jar es un archivo. jar que es un
archivo. jar enlazado. – Los archivos AAR dependen de. Esta referencia . jar solo se utiliza para satisfacer
las dependencias de tiempo de compilación. Cuando se usa esta acción de compilación C# , no se crean
enlaces para Reference . jar y no se insertan en la biblioteca de enlaces resultante. DLL. Use esta opción
cuando vaya a crear una biblioteca de enlaces para el archivo Reference . jar pero aún no lo haya hecho.
Esta acción de compilación es útil para empaquetar varios . jars (y/o. AARs) en varias bibliotecas de
enlaces interdependientes.
EmbeddedReferenceJar Inserta un archivo Reference . jar en la biblioteca de enlaces resultante. – DLL. Use
esta acción de compilación cuando desee crear C# enlaces para INPUT . jar (o. AAR ) y todas sus
referencias . jar(s) en la biblioteca de enlaces.
EmbeddedNativeLibrary Inserta un objeto nativo . así en el enlace. – Esta acción de compilación se usa para
. por tanto, los archivos que requiere el archivo . jar que se está enlazando. Puede que sea necesario
cargar manualmente la biblioteca . so antes de ejecutar el código de la biblioteca de Java. Esto se describe
a continuación.
Estas acciones de compilación se explican con más detalle en las siguientes guías.
Además, las siguientes acciones de compilación se usan para ayudar a importar la documentación de la API C#
de Java y convertirlas en documentación XML:
JavaDocJar se usa para apuntar al archivo jar de archivo Javadoc para una biblioteca Java que se ajusta a un
estilo de paquete FOOBAR-javadoc**.jar** Maven (normalmente).
JavaDocIndex se usa para apuntar index.html al archivo en el HTML de documentación de referencia de la
API.
JavaSourceJar se utiliza para complementar JavaDocJar , para generar primero Javadoc a partir de orígenes
y, a continuación, tratar los resultados como JavaDocIndex , para una biblioteca Java que se ajusta a un
FOOBAR-sources**.jar** estilo de paquete Maven (normalmente).

La documentación de la API debe ser el valor predeterminado de doclet de Java8, Java7 o java6 SDK (tienen el
mismo formato) o el estilo DroidDoc.

Incluir una biblioteca nativa en un enlace


Puede que sea necesario incluir una biblioteca . so en un proyecto de enlace de Xamarin. Android como parte
del enlace de una biblioteca de Java. Cuando se ejecuta el código de Java ajustado, Xamarin. Android no
realizará la llamada JNI y el mensaje de error Java. lang. UnsatisfiedLinkError: Método nativo no encontrado:
aparecerá en el logcat de salida de la aplicación.
La solución para esto es cargar manualmente la biblioteca . so con una llamada a
Java.Lang.JavaSystem.LoadLibrary . Por ejemplo, suponiendo que un proyecto de Xamarin. Android tiene
libpocketsphinx_jni de biblioteca compartida . por tanto , se incluye en el proyecto de enlace con una acción de
compilación de EmbeddedNativeLibrary, el siguiente fragmento de código (ejecutado antes de usar la
biblioteca compartida) cargará la biblioteca . so :

Java.Lang.JavaSystem.LoadLibrary("pocketsphinx_jni");

Adaptación de API de Java a C


El generador de enlaces de Xamarin. Android cambiará algunas expresiones y patrones de Java para que se
correspondan con los patrones de .NET. En la siguiente lista se describe cómo se asigna C#Java a/.net:
Los métodos Setter/getter de Java son propiedades de .net.
Los campos de Java son propiedades de .net.
Los agentes de escucha o las interfaces de escucha en Java son eventos en .net. Los parámetros de los
métodos de las interfaces de devolución de llamada se EventArgs representarán mediante una subclase.
Una clase anidada estática en Java es una clase anidada en .net.
Una clase interna en Java es una clase anidada con un constructor de instancia C#en.

Escenarios de enlace
Las siguientes guías de escenarios de enlace pueden ayudarle a enlazar una biblioteca de Java (o bibliotecas)
para su incorporación a su aplicación:
Enlazar un. JAR es un tutorial para crear bibliotecas de enlaces para archivos . jar .
Enlazar un. AAR es un tutorial para crear bibliotecas de enlaces para. Archivos AAR. Lea este tutorial para
aprender a enlazar bibliotecas de Android Studio.
Enlazar un proyecto de biblioteca Eclipse es un tutorial para crear bibliotecas de enlace desde proyectos
de biblioteca de Android. Lea este tutorial para aprender a enlazar proyectos de biblioteca de Android de
Eclipse.
La personalización de enlaces explica cómo realizar modificaciones manuales en el enlace para resolver
errores de compilación y dar forma a la API resultante para que seaC#más "similar".
Solución de problemas de enlaces muestra escenarios comunes de error de enlace, explica las posibles
causas y ofrece sugerencias para resolver estos errores.

Vínculos relacionados
Trabajar con JNI
Metadatos de GAPI
Uso de bibliotecas nativas
Enlace de un .JAR
16/08/2019 • 12 minutes to read • Edit Online

En este tutorial se proporcionan instrucciones paso a paso para crear una biblioteca de enlaces de Java de
Xamarin. Android desde un dispositivo Android. Archivo JAR.

Información general
La comunidad de Android ofrece muchas bibliotecas de Java que puede usar en la aplicación. Estas bibliotecas de
Java se suelen empaquetar en. Formato JAR (archivo Java), pero puede empaquetar un. JAR en una biblioteca de
enlaces de Java para que su funcionalidad esté disponible para las aplicaciones de Xamarin. Android. El propósito
de la biblioteca de enlaces de Java es crear las API en. Archivo JAR disponible para C# el código a través de
contenedores de código generados automáticamente.
Las herramientas de Xamarin pueden generar una biblioteca de enlaces a partir de una o varias entradas. Archivos
JAR. La biblioteca de enlaces (. Ensamblado DLL ) contiene lo siguiente:
Contenido de la original. Archivos JAR.
Contenedores a los que se puede llamar (MCW ) C# administrados, que son tipos que contienen los tipos
de Java correspondientes dentro de. Archivos JAR.
El código MCW generado usa JNI (Java Native Interface) para reenviar las llamadas API al subyacente. Archivo
JAR. Puede crear bibliotecas de enlaces para cualquier. Archivo JAR que se destine originalmente para usarse con
Android (tenga en cuenta que las herramientas de Xamarin no admiten actualmente el enlace de bibliotecas de
Java que no son de Android). También puede optar por compilar la biblioteca de enlaces sin incluir el contenido
de. Archivo JAR para que la DLL tenga una dependencia en. JAR en tiempo de ejecución.
En esta guía se detallan los conceptos básicos de la creación de una biblioteca de enlaces para un único. Archivo
JAR. Veremos con un ejemplo en el que todo va – bien, es decir, donde no se requiere ninguna personalización o
depuración de los enlaces. La creación de enlaces mediante metadatos ofrece un ejemplo de un escenario más
avanzado en el que el proceso de enlace no es totalmente automático y se requiere una cantidad de intervención
manual. Para obtener información general sobre el enlace de la biblioteca de Java en general (con un ejemplo de
código básico), vea enlazar una biblioteca de Java.

Tutorial
En el siguiente tutorial, vamos a crear una biblioteca de enlaces para Picasso, un conocido Android. JAR que
proporciona la funcionalidad de carga de imágenes y almacenamiento en caché. Usaremos los pasos siguientes
para enlazar Picasso-2. x. x. jar para crear un nuevo ensamblado .net que se pueda usar en un proyecto de
Xamarin. Android:
1. Cree un nuevo proyecto de biblioteca de enlaces de Java.
2. Agregue el. Archivo JAR en el proyecto.
3. Establezca la acción de compilación adecuada para. Archivo JAR.
4. Elija una versión de .NET Framework de destino que. JAR admite.
5. Compile la biblioteca de enlaces.
Una vez que hemos creado la biblioteca de enlaces, desarrollaremos una pequeña aplicación Android que
demuestra nuestra capacidad para llamar a las API en la biblioteca de enlaces. En este ejemplo, queremos acceder
a los métodos de Picasso-2. x. x. jar:

package com.squareup.picasso

public class Picasso


{
...
public static Picasso with (Context context) { ... };
...
public RequestCreator load (String path) { ... };
...
}

Después de generar una biblioteca de enlaces para Picasso-2. x. x. jar, podemos llamar a estos métodos desde
C#. Por ejemplo:

using Com.Squareup.Picasso;
...
Picasso.With (this)
.Load ("http://mydomain.myimage.jpg")
.Into (imageView);

Crear la biblioteca de enlaces


Antes de comenzar con los pasos siguientes, descargue Picasso-2. x. x. jar.
En primer lugar, cree un nuevo proyecto de biblioteca de enlaces. En Visual Studio para Mac o Visual Studio, cree
una nueva solución y seleccione la plantilla biblioteca de enlaces de Android . (Las capturas de pantallas de este
tutorial usan Visual Studio, pero Visual Studio para Mac es muy similar). Asigne a la solución el nombre
JarBinding:

La plantilla incluye una carpeta jar donde se agrega el. JAR (s) en el proyecto de biblioteca de enlaces. Haga clic
con el botón derecho en la carpeta jar y seleccione Agregar > elemento existente:
Navegue hasta el archivo Picasso-2. x. jar descargado anteriormente, selecciónelo y haga clic en Agregar:

Compruebe que el archivo Picasso-2. x. x. jar se ha agregado correctamente al proyecto:

Al crear un proyecto de biblioteca de enlaces de Java, debe especificar si el. JAR se debe insertar en la biblioteca
de enlaces o empaquetar por separado. Para ello, especifique una de las siguientes acciones de compilación:
EmbeddedJar – el. JAR se incrustará en la biblioteca de enlaces.
InputJar – el. JAR se mantendrá separado de la biblioteca de enlaces.
Normalmente, se usa la acción de compilación EmbeddedJar para que. JAR se empaqueta automáticamente en
la biblioteca de enlaces. Esta es la opción – más sencilla de código de bytes de Java en. JAR se convierte en el
código de bytes DEX y se incrusta (junto con los contenedores a los que se puede llamar administrados) en APK.
Si desea conservar el. JAR independiente de la biblioteca de enlaces, puede usar la opción InputJar ; sin embargo,
debe asegurarse de que el. El archivo JAR está disponible en el dispositivo que ejecuta la aplicación.
Establezca la acción de compilación en EmbeddedJar:
A continuación, abra las propiedades del proyecto para configurar la versión de .NET Framework de destino. Si el.
JAR usa cualquier API de Android, establezca la plataforma de destino en el nivel de API que el. JAR espera.
Normalmente, el desarrollador de. El archivo JAR indicará qué nivel de API (o niveles). JAR es compatible con.
(Para obtener más información sobre la configuración de la plataforma de destino y los niveles de la API de
Android en general, consulte Descripción de los niveles de API de Android).
Establezca el nivel de API de destino de la biblioteca de enlaces (en este ejemplo, se usa el nivel de API 19):

Por último, compile la biblioteca de enlaces. Aunque se pueden mostrar algunos mensajes de advertencia, el
proyecto de biblioteca de enlaces se debe compilar correctamente y generar una salida. DLL en la siguiente
ubicación: JarBinding/bin/Debug/JarBinding.dll
Uso de la biblioteca de enlaces
Para consumir este. DLL en la aplicación de Xamarin. Android, haga lo siguiente:
1. Agregue una referencia a la biblioteca de enlaces.
2. Realice llamadas en. JAR a través de los contenedores a los que se puede llamar administrados.
En los pasos siguientes, crearemos una aplicación mínima que use la biblioteca de enlaces para descargar y
mostrar una imagen en un ImageView ; el código que se encuentra en el se realiza el "trabajo pesado". Archivo JAR.
En primer lugar, cree una nueva aplicación de Xamarin. Android que consuma la biblioteca de enlaces. Haga clic
con el botón derecho en la solución y seleccione Agregar nuevo proyecto. Asigne al nuevo proyecto el nombre
BindingTest. Vamos a crear esta aplicación en la misma solución que la biblioteca de enlaces con el fin de
simplificar este tutorial. sin embargo, en su lugar, la aplicación que usa la biblioteca de enlaces puede residir en
una solución diferente:
Haga clic con el botón secundario en el nodo referencias del proyecto BindingTest y seleccione Agregar
referencia.. .:

Compruebe el proyecto JarBinding creado anteriormente y haga clic en Aceptar:


Abra el nodo References del proyecto BindingTest y compruebe que la referencia JarBinding está presente:

Modifique el diseño de BindingTest (Main. axml) para que tenga una única ImageView :

<?xml version="1.0" encoding="utf-8"?>


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:minWidth="25px"
android:minHeight="25px">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/imageView" />
</LinearLayout>

Agregue la siguiente using instrucción a MainActivity.CS – esto permite acceder fácilmente a los métodos de la
clase basada Picasso en Java que reside en la biblioteca de enlaces:
using Com.Squareup.Picasso;

Modifique el OnCreate método para que use la Picasso clase para cargar una imagen de una dirección URL y
mostrarla en el ImageView :

public class MainActivity : Activity


{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
ImageView imageView = FindViewById<ImageView>(Resource.Id.imageView);

// Use the Picasso jar library to load and display this image:
Picasso.With (this)
.Load ("http://i.imgur.com/DvpvklR.jpg")
.Into (imageView);
}
}

Compile y ejecute el proyecto BindingTest . La aplicación se iniciará y, después de un breve retraso (según las
condiciones de la red), debe descargar y mostrar una imagen similar a la siguiente captura de pantalla:

¡ Enhorabuena! Ha enlazado correctamente una biblioteca de Java. JAR y usarlo en la aplicación Xamarin. Android.
Resumen
En este tutorial, creamos una biblioteca de enlaces para un tercero. Archivo JAR, se ha agregado la biblioteca de
enlaces a una aplicación de prueba mínima y se ha ejecutado la aplicación para C# comprobar que el código
puede llamar al código de Java que reside en. Archivo JAR.

Vínculos relacionados
Creación de una biblioteca de enlaces de Java (vídeo)
Enlace de una biblioteca Java
Enlace de un .AAR
16/08/2019 • 15 minutes to read • Edit Online

En este tutorial se proporcionan instrucciones paso a paso para crear una biblioteca de enlaces de Java de
Xamarin. Android desde un dispositivo Android. Archivo AAR.

Información general
El archivo Android (. AAR ) es el formato de archivo de las bibliotecas de Android. Alternativa. El archivo AAR es
un. Archivo ZIP que contiene lo siguiente:
Código Java compilado
Identificadores de recursos
Recursos
Metadatos (por ejemplo, declaraciones de actividad, permisos)
En esta guía se detallan los conceptos básicos de la creación de una biblioteca de enlaces para un único. Archivo
AAR. Para obtener información general sobre el enlace de la biblioteca de Java en general (con un ejemplo de
código básico), vea enlazar una biblioteca de Java.

IMPORTANT
Un proyecto de enlace solo puede incluir uno. Archivo AAR. Si el. AAR dependencias en otros. AAR, estas dependencias
deben estar contenidas en su propio proyecto de enlace y, a continuación, se puede hacer referencia a ellas. Vea el error
44573.

Tutorial
Vamos a crear una biblioteca de enlaces para un archivo de almacenamiento de Android de ejemplo creado en
Android Studio textanalyzer. AAR. El. AAR contiene una TextCounter clase con métodos estáticos que cuentan el
número de vocales y consonantes de una cadena. Además, textanalyzer. AAR contiene un recurso de imagen
que ayuda a mostrar los resultados del recuento.
Usaremos los pasos siguientes para crear una biblioteca de enlaces desde. Archivo AAR:
1. Cree un nuevo proyecto de biblioteca de enlaces de Java.
2. Agregue un único. Archivo AAR en el proyecto. Un proyecto de enlace solo puede contener un único. AAR.
3. Establezca la acción de compilación adecuada para. Archivo AAR.
4. Elija una versión de .NET Framework de destino que. AAR admite.
5. Compile la biblioteca de enlaces.
Una vez creada la biblioteca de enlaces, desarrollaremos una pequeña aplicación de Android que pida al usuario
una cadena de texto, llama a. Los métodos de AAR para analizar el texto, recuperan la imagen de. AAR y muestra
los resultados junto con la imagen.
La aplicación de ejemplo tendrá acceso TextCounter a la clase de textanalyzer. AAR:
package com.xamarin.textcounter;

public class TextCounter


{
...
public static int numVowels (String text) { ... };
...
public static int numConsonants (String text) { ... };
...
}

Además, esta aplicación de ejemplo recuperará y mostrará un recurso de imagen que está empaquetado en
textanalyzer. AAR:

Este recurso de imagen reside en res/drawable/Monkey. png en textanalyzer. AAR.


Crear la biblioteca de enlaces
Antes de comenzar con los pasos siguientes, descargue el archivo de almacenamiento de Android de ejemplo
textanalyzer. AAR :
1. Cree un nuevo proyecto de biblioteca de enlaces a partir de la plantilla de la biblioteca de enlaces de
Android. Puede usar Visual Studio para Mac o Visual Studio (las capturas de pantallas siguientes muestran
Visual Studio, pero Visual Studio para Mac es muy similar). Asigne a la solución el nombre AarBinding:

2. La plantilla incluye una carpeta jar donde se agrega el. AAR (s) al proyecto de biblioteca de enlaces. Haga
clic con el botón derecho en la carpeta jar y seleccione Agregar > elemento existente:

3. Navegue hasta el archivo textanalyzer. AAR descargado anteriormente, selecciónelo y haga clic en
Agregar:

4. Compruebe que el archivo textanalyzer. AAR se ha agregado correctamente al proyecto:


5. Establezca la acción de compilación para textanalyzer. AAR en LibraryProjectZip . En Visual Studio para
Mac, haga clic con el botón secundario en textanalyzer. AAR para establecer la acción de compilación. En
Visual Studio, la acción de compilación se puede establecer en el panel de propiedades :

6. Abra las propiedades del proyecto para configurar la versión de .NET Framework de destino. Si el. AAR usa
cualquier API de Android, establezca la plataforma de destino en el nivel de API que el. AAR espera. (Para
obtener más información sobre la configuración de la plataforma de destino y los niveles de la API de
Android en general, consulte Descripción de los niveles de API de Android).
Establezca el nivel de API de destino para la biblioteca de enlaces. En este ejemplo, podemos usar el nivel
de API de plataforma más reciente (nivel de API 23) porque nuestro textanalyzer no tiene una
dependencia en las API de Android:
7. Compile la biblioteca de enlaces. El proyecto de biblioteca de enlaces se debe compilar correctamente y
generar una salida. DLL en la siguiente ubicación: AarBinding/bin/Debug/AarBinding.dll
Uso de la biblioteca de enlaces
Para consumir este. DLL en la aplicación de Xamarin. Android, primero debe agregar una referencia a la biblioteca
de enlaces. Siga estos pasos:
1. Vamos a crear esta aplicación en la misma solución que la biblioteca de enlaces para simplificar este tutorial.
(La aplicación que usa la biblioteca de enlaces también puede residir en una solución diferente). Cree una
nueva aplicación de Xamarin. Android: haga clic con el botón derecho en la solución y seleccione Agregar
nuevo proyecto. Asigne al nuevo proyecto el nombre BindingTest:

2. Haga clic con el botón secundario en el nodo referencias del proyecto BindingTest y seleccione Agregar
referencia.. .:
3. Seleccione el proyecto AarBinding creado anteriormente y haga clic en Aceptar:

4. Abra el nodo References del proyecto BindingTest para comprobar que la referencia AarBinding está
presente:

Si desea ver el contenido del proyecto de biblioteca de enlaces, puede hacer doble clic en la referencia para abrirla
en el Examinador de objetos. Puede ver el contenido asignado del Com.Xamarin.Textcounter espacio de nombres
(asignado desde el paquete de Java com.xamarin.textanalyzezr ) y puede ver los miembros de la TextCounter
clase:

En la captura de pantalla anterior TextAnalyzer se resaltan los dos métodos a NumConsonants los que llamará la
aplicación de numConsonants ejemplo: (que NumVowels incluye el método Java subyacente) y numVowels (que
incluye el método Java subyacente).
Acceso a. Tipos de AAR
Después de agregar una referencia a la aplicación que apunta a la biblioteca de enlaces, puede tener acceso a los
tipos de Java en el. AAR como se haría con C# los tipos de acceso ( C# gracias a los contenedores). C#el código de
la TextAnalyzer aplicación puede llamar a métodos como se muestra en este ejemplo:

using Com.Xamarin.Textcounter;
...
int numVowels = TextCounter.NumVowels (myText);
int numConsonants = TextCounter.NumConsonants (myText);

En el ejemplo anterior, se llama a métodos estáticos en TextCounter la clase. Sin embargo, también puede crear
instancias de clases y llamar a métodos de instancia. Por ejemplo, si su. AAR contiene una clase denominada
Employee que tiene el método buildFullName de instancia MyClass , puede crear instancias de ella y usarla tal y
como se muestra aquí:

var employee = new Com.MyCompany.MyProject.Employee();


var name = employee.BuildFullName ();

En los pasos siguientes se agrega código a la aplicación para que solicite texto al usuario, usa TextCounter para
analizar el texto y, a continuación, muestra los resultados.
Reemplace el diseño de BindingTest (Main. axml) con el siguiente código XML. Este diseño tiene un EditText
para la entrada de texto y dos botones para iniciar recuentos de vocales y consonantes:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation ="vertical"
android:layout_width ="fill_parent"
android:layout_height ="fill_parent" >
<TextView
android:text ="Text to analyze:"
android:textSize ="24dp"
android:layout_marginTop ="30dp"
android:layout_gravity ="center"
android:layout_width ="wrap_content"
android:layout_height ="wrap_content" />
<EditText
android:id ="@+id/input"
android:text ="I can use my .AAR file from C#!"
android:layout_marginTop ="10dp"
android:layout_gravity ="center"
android:layout_width ="300dp"
android:layout_height ="wrap_content"/>
<Button
android:id ="@+id/vowels"
android:layout_marginTop ="30dp"
android:layout_width ="240dp"
android:layout_height ="wrap_content"
android:layout_gravity ="center"
android:text ="Count Vowels" />
<Button
android:id ="@+id/consonants"
android:layout_width ="240dp"
android:layout_height ="wrap_content"
android:layout_gravity ="center"
android:text ="Count Consonants" />
</LinearLayout>

Reemplace el contenido de MainActivity.CS por el código siguiente. Como se aprecia en este ejemplo, los
controladores de eventos de botón TextCounter llaman a métodos ajustados que residen en. AAR y use la
notificación del sistema para mostrar los resultados. Observe la using instrucción para el espacio de nombres de
la biblioteca enlazada (en Com.Xamarin.Textcounter este caso,):
using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using Android.Views.InputMethods;
using Com.Xamarin.Textcounter;

namespace BindingTest
{
[Activity(Label = "BindingTest", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{
InputMethodManager imm;

protected override void OnCreate(Bundle bundle)


{
base.OnCreate(bundle);

SetContentView(Resource.Layout.Main);

imm = (InputMethodManager)GetSystemService(Context.InputMethodService);

var vowelsBtn = FindViewById<Button>(Resource.Id.vowels);


var consonBtn = FindViewById<Button>(Resource.Id.consonants);
var edittext = FindViewById<EditText>(Resource.Id.input);
edittext.InputType = Android.Text.InputTypes.TextVariationPassword;

edittext.KeyPress += (sender, e) =>


{
imm.HideSoftInputFromWindow(edittext.WindowToken, HideSoftInputFlags.NotAlways);
e.Handled = true;
};

vowelsBtn.Click += (sender, e) =>


{
int count = TextCounter.NumVowels(edittext.Text);
string msg = count + " vowels found.";
Toast.MakeText (this, msg, ToastLength.Short).Show ();
};

consonBtn.Click += (sender, e) =>


{
int count = TextCounter.NumConsonants(edittext.Text);
string msg = count + " consonants found.";
Toast.MakeText (this, msg, ToastLength.Short).Show ();
};

}
}
}

Compile y ejecute el proyecto BindingTest . La aplicación se iniciará y presentará la captura de pantalla a


EditText la izquierda (el se inicializa con texto, pero puede puntear para cambiarlo). Al pulsar en recuentode
vocales, un sistema de notificación muestra el número de vocales, como se muestra a la derecha:
Pruebe a pulsar el botón recuento de consonantes. Además, puede modificar la línea de texto y puntear de nuevo
en estos botones para probar los diferentes recuentos de vocales y consonantes.
Acceso a. Recursos de AAR
Las herramientas de Xamarin combinan los datos de R de. AAR en la clase de recursos de la aplicación. Como
resultado, puede tener acceso a. AAR recursos del diseño (y del código subyacente) de la misma manera en que
tendría acceso a los recursos que se encuentran en la ruta de acceso a los recursos del proyecto.
Para tener acceso a un recurso de imagen, use el nombre de recurso. drawable para la imagen empaquetada
dentro de. AAR. Por ejemplo, puede hacer referencia a Image. png en. Archivo AAR con @drawable/image :

<ImageView android:src="@drawable/image" ... />

También puede tener acceso a los diseños de recursos que residen en el. AAR. Para ello, utilice el nombre
Resource. layout para el diseño empaquetado dentro de. AAR. Por ejemplo:

var a = new ArrayAdapter<string>(this, Resource.Layout.row_layout, ...);

El ejemplo de textanalyzer. AAR contiene un archivo de imagen que reside en res/drawable/Monkey. png.
Vamos a acceder a este recurso de imagen y usarlo en nuestra aplicación de ejemplo:
Edite el diseño de BindingTest (Main. axml) ImageView y agregue al final del LinearLayout contenedor. Se
muestra la imagen que se **@drawable/monkey** encuentra en; esta imagen se cargará desde la sección de
recursos de textanalyzer. AAR: ImageView
...
<ImageView
android:src ="@drawable/monkey"
android:layout_marginTop ="40dp"
android:layout_width ="200dp"
android:layout_height ="200dp"
android:layout_gravity ="center" />

</LinearLayout>

Compile y ejecute el proyecto BindingTest . La aplicación se iniciará y presentará la captura de – pantalla de la


izquierda cuando pulse en recuento de consonantes, los resultados se mostrarán como se muestra a la derecha:

¡ Enhorabuena! Ha enlazado correctamente una biblioteca de Java. AAR!

Resumen
En este tutorial, creamos una biblioteca de enlaces para un. Archivo AAR, agregó la biblioteca de enlaces a una
aplicación de prueba mínima y ejecutó la aplicación para comprobar que C# el código puede llamar al código Java
que reside en. Archivo AAR. Además, extendimos la aplicación para obtener acceso y mostrar un recurso de
imagen que se encuentra en el. Archivo AAR.

Vínculos relacionados
Creación de una biblioteca de enlaces de Java (vídeo)
Enlace de un .JAR
Enlace de una biblioteca Java
AarBinding (ejemplo)
Error 44573: un proyecto no puede enlazar varios archivos. AAR
Enlace de un proyecto de biblioteca de Eclipse
11/07/2019 • 5 minutes to read • Edit Online

Este tutorial explica cómo usar las plantillas de proyecto de Xamarin.Android para enlazar un proyecto de
biblioteca de Android de Eclipse.

Información general
Aunque. Archivos AAR son cada vez más la norma para la distribución de la biblioteca de Android, en algunos
casos es necesario crear un enlace para un proyecto de biblioteca Android. Los proyectos de biblioteca Android
son proyectos de Android especiales que contienen código que se puede compartir y recursos que pueden hacer
referencia a los proyectos de aplicación de Android. Normalmente, enlaza a un proyecto de biblioteca de Android
cuando se crea la biblioteca en el IDE de Eclipse. En este tutorial se proporciona ejemplos de cómo crear un
proyecto de biblioteca Android. Código postal de la estructura de directorios de un proyecto de Eclipse.
Los proyectos de biblioteca Android son diferentes de los proyectos de Android normales en que no se compilan
en un APK y no, son por sí solos, puede implementar en un dispositivo. En su lugar, un proyecto de biblioteca
Android sirve para hacer referencia a un proyecto de aplicación de Android. Cuando se compila un proyecto de
aplicación de Android, en primer lugar se compila el proyecto de biblioteca de Android. El proyecto de aplicación
de Android, a continuación, se se absorba en el proyecto de biblioteca de Android compilado e incluya el código y
los recursos en el APK para su distribución. Debido a esta diferencia, crear un enlace para un proyecto de
biblioteca de Android es ligeramente diferente de la creación de un enlace para un Java. JAR o. Archivo AAR.

Tutorial
Para usar un proyecto de biblioteca de Android en un proyecto de enlace de Java de Xamarin.Android es necesario
para compilar el proyecto de biblioteca de Android en Eclipse. Captura de pantalla siguiente muestra un ejemplo
de un proyecto de biblioteca de Android después de la compilación:
Tenga en cuenta que se ha compilado el código fuente del proyecto de biblioteca de Android en un archivo
temporal. Archivo JAR denominado android mapviewballoons.jar, y que los recursos se han copiado en el
res/bin/tardaban carpeta.
Una vez que se ha compilado el proyecto de biblioteca de Android en Eclipse, se puede, a continuación, enlazar
con un proyecto de enlace de Java de Xamarin.Android. Primera una. Se debe crear el archivo ZIP que contiene el
bin y res carpetas del proyecto de biblioteca Android. Es importante que quite el intermedia tardaban
subdirectorio para que los recursos residen en bin/res. Captura de pantalla siguiente muestra el contenido de una
tal. Archivo ZIP:
Esto. Archivo ZIP, a continuación, se agrega al proyecto de enlace de Java de Xamarin.Android, como se muestra
en la captura de pantalla siguiente:

Tenga en cuenta que la acción de compilación de la. Archivo ZIP se ha establecido automáticamente en
LibraryProjectZip.
Si hay alguno. Archivos JAR necesarios para el proyecto de biblioteca de Android, se debe agregar a la archivos
JAR carpeta del proyecto de biblioteca de enlaces de Java y el acción de compilación establecido en
ReferenceJar. Un ejemplo de esto se aprecia en la captura de pantalla siguiente:
Una vez completados estos pasos, se puede usar el proyecto Xamarin.Android Java enlace como se describe
anteriormente en este documento.

NOTE
En este momento no se admite la compilación de los proyectos de biblioteca de Android en otros IDE. Otros IDE no puede
crear la misma estructura de directorios o archivos en el bin carpeta como Eclipse.

Resumen
En este artículo, hemos visto el proceso de enlazar un proyecto de biblioteca Android. Se generó el proyecto de
biblioteca de Android en Eclipse, a continuación, creamos un archivo zip desde el bin y res carpetas del proyecto
de biblioteca Android. A continuación, se usa este archivo zip para crear un proyecto de enlace de Java de
Xamarin.Android.
Personalización de enlaces
16/08/2019 • 2 minutes to read • Edit Online

Puede personalizar un enlace de Xamarin. Android editando los metadatos que controlan el proceso de enlace.
Estas modificaciones manuales suelen ser necesarias para resolver errores de compilación y para dar forma a la
API resultante para que sea más coherente con C#/.net. En estas guías se explica la estructura de estos metadatos,
cómo modificar los metadatos y cómo usar JavaDoc para recuperar los nombres de los parámetros de método.

Información general
Xamarin. Android automatiza gran parte del proceso de enlace. sin embargo, en algunos casos, se requiere una
modificación manual para solucionar los problemas siguientes:
Resolver errores de compilación causados por tipos que faltan, tipos ofuscados, nombres duplicados,
problemas de visibilidad de clases y otras situaciones que las herramientas de Xamarin. Android no pueden
resolver.
Cambiar la asignación que usa Xamarin. Android para enlazar la API de Android a diferentes C# tipos en
(por ejemplo, muchos desarrolladores prefieren asignar int constantes de Java C# enum a constantes).
Quitar los tipos no usados que no es necesario enlazar.
Agregar tipos que no tienen homólogos en la API de Java subyacente.
Puede realizar algunos o todos estos cambios modificando los metadatos que controlan el proceso de enlace.

Guías
En las guías siguientes se describen los metadatos que controlan el proceso de enlace y se explica cómo
modificarlos para solucionar estos problemas:
Los metadatos de enlaces de Java proporcionan información general de los metadatos que entran en un
enlace de Java. Describe los distintos pasos manuales que a veces se requieren para completar una
biblioteca de enlace de Java y explica cómo dar forma a una API expuesta por un enlace para seguir las
instrucciones de diseño de .NET.
El nombre de los parámetros con javadoc explica cómo recuperar los nombres de los parámetros en un
proyecto de enlace de Java mediante el uso de Javadoc generado a partir del proyecto de Java enlazado.
Metadatos de enlaces Java
16/08/2019 • 20 minutes to read • Edit Online

C#el código de Xamarin. Android llama a las bibliotecas de Java a través de enlaces, que son un mecanismo que
abstrae los detalles de bajo nivel que se especifican en Java Native Interface (JNI ). Xamarin. Android proporciona
una herramienta que genera estos enlaces. Estas herramientas permiten al desarrollador controlar cómo se crea
un enlace mediante metadatos, lo que permite procedimientos como la modificación de espacios de nombres y el
cambio de nombre de los miembros. En este documento se explica cómo funcionan los metadatos, se resumen los
atributos que admiten los metadatos y se explica cómo resolver los problemas de enlace mediante la
modificación de estos metadatos.

Información general
Una biblioteca de enlace de Java de Xamarin. Android intenta automatizar gran parte del trabajo necesario
para enlazar una biblioteca de Android existente con la ayuda de una herramienta que a veces se conoce como
generador de enlaces. Al enlazar una biblioteca de Java, Xamarin. Android inspeccionará las clases de Java y
generará una lista de todos los paquetes, tipos y miembros que se van a enlazar. Esta lista de API se almacena en
un archivo XML que se puede encontrar en {el directorio de proyecto} \obj\Release\api.XML para una
compilación de versión y en {el directorio de proyecto} \obj\Debug\api.XML para una compilación de
depuración.

El generador de enlaces usará el archivo API. XML como guía para generar las clases de contenedor C#
necesarias. El contenido de este archivo XML es una variación del formato de proyecto de código abierto de
Android de Google. El siguiente fragmento de código es un ejemplo del contenido de API. XML:

<api>
<package name="android">
<class abstract="false" deprecated="not deprecated" extends="java.lang.Object"
extends-generic-aware="java.lang.Object"
final="true"
name="Manifest"
static="false"
visibility="public">
<constructor deprecated="not deprecated" final="false"
name="Manifest" static="false" type="android.Manifest"
visibility="public">
</constructor>
</class>
...
</api>
En este ejemplo, API. XML declara una clase en el android paquete denominado Manifest que extiende el
java.lang.Object .

En muchos casos, la asistencia humana es necesaria para que la API de Java sienta más ".NET como" o para
corregir los problemas que impiden la compilación del ensamblado de enlace. Por ejemplo, puede ser necesario
cambiar los nombres de los paquetes Java a espacios de nombres .NET, cambiar el nombre de una clase o
cambiar el tipo de valor devuelto de un método.
Estos cambios no se logran mediante la modificación de API. XML directamente. En su lugar, los cambios se
registran en archivos XML especiales proporcionados por la plantilla biblioteca de enlaces de Java. Al compilar el
ensamblado de enlace de Xamarin. Android, estos archivos de asignación influirán en el generador de enlaces al
crear el ensamblado de enlace.
Estos archivos de asignación XML se pueden encontrar en la carpeta Transformations del proyecto:
Metadata. XML – permite realizar cambios en la API final, como cambiar el espacio de nombres del
enlace generado.
EnumFields. XML – contiene la asignación entre las int constantes de Java C# enums y.
Enummethods (. XML – permite cambiar los parámetros de método y los tipos int de valor devueltos
de las constantes de Java a C# enums .

El archivo Metadata. XML es la importación más importante de estos archivos, ya que permite cambios
generales en el enlace, como:
Cambiar el nombre de los espacios de nombres, clases, métodos o campos para seguir las convenciones de
.NET.
Quitar espacios de nombres, clases, métodos o campos que no son necesarios.
Mover clases a distintos espacios de nombres.
Agregar clases de soporte adicionales para hacer que el diseño del enlace siga los patrones de .NET
Framework.
Permite pasar a analizar Metadata. XML con más detalle.

Metadata. XML (archivo de transformación)


Como ya hemos aprendido, el generador de enlaces usa el archivo Metadata. XML para influir en la creación del
ensamblado de enlace. El formato de metadatos usa la sintaxis de XPath y es casi idéntico a los metadatos de
GAPI descritos en la guía de metadatos de GAPI . Esta implementación es casi una implementación completa de
XPath 1,0 y, por lo tanto, admite elementos del estándar 1,0. Este archivo es un eficaz mecanismo basado en
XPath para cambiar, agregar, ocultar o quitar cualquier elemento o atributo en el archivo de la API. Todos los
elementos de regla de la especificación de metadatos incluyen un atributo de ruta de acceso para identificar el
nodo al que se aplicará la regla. Las reglas se aplican en el orden siguiente:
agregar nodo – Anexa un nodo secundario al nodo especificado por el atributo de ruta de acceso.
ATTR – Establece el valor de un atributo del elemento especificado por el atributo de ruta de acceso.
quitar nodo – Quita los nodos que coinciden con un XPath especificado.
El siguiente es un ejemplo de un archivo Metadata. XML :
<metadata>
<!-- Normalize the namespace for .NET -->
<attr path="/api/package[@name='com.evernote.android.job']"
name="managedName">Evernote.AndroidJob</attr>

<!-- Don't need these packages for the Xamarin binding/public API -->
<remove-node path="/api/package[@name='com.evernote.android.job.v14']" />
<remove-node path="/api/package[@name='com.evernote.android.job.v21']" />

<!-- Change a parameter name from the generic p0 to a more meaningful one. -->
<attr
path="/api/package[@name='com.evernote.android.job']/class[@name='JobManager']/method[@name='forceApi']/param
eter[@name='p0']"
name="name">api</attr>
</metadata>

A continuación se enumeran algunos de los elementos XPath más usados para las API de Java:
interface – Se usa para buscar una interfaz de Java. por ejemplo,. /interface[@name='AuthListener']

class – Se utiliza para buscar una clase. por ejemplo,. /class[@name='MapView']

method – Se usa para buscar un método en una clase o interfaz de Java. por ejemplo,.
/class[@name='MapView']/method[@name='setTitleSource']

parameter – Identifique un parámetro para un método. ej. /parameter[@name='p0']


Agregar tipos
El add-node elemento le indicará al proyecto de enlace de Xamarin. Android que agregue una nueva clase
contenedora a API. XML. Por ejemplo, el siguiente fragmento de código dirigirá el generador de enlace para
crear una clase con un constructor y un campo único:

<add-node path="/api/package[@name='org.alljoyn.bus']">
<class abstract="false" deprecated="not deprecated" final="false" name="AuthListener.AuthRequest"
static="true" visibility="public" extends="java.lang.Object">
<constructor deprecated="not deprecated" final="false" name="AuthListener.AuthRequest" static="false"
type="org.alljoyn.bus.AuthListener.AuthRequest" visibility="public" />
<field name="p0" type="org.alljoyn.bus.AuthListener.Credentials" />
</class>
</add-node>

Quitar tipos
Es posible indicar al generador de enlaces de Xamarin. Android que ignore un tipo de Java y que no lo enlace.
Esto se hace agregando un remove-node elemento XML al archivo Metadata. XML :

<remove-node path="/api/package[@name='{package_name}']/class[@name='{name}']" />

Cambiar el nombre de los miembros


No es posible cambiar el nombre de los miembros editando directamente el archivo API. XML porque Xamarin.
Android requiere los nombres de la interfaz nativa de Java (JNI) original. Por lo tanto //class/@name , no se
puede modificar el atributo; si es, el enlace no funcionará.
Considere el caso en el que queremos cambiar el nombre de un android.Manifest tipo. Para lograrlo, es posible
que intente editar directamente API. XML y cambiar el nombre de la clase de la manera siguiente:
<attr path="/api/package[@name='android']/class[@name='Manifest']"
name="name">NewName</attr>

Esto hará que el generador de enlaces cree el código siguiente C# para la clase contenedora:

[Register ("android/NewName")]
public class NewName : Java.Lang.Object { ... }

Observe que se ha cambiado el nombre de la NewName clase contenedora a, mientras que el Manifest tipo de Java
original sigue siendo. Ya no es posible que la clase de enlace de Xamarin. Android tenga acceso a cualquier
android.Manifest método de; la clase contenedora se enlaza a un tipo de Java inexistente.

Para cambiar correctamente el nombre administrado de un tipo ajustado (o método), es necesario establecer el
managedName atributo como se muestra en este ejemplo:

<attr path="/api/package[@name='android']/class[@name='Manifest']"
name="managedName">NewName</attr>

Cambiar el EventArg nombre de clases contenedoras


Cuando el generador de enlaces de Xamarin. Android onXXX identifica un método de establecedor para un tipo
C# de agente EventArgs de escucha, se generará un evento y una subclase para admitir una API de .net
aromatizada para el patrón de agente de escucha basado en Java. Como ejemplo, considere la clase y el método
de Java siguientes:

com.someapp.android.mpa.guidance.NavigationManager.on2DSignNextManuever(NextManueverListener listener);

Xamarin. Android quitará el prefijo on del método setter y, en su lugar, usará 2DSignNextManuever como base
para el nombre EventArgs de la subclase. La subclase se denominará algo similar a:

NavigationManager.2DSignNextManueverEventArgs

No es un nombre de C# clase válido. Para corregir este problema, el autor del enlace debe usar argsType el
atributo y proporcionar un C# nombre válido para EventArgs la subclase:

<attr path="/api/package[@name='com.someapp.android.mpa.guidance']/
interface[@name='NavigationManager.Listener']/
method[@name='on2DSignNextManeuver']"
name="argsType">NavigationManager.TwoDSignNextManueverEventArgs</attr>

Atributos admitidos
En las secciones siguientes se describen algunos de los atributos para transformar las API de Java.
argsType
Este atributo se coloca en métodos de establecedor para EventArg asignar un nombre a la subclase que se
generará para admitir agentes de escucha de Java. Esto se describe con más detalle a continuación en la sección
cambiar el nombre de las clases de contenedor de EventArg más adelante en esta guía.
eventName
Especifica un nombre para un evento. Si está vacío, impide la generación de eventos. Esto se describe con más
detalle en el título sección cambiar el nombre de las clases contenedoras de EventArg.
managedName
Se utiliza para cambiar el nombre de un paquete, una clase, un método o un parámetro. Por ejemplo, para
cambiar el nombre de la clase MyClass Java NewClassName a:

<attr path="/api/package[@name='com.my.application']/class[@name='MyClass']"
name="managedName">NewClassName</attr>

En el ejemplo siguiente se muestra una expresión XPath para cambiar el nombre java.lang.object.toString del
Java.Lang.Object.NewManagedName método a:

<attr path="/api/package[@name='java.lang']/class[@name='Object']/method[@name='toString']"
name="managedName">NewMethodName</attr>

managedType
managedType se utiliza para cambiar el tipo de valor devuelto de un método. En algunas situaciones, el generador
de enlaces infiere incorrectamente el tipo de valor devuelto de un método Java, lo que producirá un error en
tiempo de compilación. Una posible solución en esta situación es cambiar el tipo de valor devuelto del método.
Por ejemplo, el generador de enlaces considera que el método de.neom.neoreadersdk.resolution.compareTo() Java
debe int devolver, lo que genera el error CS0535 del mensaje de error: Resguardo. Neom. Neoreadersdk.
Resolution ' no implementa el miembro de interfaz ' Java. lang. IComparable. CompareTo (Java. lang.
Object) '. El siguiente fragmento de código muestra cómo cambiar el tipo de parámetro del C# método generado
de DE.Neom.Neoreadersdk.Resolution un a Java.Lang.Object un:

<attr path="/api/package[@name='de.neom.neoreadersdk']/
class[@name='Resolution']/
method[@name='compareTo' and count(parameter)=1 and
parameter[1][@type='de.neom.neoreadersdk.Resolution']]/
parameter[1]" name="managedType">Java.Lang.Object</attr>

managedReturn
Cambia el tipo de valor devuelto de un método. Esto no cambia el atributo Return (dado que los cambios en los
atributos devueltos pueden dar lugar a cambios incompatibles en la firma JNI). En el ejemplo siguiente, el tipo de
append valor devuelto del método se cambia de SpannableStringBuilder a IAppendable ( C# Recuerde que no
admite los tipos de valor devuelto covariante):

<attr path="/api/package[@name='android.text']/
class[@name='SpannableStringBuilder']/
method[@name='append']"
name="managedReturn">Java.Lang.IAppendable</attr>

ofuscados
Las herramientas que ofuscan las bibliotecas de Java pueden interferir con el generador de enlaces de Xamarin.
Android C# y su capacidad de generar clases contenedoras. Las características de las clases ofuscadas incluyen:
El nombre de clase incluye $ una clase, es decir, una $.
El nombre de clase está totalmente comprometido por caracteres en minúsculas, es decir, a.
Este fragmento de código es un ejemplo de cómo generar un tipo "no ofuscado C# ":

<attr path="/api/package[@name='{package_name}']/class[@name='{name}']"
name="obfuscated">false</attr>
propertyName
Este atributo se puede utilizar para cambiar el nombre de una propiedad administrada.
Un caso especializado de uso propertyName implica la situación en la que una clase de Java solo tiene un método
de captador para un campo. En esta situación, el generador de enlaces desearía crear una propiedad de solo
escritura, algo que no se recomienda en .NET. En el fragmento de código siguiente se muestra cómo "quitar" las
propiedades propertyName de .net estableciendo en una cadena vacía:

<attr
path="/api/package[@name='org.java_websocket.handshake']/class[@name='HandshakeImpl1Client']/method[@name='se
tResourceDescriptor'
and count(parameter)=1
and parameter[1][@type='java.lang.String']]"
name="propertyName"></attr>
<attr
path="/api/package[@name='org.java_websocket.handshake']/class[@name='HandshakeImpl1Client']/method[@name='ge
tResourceDescriptor'
and count(parameter)=0]"
name="propertyName"></attr>

Tenga en cuenta que el generador de enlaces todavía creará los métodos Setter y getter.
sender
Especifica qué parámetro de un método debe ser el sender parámetro cuando el método se asigna a un evento.
El valor puede ser true o false . Por ejemplo:

<attr path="/api/package[@name='android.app']/
interface[@name='TimePickerDialog.OnTimeSetListener']/
method[@name='onTimeSet']/
parameter[@name='view']"
name="sender">true</ attr>

visibilidad
Este atributo se usa para cambiar la visibilidad de una clase, método o propiedad. Por ejemplo, puede que sea
necesario promocionar un protected método de Java para que sea el C# contenedor public correspondiente:

<!-- Change the visibility of a class -->


<attr path="/api/package[@name='namespace']/class[@name='ClassName']" name="visibility">public</attr>

<!-- Change the visibility of a method -->


<attr path="/api/package[@name='namespace']/class[@name='ClassName']/method[@name='MethodName']"
name="visibility">public</attr>

EnumFields. XML y Enummethods (. XML


Hay casos en los que las bibliotecas de Android usan constantes de tipo entero para representar los Estados que
se pasan a las propiedades o los métodos de las bibliotecas. En muchos casos, resulta útil enlazar estas constantes
de tipo entero a las enumeraciones en C#. Para facilitar esta asignación, use los archivos EnumFields. XML y
enummethods (. XML en el proyecto de enlace.
Definir una enumeración mediante EnumFields. XML
El archivo EnumFields. XML contiene la asignación entre las int constantes de Java C# enums y. Vamos a crear
el ejemplo siguiente de una C# enumeración que se crea para un int conjunto de constantes:
<mapping jni-class="com/skobbler/ngx/map/realreach/SKRealReachSettings" clr-enum-
type="Skobbler.Ngx.Map.RealReach.SKMeasurementUnit">
<field jni-name="UNIT_SECOND" clr-name="Second" value="0" />
<field jni-name="UNIT_METER" clr-name="Meter" value="1" />
<field jni-name="UNIT_MILIWATT_HOURS" clr-name="MilliwattHour" value="2" />
</mapping>

Aquí SKRealReachSettings hemos tomado la clase de Java y hemos definido una C# enumeración llamada
SKMeasurementUnit en el espacio de nombres. Skobbler.Ngx.Map.RealReach Las field entradas definen el nombre
de la constante de Java ( UNIT_SECOND ejemplo), el nombre de la entrada de enumeración (ejemplo Second ) y el
valor entero representado por ambas entidades ( 0 ejemplo).
Definir métodos de captador/establecedor mediante Enummethods (. XML
El archivo enummethods (. XML permite cambiar los parámetros de método y los tipos int de valor devueltos
de las constantes de Java a. C# enums En otras palabras, asigna la lectura y escritura C# de enumeraciones
(definidas en el archivo EnumFields. XML ) a los métodos int y get set constantes de Java.
Dada la SKRealReachSettings enumeración definida anteriormente, el siguiente archivo enummethods (. XML
definiría el captador/establecedor para esta enumeración:

<mapping jni-class="com/skobbler/ngx/map/realreach/SKRealReachSettings">
<method jni-name="getMeasurementUnit" parameter="return" clr-enum-
type="Skobbler.Ngx.Map.RealReach.SKMeasurementUnit" />
<method jni-name="setMeasurementUnit" parameter="measurementUnit" clr-enum-
type="Skobbler.Ngx.Map.RealReach.SKMeasurementUnit" />
</mapping>

La primera method línea asigna el valor devuelto del método getMeasurementUnit Java a la SKMeasurementUnit
enumeración. La segunda method línea asigna el primer parámetro setMeasurementUnit de a la misma
enumeración.
Con todos estos cambios en su lugar, puede usar el código siguiente en Xamarin. Android para establecer
MeasurementUnit :

realReachSettings.MeasurementUnit = SKMeasurementUnit.Second;

Resumen
En este artículo se describe cómo Xamarin. Android usa metadatos para transformar una definición de API desde
el formato de Google AOSP. Después de cubrir los cambios que son posibles mediante Metadata. XML, examinó
las limitaciones que se producen al cambiar el nombre de los miembros y se presenta la lista de atributos XML
admitidos, que describen Cuándo debe usarse cada atributo.

Vínculos relacionados
Trabajar con JNI
Enlace de una biblioteca Java
Metadatos de GAPI
Nomenclatura de parámetros con javadoc
16/08/2019 • 2 minutes to read • Edit Online

En este artículo se explica cómo recuperar nombres de parámetros en un proyecto de enlace de Java mediante el
uso de Javadoc generado a partir del proyecto de Java.

Información general
Al enlazar una biblioteca de Java existente, se pierden algunos metadatos sobre la API enlazada. En particular, los
nombres de los parámetros de los métodos. Los nombres de parámetro aparecerán p0 como p1 ,, etc. Esto se
debe a que .class los archivos Java no conservan los nombres de parámetro que se usaron en el código fuente
de Java.
Un proyecto de enlace de Java de Xamarin. Android puede proporcionar los nombres de parámetro si tiene acceso
al HTML Javadoc desde la biblioteca original.

Integración de Javadoc HTML en un proyecto de enlace de Java


La integración de Javadoc HTML en un proyecto de enlace de Java es un proceso manual que consta de los pasos
siguientes:
1. Descargar Javadoc para la biblioteca
2. Edite .csproj el archivo y agregue <JavaDocPaths> una propiedad:
3. Limpiar y volver a generar el proyecto
Una vez hecho esto, los nombres de parámetros de Java originales deben estar presentes en las API enlazadas por
un proyecto de enlace de Java.

NOTE
Hay una gran cantidad de varianza en la salida de JavaDoc. El. La cadena de herramientas de enlace JAR no admite todas las
permutaciones posibles y, por lo tanto, es posible que algún parámetro no tenga un nombre correcto.

Resumen
En este artículo se explica cómo usar Javadoc en un proyecto de enlace de Java para proporcionar los nombres de
parámetro de significado para las API enlazadas.
Solución de problemas de enlaces
16/08/2019 • 19 minutes to read • Edit Online

En este artículo se resumen los errores comunes de servidor que pueden producirse al generar enlaces, junto con
las posibles causas y las formas sugeridas de resolverlos.

Información general
Enlazar una biblioteca de Android (un archivo . AAR o . jar) rara vez es un suerte sencillo; normalmente requiere
un esfuerzo adicional para mitigar los problemas derivados de las diferencias entre Java y .NET. Estos problemas
impedirán que Xamarin. Android enlace la biblioteca de Android y se presente como mensajes de error en el
registro de compilación. En esta guía se ofrecen algunas sugerencias para solucionar los problemas, se enumeran
algunos de los problemas o escenarios más comunes y se proporcionan posibles soluciones para enlazar
correctamente la biblioteca de Android.
Al enlazar una biblioteca de Android existente, es necesario tener en cuenta los puntos siguientes:
Dependencias externas de la biblioteca Todas las dependencias de Java que requiere la biblioteca de
Android deben incluirse en el proyecto de Xamarin. Android como ReferenceJar o como
EmbeddedReferenceJar. –
El nivel de API de Android que es destino de la biblioteca de Android – No es posible "degradar" el
nivel de API de Android; Asegúrese de que el proyecto de enlace de Xamarin. Android tenga como destino
el mismo nivel de API (o superior) que la biblioteca de Android.
La versión del JDK de Android que se usó para empaquetar la biblioteca de Android – Pueden
producirse errores de enlace si la biblioteca de Android se compiló con una versión de JDK diferente de la
que usa Xamarin. Android. Si es posible, vuelva a compilar la biblioteca de Android con la misma versión
del JDK que usa la instalación de Xamarin. Android.
El primer paso para la solución de problemas con el enlace de una biblioteca de Xamarin. Android es habilitar la
salida de MSBuild de diagnóstico. Después de habilitar la salida de diagnóstico, vuelva a compilar el proyecto de
enlace de Xamarin. Android y examine el registro de compilación para buscar pistas sobre cuál es la causa del
problema.
También puede resultar útil descompilar la biblioteca de Android y examinar los tipos y métodos que Xamarin.
Android está intentando enlazar. Esto se explica con más detalle más adelante en esta guía.

Descompilación de una biblioteca de Android


Inspeccionar las clases y los métodos de las clases de Java puede proporcionar información valiosa que le ayudará
en el enlace de una biblioteca. JD -GUI es una utilidad gráfica que puede mostrar el código fuente de Java de los
archivos de clase contenidos en un archivo jar. Se puede ejecutar como una aplicación independiente o como un
complemento para IntelliJ o Eclipse.
Para descompilar una biblioteca de Android, abra el . Archivo JAR con la descompilador de Java. Si la biblioteca
es una . Archivo AAR , es necesario extraer el archivo classes . jar del archivo de almacenamiento. A continuación
se muestra una captura de pantalla de ejemplo del uso de JD -GUI para analizar el archivo jar de Picasso :
Una vez que haya descompilado la biblioteca de Android, examine el código fuente. En términos generales,
busque:
Clases que tienen características de ofuscación – Las características de las clases ofuscadas incluyen:
El nombre de clase incluye $ una clase, es decir, una $.
El nombre de clase está totalmente comprometido por caracteres en minúsculas, es decir, a.
las instrucciones – de las bibliotecas sin referencia identifican la biblioteca sin referencia y agregan
esas dependencias al proyecto de enlace de Xamarin. Android con una acción de compilación de
ReferenceJar o import EmbedddedReferenceJar.

NOTE
La descompilación de una biblioteca de Java puede estar prohibida o sujeta a restricciones legales basadas en leyes locales o
en la licencia en la que se publicó la biblioteca de Java. Si es necesario, dé de alta los servicios de un profesional legal antes de
intentar descompilar una biblioteca de Java e inspeccionar el código fuente.

Inspeccione la API. LENGUAJE


Como parte de la compilación de un proyecto de enlace, Xamarin. Android generará un nombre de archivo XML
obj/Debug/API. XML:
Este archivo proporciona una lista de todas las API de Java que está intentando enlazar Xamarin. Android. El
contenido de este archivo puede ayudar a identificar los tipos o métodos que faltan, el enlace duplicado. Aunque la
inspección de este archivo es tediosa y lenta, puede proporcionar pistas sobre lo que puede estar causando
problemas de enlace. Por ejemplo, API. XML podría revelar que una propiedad devuelve un tipo inadecuado o
que hay dos tipos que comparten el mismo nombre administrado.

Problemas conocidos
En esta sección se enumeran algunos de los mensajes de error comunes o síntomas que se producen al intentar
enlazar una biblioteca de Android.
Problema: Versión de Java no coincidente
A veces, los tipos no se generan o se pueden producir bloqueos inesperados porque se usa una versión más
reciente o anterior de Java en comparación con la compilación de la biblioteca. Vuelva a compilar la biblioteca de
Android con la misma versión del JDK que usa el proyecto de Xamarin. Android.
Problema: Se requiere al menos una biblioteca de Java
Recibe el error "se requiere al menos una biblioteca de Java", aunque. Se ha agregado el archivo JAR.
Causas posibles:
Asegúrese de que la acción de compilación está EmbeddedJar establecida en. Dado que hay varias acciones de
compilación para. Archivos JAR ( InputJar como EmbeddedJar ReferenceJar , y EmbeddedReferenceJar ), el
generador de enlaces no puede adivinar automáticamente cuál debe usarse de forma predeterminada. Para
obtener más información sobre las acciones de compilación, vea acciones de compilación.
Problema: Las herramientas de enlace no pueden cargar. Biblioteca JAR
El generador de la biblioteca de enlaces no puede cargar. Biblioteca JAR.
Causas posibles
Existen. Las bibliotecas de JAR que usan la ofuscación de código (a través de herramientas como ProGuard) no se
pueden cargar con las herramientas de Java. Dado que nuestra herramienta hace uso de la reflexión de Java y la
biblioteca de ingeniería de código de bytes ASM, esas herramientas dependientes pueden rechazar las bibliotecas
ofuscadas, mientras que las herramientas de tiempo de ejecución de Android pueden pasar. La solución alternativa
para esto es enlazar a mano estas bibliotecas en lugar de usar el generador de enlaces.
Problema: Faltan C# tipos en la salida generada.
Binding . dll se compila pero se pierden algunos tipos de Java o el origen C# generado no se compila debido a un
error que indica que faltan tipos.
Causas posibles:
Este error puede producirse por varias razones, como se indica a continuación:
La biblioteca que se está enlazando puede hacer referencia a una segunda biblioteca de Java. Si la API
pública de la biblioteca enlazada usa tipos de la segunda biblioteca, también debe hacer referencia a un
enlace administrado para la segunda biblioteca.
Es posible que se haya insertado una biblioteca debido a la reflexión de Java, similar a la causa del error de
carga de la biblioteca anterior, lo que provocaría la carga inesperada de metadatos. Actualmente, las
herramientas de Xamarin. Android no pueden resolver esta situación. En tal caso, la biblioteca se debe
enlazar manualmente.
Error en el tiempo de ejecución de .NET 4,0 que no pudo cargar los ensamblados cuando debería tener. Este
problema se ha corregido en el tiempo de ejecución de .NET 4,5.
Java permite derivar una clase pública de una clase no pública, pero esto no se admite en .NET. Dado que el
generador de enlaces no genera enlaces para clases no públicas, las clases derivadas como estas no se
pueden generar correctamente. Para corregirlo, quite la entrada de metadatos para las clases derivadas
mediante el uso de Remove-node en Metadata. XMLo corrija los metadatos que hacen que la clase no
pública sea pública. Aunque la última solución creará el enlace para que se C# compile el origen, no se debe
usar la clase no pública.
Por ejemplo:

<attr path="/api/package[@name='com.some.package']/class[@name='SomeClass']"
name="visibility">public</attr>

Las herramientas que ofuscan las bibliotecas de Java pueden interferir con el generador de enlaces de
Xamarin. Android C# y su capacidad de generar clases contenedoras. En el fragmento de código siguiente
se muestra cómo actualizar Metadata. XML para no ofuscar un nombre de clase:

<attr path="/api/package[@name='{package_name}']/class[@name='{name}']"
name="obfuscated">false</attr>

Problema: El C# origen generado no se compila debido a un error de coincidencia de tipos de parámetro


El origen C# generado no se compila. Los tipos de parámetros del método invalidado no coinciden.
Causas posibles:
Xamarin. Android incluye una variedad de campos de Java que se asignan a las enumeraciones en los C# enlaces.
Pueden provocar incompatibilidades de tipos en los enlaces generados. Para resolver esto, las signaturas de
método creadas desde el generador de enlaces deben modificarse para usar las enumeraciones. Para obtener más
información, vea corregir enumeraciones.
Problema: NoClassDefFoundError en empaquetado
java.lang.NoClassDefFoundError se produce en el paso de empaquetado.

Causas posibles:
La razón más probable de este error es que es necesario agregar una biblioteca Java obligatoria al proyecto de
aplicación ( . csproj). . Los archivos JAR no se resuelven automáticamente. Un enlace de la biblioteca de Java no se
genera siempre en un ensamblado de usuario que no existe en el emulador o dispositivo de destino (como Google
Maps Maps. jar). Este no es el caso de la compatibilidad con proyectos de biblioteca Android, como la biblioteca.
JAR se incrusta en el archivo dll de biblioteca. Por ejemplo: Error 4288
Problema: Tipos de EventArgs personalizados duplicados
Se produce un error en la compilación debido a tipos EventArgs personalizados duplicados. Se produce un error
similar al siguiente:

error CS0102: The type `Com.Google.Ads.Mediation.DismissScreenEventArgs' already contains a definition for


`p0'
Causas posibles:
Esto se debe a que hay algún conflicto entre los tipos de eventos que proceden de más de un tipo de "agente de
escucha" de la interfaz que comparte métodos que tienen nombres idénticos. Por ejemplo, si hay dos interfaces
Java como se muestra en el ejemplo siguiente, el generador crea DismissScreenEventArgs MediationBannerListener
para y MediationInterstitialListener , lo que produce el error.

// Java:
public interface MediationBannerListener {
void onDismissScreen(MediationBannerAdapter p0);
}
public interface MediationInterstitialListener {
void onDismissScreen(MediationInterstitialAdapter p0);
}

Esto es así por diseño para evitar los nombres largos en los tipos de argumento de evento. Para evitar estos
conflictos, se requiere una transformación de metadatos. Edite Transforms\Metadata.XML y agregue argsType
un atributo en cualquiera de las interfaces (o en el método de interfaz):

<attr path="/api/package[@name='com.google.ads.mediation']/
interface[@name='MediationBannerListener']/method[@name='onDismissScreen']"
name="argsType">BannerDismissScreenEventArgs</attr>

<attr path="/api/package[@name='com.google.ads.mediation']/
interface[@name='MediationInterstitialListener']/method[@name='onDismissScreen']"
name="argsType">IntersitionalDismissScreenEventArgs</attr>

<attr path="/api/package[@name='android.content']/
interface[@name='DialogInterface.OnClickListener']"
name="argsType">DialogClickEventArgs</attr>

Problema: La clase no implementa el método de interfaz


Se genera un mensaje de error que indica que una clase generada no implementa un método necesario para una
interfaz que implementa la clase generada. Sin embargo, si examina el código generado, puede ver que el método
está implementado.
Este es un ejemplo del error:

obj\Debug\generated\src\Oauth.Signpost.Basic.HttpURLConnectionRequestAdapter.cs(8,23):
error CS0738: 'Oauth.Signpost.Basic.HttpURLConnectionRequestAdapter' does not
implement interface member 'Oauth.Signpost.Http.IHttpRequest.Unwrap()'.
'Oauth.Signpost.Basic.HttpURLConnectionRequestAdapter.Unwrap()' cannot implement
'Oauth.Signpost.Http.IHttpRequest.Unwrap()' because it does not have the matching
return type of 'Java.Lang.Object'

Causas posibles:
Se trata de un problema que se produce al enlazar métodos de Java con tipos de valor devuelto covariante. En este
ejemplo, el método Oauth.Signpost.Http.IHttpRequest.UnWrap() debe devolver. Java.Lang.Object Sin embargo, el
Oauth.Signpost.Basic.HttpURLConnectionRequestAdapter.UnWrap() método tiene un tipo de HttpURLConnection valor
devuelto de. Hay dos maneras de corregir este problema:
Agregue una declaración de clase parcial HttpURLConnectionRequestAdapter para y implemente
IHttpRequest.Unwrap() explícitamente:
namespace Oauth.Signpost.Basic {
partial class HttpURLConnectionRequestAdapter {
Java.Lang.Object OauthSignpost.Http.IHttpRequest.Unwrap() {
return Unwrap();
}
}
}

Quite la covarianza del código generado C# . Esto implica agregar la siguiente transformación a
Transforms\Metadata.XML , lo que hará que C# el código generado tenga un tipo de Java.Lang.Object
valor devuelto de:

<attr

path="/api/package[@name='oauth.signpost.basic']/class[@name='HttpURLConnectionRequestAdapter']/method[
@name='unwrap']"
name="managedReturn">Java.Lang.Object
</attr>

Problema: Colisiones de nombres en clases o propiedades internas


Visibilidad en conflicto en los objetos heredados.
En Java, no es necesario que una clase derivada tenga la misma visibilidad que su elemento primario. Java solo lo
corregirá por usted. En C#, eso debe ser explícito, por lo que debe asegurarse de que todas las clases de la
jerarquía tengan la visibilidad adecuada. En el ejemplo siguiente se muestra cómo cambiar el nombre de un
com.evernote.android.job paquete Evernote.AndroidJob de Java de a:

<!-- Change the visibility of a class -->


<attr path="/api/package[@name='namespace']/class[@name='ClassName']" name="visibility">public</attr>

<!-- Change the visibility of a method -->


<attr path="/api/package[@name='namespace']/class[@name='ClassName']/method[@name='MethodName']"
name="visibility">public</attr>

Problema: A . por lo tanto , la biblioteca requerida por el enlace no se está cargando


Algunos proyectos de enlace también pueden depender de la funcionalidad de una biblioteca . Es posible que
Xamarin. Android no cargue automáticamente la biblioteca . so . Cuando se ejecuta el código de Java ajustado,
Xamarin. Android no realizará la llamada JNI y el mensaje de error Java. lang. UnsatisfiedLinkError: Método
nativo no encontrado: aparecerá en el logcat de salida de la aplicación.
La solución para esto es cargar manualmente la biblioteca . so con una llamada a
Java.Lang.JavaSystem.LoadLibrary . Por ejemplo, suponiendo que un proyecto de Xamarin. Android tiene
libpocketsphinx_jni de biblioteca compartida . por tanto , se incluye en el proyecto de enlace con una acción de
compilación de EmbeddedNativeLibrary, el siguiente fragmento de código (ejecutado antes de usar la biblioteca
compartida) cargará la biblioteca . so :

Java.Lang.JavaSystem.LoadLibrary("pocketsphinx_jni");

Resumen
En este artículo se enumeran los problemas comunes de solución de problemas asociados a los enlaces de Java y
se explica cómo resolverlos.
Vínculos relacionados
Proyectos de biblioteca
Trabajar con JNI
Habilitar salida de diagnóstico
Xamarin para desarrolladores de Android
JD -GUI
Uso de bibliotecas nativas
16/08/2019 • 3 minutes to read • Edit Online

Xamarin. Android admite el uso de bibliotecas nativas mediante el mecanismo estándar de PInvoke. También
puede agrupar bibliotecas nativas adicionales que no forman parte del sistema operativo en su. apk.
Para implementar una biblioteca nativa con una aplicación de Xamarin. Android, agregue el archivo binario de la
biblioteca al proyecto y establezca su acción de compilación en AndroidNativeLibrary.
Para implementar una biblioteca nativa con un proyecto de biblioteca de Xamarin. Android, agregue el archivo
binario de biblioteca al proyecto y establezca su acción de compilación en EmbeddedNativeLibrary.
Tenga en cuenta que, como Android admite varias interfaces binarias de aplicación (ABI), Xamarin. Android debe
saber para qué ABI se ha creado la biblioteca nativa. Hay dos maneras de hacerlo:
1. Ruta de acceso "sniffing"
2. Mediante el uso AndroidNativeLibrary/Abi de un elemento dentro del archivo de proyecto
Con el examen de la ruta de acceso, el nombre del directorio principal de la biblioteca nativa se utiliza para
especificar la ABI a la que se dirige la biblioteca. Por lo tanto, si lib/armeabi/libfoo.so agrega al proyecto, la ABI
se "examinará" como. armeabi
Como alternativa, puede editar el archivo de proyecto para especificar explícitamente la ABI que se va a usar:

<ItemGroup>
<AndroidNativeLibrary Include="path/to/libfoo.so">
<Abi>armeabi</Abi>
</AndroidNativeLibrary>
</ItemGroup>

Para obtener más información sobre el uso de bibliotecas nativas, consulte interoperabilidad con bibliotecas
nativas.

Depurar código nativo con Visual Studio


Si usa visual studio 2019 o Visual Studio 2017, no tiene que modificar los archivos de proyecto tal y como se ha
descrito anteriormente. Puede compilar y C++ depurar dentro de la solución de Xamarin. Android agregando
C++ una referencia de proyecto a un proyecto de biblioteca dinámica compartida (Android) .
Para depurar código nativo C++ en el proyecto, siga estos pasos:
1. Haga doble clic en propiedades del proyecto y seleccione la página Opciones de Android .
2. Desplácese hacia abajo hasta Opcionesde depuración.
3. En el menú desplegable del depurador, seleccione C++ (en lugar de .net predeterminado (Xamarin) ).
Los desarrolladores C++ C++ de Visual Studio pueden ver el ejemplo SanAngeles_NativeDebug para probar la
depuración desde visual Studio 2019 o Visual Studio 2017 con Xamarin. y consulte nuestra entrada de blog para
obtener más información.

Vínculos relacionados
SanAngeles_NativeDebug (ejemplo)
Desarrollo de aplicaciones nativas de Xamarin Android
Una introducción a Renderscript
27/07/2019 • 16 minutes to read • Edit Online

En esta guía se presenta Renderscript y se explica cómo usar las API intrínsecas de Renderscript en una aplicación
de Xamarin. Android que tiene como destino el nivel de API 17 o superior.

Información general
Renderscript es un marco de programación creado por Google con el fin de mejorar el rendimiento de las
aplicaciones de Android que requieren recursos de cálculo extensivos. Se trata de una API de bajo nivel y alto
rendimiento basada en C99. Dado que se trata de una API de bajo nivel que se ejecutará en CPU, GPU o DSP,
Renderscript es adecuado para aplicaciones Android que pueden necesitar realizar cualquiera de las siguientes
acciones:
Gráficos
Procesamiento de imágenes
Cifrado
Procesamiento de señal
Rutinas matemáticas
Renderscript usará y compilará los scripts en el código de LLVM bytes que se incluye en el APK. clang Cuando la
aplicación se ejecuta por primera vez, el código de bytes de LLVM se compilará en el código máquina para los
procesadores del dispositivo. Esta arquitectura permite a una aplicación de Android aprovechar las ventajas del
código máquina sin que los desarrolladores tengan que escribirla para cada procesador en el propio dispositivo.
Hay dos componentes en una rutina Renderscript:
1. El tiempo de ejecución de Renderscript – Se trata de las API nativas que son responsables de ejecutar
Renderscript. Esto incluye cualquier Renderscripts escrito para la aplicación.
2. Contenedores administrados desde el marco de trabajo de Android – Clases administradas que
permiten a una aplicación Android controlar e interactuar con el tiempo de ejecución y los scripts de
Renderscript. Además de las clases proporcionadas para controlar el tiempo de ejecución de Renderscript, la
cadena de herramientas de Android examinará el código fuente de Renderscript y generará clases
contenedoras administradas para que las use la aplicación de Android.
En el diagrama siguiente se muestra cómo se relacionan estos componentes:
Hay tres conceptos importantes para el uso de Renderscripts en una aplicación de Android:
1. Un contexto – Una API administrada proporcionada por el Android SDK que asigna recursos a
Renderscript y permite a la aplicación Android pasar y recibir datos de Renderscript.
2. Un kernel de proceso También conocido como kernel raíz o kernel, que es una rutina que realiza el trabajo.
– El kernel es muy similar a una función de C. se trata de una rutina pueden paralelizar que se ejecutará en
todos los datos de la memoria asignada.
3. Memoria asignada Los datos se pasan a y desde un kernel a través de una asignación. – Un kernel puede
tener una asignación de entrada o de salida.
El espacio de nombres Android. Renderscripts contiene las clases para interactuar con el tiempo de ejecución de
Renderscript. En concreto, la Renderscript clase administrará el ciclo de vida y los recursos del motor
Renderscript. La aplicación Android debe inicializar una o más Android.Renderscripts.Allocation los. Una
asignación es una API administrada que es responsable de la asignación y el acceso a la memoria que se comparte
entre la aplicación de Android y el tiempo de ejecución de Renderscript. Normalmente, se crea una asignación para
la entrada y, opcionalmente, se crea otra asignación que contiene la salida del kernel. El motor en tiempo de
ejecución de Renderscript y las clases contenedoras administradas asociadas administrarán el acceso a la memoria
mantenida por las asignaciones, no es necesario que un desarrollador de aplicaciones Android realice ningún
trabajo adicional.
Una asignación contendrá uno o varios elementos Android. Renderscripts. Elements. Los elementos son un tipo
especializado que describen los datos de cada asignación. Los tipos de elemento de la asignación de salida deben
coincidir con los tipos del elemento de entrada. Al ejecutar, una Renderscript iterará en cada elemento de la
asignación de entrada en paralelo y escribirá los resultados en la asignación de salida. Hay dos tipos de elementos:
tipo simple Conceptualmente, float es igual que un tipo de datos de C o char .–
tipo complejo Este tipo es similar a un C struct .–
El motor de Renderscript realizará una comprobación en tiempo de ejecución para asegurarse de que los
elementos de cada asignación son compatibles con lo que necesita el kernel. Si el tipo de datos de los elementos
de la asignación no coincide con el tipo de datos que el kernel espera, se producirá una excepción.
Todos los kernels de Renderscript se ajustarán mediante un tipo que sea un descendiente del
Android.Renderscripts.Script clase. La Script clase se usa para establecer los parámetros de un Renderscript,
establecer el Allocations apropiado y ejecutar Renderscript. Hay dos Script subclases en el Android SDK:
Android.Renderscripts.ScriptIntrinsic Algunas de las tareas más comunes de Renderscript se incluyen en
el Android SDK y son accesibles mediante una subclase de la clase ScriptIntrinsic. – No es necesario que un
desarrollador realice pasos adicionales para usar estos scripts en su aplicación, ya que ya se proporcionan.
ScriptC_XXXXX También conocido como scripts de usuario, son scripts escritos por desarrolladores y
empaquetados en el APK. – En tiempo de compilación, la cadena de herramientas de Android generará
clases contenedoras administradas que permitirán usar los scripts en la aplicación de Android. El nombre de
estas clases generadas es el nombre del archivo Renderscript, con ScriptC_ el prefijo. La escritura e
incorporación de scripts de usuario no es compatible oficialmente con Xamarin. Android y más allá del
ámbito de esta guía.
De estos dos tipos, solo StringIntrinsic es compatible con Xamarin. Android. En esta guía se explica cómo usar
scripts intrínsecos en una aplicación de Xamarin. Android.

Requisitos
Esta guía está destinada a las aplicaciones de Xamarin. Android que tienen como destino el nivel de API 17 o
superior. El uso de scripts de usuario no se trata en esta guía.
La biblioteca de compatibilidad de Xamarin. Android V8 transporta las API de intrínsecas Renderscript para las
aplicaciones destinadas a versiones anteriores de la Android SDK. Agregar este paquete a un proyecto de Xamarin.
Android debe permitir que las aplicaciones destinadas a versiones anteriores de la Android SDK aprovechen los
scripts intrínsecos.

Usar Renderscripts intrínseco en Xamarin. Android


Los scripts intrínsecos son una excelente manera de realizar tareas informáticas intensivas con una cantidad
mínima de código adicional. Se han optimizado para ofrecer un rendimiento óptimo en una gran sección de
dispositivos cruzados. No es raro que un script intrínseco se ejecute 10 veces más rápido que el código
administrado y 2-3 veces después de una implementación personalizada de C. Muchos de los escenarios de
procesamiento típicos están incluidos en los scripts intrínsecos. Esta lista de los scripts intrínsecos describe los
scripts actuales de Xamarin. Android:
ScriptIntrinsic3DLUT – Convierte RGB en RGBA mediante una tabla de búsqueda 3D.
ScriptIntrinsicBLAS Provideshigh performance Renderscript API to Blas. – Los subprogramas de BLASs de
álgebra lineal básicos son rutinas que proporcionan los bloques de creación estándar para realizar
operaciones básicas de vector y matriz.
ScriptIntrinsicBlend – Combina dos asignaciones juntas.
ScriptIntrinsicBlur – Aplica un desenfoque gaussiano a una asignación.
ScriptIntrinsicColorMatrix – Aplica una matriz de colores a una asignación (es decir, cambiar los colores,
ajustar el matiz).
ScriptIntrinsicConvolve3x3 – Aplica una matriz de colores 3x3 a una asignación.
ScriptIntrinsicConvolve5x5 – Aplica una matriz de colores 5x5 a una asignación.
ScriptIntrinsicHistogram – Un filtro de histograma intrínseco.
ScriptIntrinsicLUT – Aplica una tabla de búsqueda por canal a un búfer.
ScriptIntrinsicResize – Script para realizar el ajuste de tamaño de una asignación de 2D.
ScriptIntrinsicYuvToRGB – Convierte un búfer YUV en RGB.
Consulte la documentación de la API para obtener más información sobre cada uno de los scripts intrínsecos.
A continuación se describen los pasos básicos para usar Renderscript en una aplicación de Android.
Crear un contexto de Renderscript – El Renderscript la clase es un contenedor administrado en torno al
contexto Renderscript y controlará la inicialización, la administración de recursos y la limpieza. El objeto
Renderscript se crea mediante el RenderScript.Create Factory Method, que toma un contexto de Android (como
una actividad) como parámetro. En la siguiente línea de código se muestra cómo inicializar el contexto
Renderscript:

Android.Renderscripts.RenderScript renderScript = RenderScript.Create(this);

Crear asignaciones Dependiendo del script intrínseco, puede ser necesario crear uno o dos Allocation . – El
Android.Renderscripts.Allocation la clase tiene varios métodos de generador para facilitar la creación de
instancias de una asignación para un intrínseco. Como ejemplo, el siguiente fragmento de código muestra cómo
crear una asignación para los mapas de bits.

Android.Graphics.Bitmap originalBitmap;
Android.Renderscripts.Allocation inputAllocation = Allocation.CreateFromBitmap(renderScript,
originalBitmap,
Allocation.MipmapControl.MipmapFull,
AllocationUsage.Script);

A menudo, será necesario crear un Allocation para contener los datos de salida de un script. En el siguiente
fragmento de código se muestra Allocation.CreateTyped cómo usar el ayudante para crear instancias Allocation
de un segundo que tiene el mismo tipo que el original:

Android.Renderscripts.Allocation outputAllocation = Allocation.CreateTyped(renderScript,


inputAllocation.Type);

Crear una instancia del contenedor de script Cada una de las clases contenedoras de scripts intrínsecos debe
tener métodos Create auxiliares (normalmente denominados) para crear instancias de un objeto contenedor para
ese script. – El siguiente fragmento de código es un ejemplo de cómo crear una instancia ScriptIntrinsicBlur de
un objeto Blur. El Element.U8_4 método auxiliar creará un elemento que describe un tipo de datos de 4 campos de
valores enteros sin signo de 8 bits, que es adecuado para contener los datos de un Bitmap objeto:

Android.Renderscripts.ScriptIntrinsicBlur blurScript = ScriptIntrinsicBlur.Create(renderScript,


Element.U8_4(renderScript));

Asignar asignaciones, establecer parámetros, & ejecutar script La clase proporciona un ForEach método
para ejecutar realmente Renderscript. Script – Este método recorre en iteración Element cada Allocation en la
que contiene los datos de entrada. En algunos casos, puede ser necesario proporcionar un Allocation que
contiene la salida. ForEach sobrescribirá el contenido de la asignación de salida. Para continuar con los fragmentos
de código de los pasos anteriores, este ejemplo muestra cómo asignar una asignación de entrada, establecer un
parámetro y, por último, ejecutar el script (copiando los resultados en la asignación de salida):

blurScript.SetInput(inputAllocation);
blurScript.SetRadius(25); // Set a pamaeter
blurScript.ForEach(outputAllocation);

Es posible que desee consultar la receta desenfocar una imagen con Renderscript , que es un ejemplo completo de
cómo usar un script intrínseco en Xamarin. Android.

Resumen
En esta guía se ha introducido Renderscript y cómo usarlo en una aplicación de Xamarin. Android. Describe
brevemente qué es Renderscript y cómo funciona en una aplicación Android. Se describen algunos de los
componentes clave de Renderscript y la diferencia entre los scripts de usuario y los scripts de intrínsecas. Por
último, en esta guía se describen los pasos para usar un script intrínseco en una aplicación de Xamarin. Android.

Vínculos relacionados
Espacio de nombres Android. Renderscripts
Desenfoque de una imagen con Renderscript
Renderscript
Tutorial: Introducción con Renderscript
Xamarin.Essentials
11/07/2019 • 4 minutes to read • Edit Online

Xamarin.Essentials brinda a los desarrolladores API multiplataformas para sus aplicaciones móviles.
Android, iOS y UWP ofrecen API de plataforma y sistema operativo únicas a las que los desarrolladores pueden
tener acceso desde C# mediante Xamarin. Xamarin.Essentials brinda una API multiplataforma única que funciona
con cualquier aplicación Xamarin.Forms, Android, iOS o UWP accesible desde código compartido, sin importar
cómo se creó la interfaz de usuario.

Introducción a Xamarin.Essentials
Siga la guía de introducción para instalar el paquete NuGet de Xamarin.Essentials a los proyectos nuevos o
existentes de Xamarin.Forms, Android, iOS o UWP.

Guías de características
Siga las guías para integrar estas características de Xamarin.Essentials en las aplicaciones:
Accelerometer: recupere los datos de aceleración del dispositivo en un espacio tridimensional.
App Information: conozca información sobre la aplicación.
Barometer: supervise los cambios de presión con el barómetro.
Battery: detecte fácilmente el nivel, origen y estado de la batería.
Clipboard: establezca o lea fácil y rápidamente texto en el Portapapeles.
Color Converters: métodos del asistente para System.Drawing.Color.
Compass: supervise los cambios en la brújula.
Connectivity: compruebe el estado de la conectividad y detecte cambios.
Detect Shake: detecte movimientos de agitación en el dispositivo.
Device Display Information: obtenga la orientación y las métricas de la pantalla del dispositivo.
Device Information: conozca información sobre el dispositivo de manera sencilla.
Email: envíe fácilmente mensajes de correo electrónico.
File System Helpers: guarde fácilmente archivos en los datos de la aplicación.
Flashlight: una manera sencilla de encender y apagar la linterna.
Geocoding: coordenadas y direcciones de código geográfico y de código geográfico inverso.
Geolocation: recupere la ubicación de GPS del dispositivo.
Gyroscope: haga seguimiento de la rotación alrededor de tres ejes primarios del dispositivo.
Launcher: permite que una aplicación abra un URI por el sistema.
Magnetometer: detecte la orientación del dispositivo respectivo del campo magnético de la Tierra.
MainThread: ejecute código en el subproceso principal de la aplicación.
Maps: abra la aplicación de mapas en una ubicación específica.
Open Browser: abra rápidamente y sin problemas un explorador en un sitio web específico.
Orientation Sensor: recupere la orientación del dispositivo en un espacio tridimensional.
Phone Dialer: abra el marcador telefónico.
Platform Extensions: métodos del asistente para convertir Rect, Size y Point.
Preferences: agregue rápida y sencillamente las preferencias persistentes.
Secure Storage: almacene datos de manera segura.
Share: envíe texto y URI de sitio web a otras aplicaciones.
SMS: cree un mensajes SMS para enviarlo.
Text-to-Speech: vocalice texto en el dispositivo.
Unit Converters: métodos del asistente para convertir unidades.
Version Tracking: haga seguimiento de las versiones de las aplicaciones y los números de compilación.
Vibrate: haga que el dispositivo vibre.

Solución de problemas
Busque ayuda si se encuentra con problemas.

Documentación de la API
Examine la documentación de la API para cada característica de Xamarin.Essentials.
Introducción a Xamarin.Essentials
22/07/2019 • 5 minutes to read • Edit Online

Xamarin.Essentials brinda una API multiplataforma única que funciona con cualquier aplicación iOS,
Android o UWP accesible desde código compartido, sin importar cómo se creó la interfaz de usuario.
Para obtener más información sobre los sistemas operativos compatibles, consulte la guía de
compatibilidad con plataformas y características.

Instalación
Xamarin.Essentials está disponible como paquete NuGet que se puede agregar a cualquier proyecto
nuevo o existente con Visual Studio.
1. Descargue e instale Visual Studio con Visual Studio Tools para Xamarin.
2. Abra un proyecto existente o cree uno nuevo con la plantilla de aplicación vacía en Visual Studio
C# (Android, iPhone e iPad o multiplataforma).

IMPORTANT
Si se agrega a un proyecto de UWP, asegúrese de que en las propiedades del proyecto esté establecida la
compilación 16299 u otra posterior.

3. Agregue el paquete NuGet Xamarin.Essentials a cada proyecto:


Visual Studio
Visual Studio para Mac
En el panel del Explorador de soluciones, haga clic con el botón derecho en el nombre de la
solución y seleccione Administrar paquetes NuGet. Busque Xamarin.Essentials e instale el
paquete en TODOS los proyectos, incluidos Android, iOS, UWP y las bibliotecas de .NET
Standard.
4. Agregue una referencia a Xamarin.Essentials en cualquier clase de C# para hacer referencia a las
API.

using Xamarin.Essentials;

5. Xamarin.Essentials requiere una configuración específica de plataforma:


Android
iOS
UWP
La versión mínima de Android compatible con Xamarin.Essentials es la 4.4, que corresponde a un
nivel de API 19, pero la versión de destino de Android para compilar debe ser la 9.0,
correspondiente al nivel de API 28. (En Visual Studio, estas dos versiones se establecen en el
cuadro de diálogo Propiedades del proyecto correspondiente al proyecto de Android en la pestaña
Manifiesto de Android). En Visual Studio para Mac, se establecen en el cuadro de diálogo
Opciones del proyecto correspondiente al proyecto de Android, en la pestaña Aplicación de
Android).
Xamarin.Essentials instala la versión 28.0.0.1 de las bibliotecas de Xamarin.Android.Support que
necesita. Las demás bibliotecas de Xamarin.Android.Support que requiere la aplicación también se
deben actualizar a la versión 28.0.0.1 con el administrador de paquetes NuGet. Todas las
bibliotecas de Xamarin.Android.Support que la aplicación usa deben ser iguales y la versión debe
ser al menos 28.0.0.1. Consulte la página de solución de problemas si no puede agregar el paquete
NuGet de Xamarin.Essentials ni actualizar los paquetes NuGet de la solución.
En MainLauncher del proyecto Android o en cualquier Activity que se inicia, Xamarin.Essentials
se debe inicializar en el método OnCreate :

protected override void OnCreate(Bundle savedInstanceState) {


//...
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState); // add this line to your code,
it may also be called: bundle
//...

Para controlar los permisos en tiempo de ejecución de Android, Xamarin.Essentials debe recibir
cualquier OnRequestPermissionsResult . Agregue el código siguiente a todas las clases Activity :

public override void OnRequestPermissionsResult(int requestCode, string[] permissions,


[GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions,
grantResults);

base.OnRequestPermissionsResult(requestCode, permissions, grantResults);


}

6. Siga las guías de Xamarin.Essentials para poder copiar y pegar fragmentos de código para cada
característica.

Xamarin.Essentials : API multiplataformas para Mobile Apps


(video)

Otros recursos
Es recomendable que los desarrolladores que trabajan por primera vez con Xamarin visiten Introducción
al desarrollo de Xamarin.
Visite el repositorio GitHub de Xamarin.Essentials para ver el código fuente actual, qué viene más
adelante, ejecutar ejemplos y clonar el repositorio. Estaremos encantados de recibir cualquier
colaboración de la comunidad.
Examine la documentación de la API para conocer cada característica de Xamarin.Essentials.
Compatibilidad de la plataforma
30/07/2019 • 3 minutes to read • Edit Online

Xamarin.Essentials admite las siguientes plataformas y sistemas operativos:

PLATAFORMA VERSIÓN

Android 4.4 (API 19) o versiones posteriores

iOS 10.0 o versiones posteriores

Tizen 4.0 o versiones posteriores

tvOS 10.0 o versiones posteriores

watchOS 4.0 o versiones posteriores

UWP 10.0.16299.0 o versiones posteriores

Nota:
Tizen es compatible oficialmente con el equipo de desarrollo de Samsung.
tvOS & watchOS tienen una cobertura de API limitada; consulte la guía de características para obtener más
información.
Tizen, tvOS, & watchOS actualmente están en versión preliminar y están disponibles en Xamarin.Essentials
1.3-pre.

Compatibilidad con características


Xamarin.Essentials siempre intenta incorporar características a cada plataforma, aunque a veces hay limitaciones
en función del dispositivo. A continuación se muestra una guía de las características admitidas en cada plataforma.
Guía de iconos:
✔: compatibilidad total
: compatibilidad limitada
: no compatible

CARACTERÍSTIC
A ANDROID IOS UWP WATCHOS TVOS TIZEN

Acelerómetro ✔ ✔ ✔ ✔ ✔

Información ✔ ✔ ✔ ✔ ✔ ✔
de la
aplicación

Barómetro ✔ ✔ ✔ ✔ ✔

Batería ✔ ✔ ✔ ✔
CARACTERÍSTIC
A ANDROID IOS UWP WATCHOS TVOS TIZEN

Portapapeles ✔ ✔ ✔

Convertidores ✔ ✔ ✔ ✔ ✔ ✔
de colores

Brújula ✔ ✔ ✔ ✔

Conectividad ✔ ✔ ✔ ✔ ✔ ✔

Detección de ✔ ✔ ✔ ✔ ✔ ✔
vibraciones

Información ✔ ✔ ✔
de pantalla
del dispositivo

Información ✔ ✔ ✔ ✔ ✔ ✔
del dispositivo

Correo ✔ ✔ ✔ ✔
electrónico

Asistentes del ✔ ✔ ✔ ✔ ✔ ✔
sistema de
archivos

Linterna ✔ ✔ ✔ ✔

Codificación ✔ ✔ ✔ ✔ ✔ ✔
geográfica

Geolocalizació ✔ ✔ ✔ ✔
n

Giroscopio ✔ ✔ ✔ ✔ ✔

Selector ✔ ✔ ✔ ✔

Magnetómetr ✔ ✔ ✔ ✔ ✔
o

MainThread ✔ ✔ ✔ ✔ ✔ ✔

Mapas ✔ ✔ ✔ ✔ ✔

Apertura del ✔ ✔ ✔ ✔
explorador

Sensor de ✔ ✔ ✔ ✔ ✔
orientación
CARACTERÍSTIC
A ANDROID IOS UWP WATCHOS TVOS TIZEN

Marcador ✔ ✔ ✔ ✔
telefónico

Extensiones ✔ ✔ ✔ ✔ ✔ ✔
de plataforma

Preferencias ✔ ✔ ✔ ✔ ✔ ✔

Almacenamie ✔ ✔ ✔ ✔ ✔ ✔
nto seguro

Compartir ✔ ✔ ✔ ✔

SMS ✔ ✔ ✔ ✔

Texto a voz ✔ ✔ ✔ ✔ ✔ ✔

Convertidores ✔ ✔ ✔ ✔ ✔ ✔
de unidades

Seguimiento ✔ ✔ ✔ ✔ ✔ ✔
de versiones

Vibración ✔ ✔ ✔ ✔
Xamarin.Essentials: Acelerómetro
11/07/2019 • 4 minutes to read • Edit Online

La clase Accelerometer permite supervisar el sensor del acelerómetro del dispositivo, que indica la aceleración
del dispositivo en un espacio tridimensional.

Primeros pasos
Para empezar a usar esta API, lea la guía de introducción para Xamarin.Essentials con el fin de asegurarse de que
la biblioteca está correctamente instalada y configurada en los proyectos.

Uso de Accelerometer
Agregue una referencia a Xamarin.Essentials en su clase:

using Xamarin.Essentials;

La funcionalidad Accelerometer funciona mediante una llamada a los métodos Start y Stop para realizar
escuchas de los cambios realizados en la aceleración. Los cambios se enviarán a través del evento ReadingChanged
. A continuación le mostramos un ejemplo de uso:
public class AccelerometerTest
{
// Set speed delay for monitoring changes.
SensorSpeed speed = SensorSpeed.UI;

public AccelerometerTest()
{
// Register for reading changes, be sure to unsubscribe when finished
Accelerometer.ReadingChanged += Accelerometer_ReadingChanged;
}

void Accelerometer_ReadingChanged(object sender, AccelerometerChangedEventArgs e)


{
var data = e.Reading;
Console.WriteLine($"Reading: X: {data.Acceleration.X}, Y: {data.Acceleration.Y}, Z:
{data.Acceleration.Z}");
// Process Acceleration X, Y, and Z
}

public void ToggleAccelerometer()


{
try
{
if (Accelerometer.IsMonitoring)
Accelerometer.Stop();
else
Accelerometer.Start(speed);
}
catch (FeatureNotSupportedException fnsEx)
{
// Feature not supported on device
}
catch (Exception ex)
{
// Other error has occurred.
}
}
}

Las lecturas del acelerómetro se notifican en G. La G es una unidad de fuerza gravitacional igual a la ejercida por
el campo gravitatorio de la Tierra (9,81 m/s^2).
El sistema de coordenadas se define con respecto a la pantalla del teléfono en orientación predeterminada.
Cuando cambia la orientación de pantalla del dispositivo no se intercambian los ejes.
El eje X es horizontal y apunta a la derecha, el eje Y es vertical y apunta hacia arriba, y el eje Z apunta hacia el
exterior de la parte frontal de la pantalla. En este sistema, las coordenadas de detrás de la pantalla tienen valores
de Z negativo.
Ejemplos:
Cuando el dispositivo se encuentra plano sobre una mesa y se mueve desde el lado izquierdo hacia la
derecha, el valor de aceleración de X es positivo.
Cuando el dispositivo se encuentra plano sobre una mesa, el valor de aceleración es + 1,00 G o (+ 9,81
m/s^2), que corresponden a la aceleración del dispositivo (0 m/s^2) menos la fuerza de la gravedad (-
9,81 m/s^2) y normalizada en G.
Cuando el dispositivo se encuentra plano sobre una mesa y se mueve hacia el cielo con una aceleración de
A m/s^2, el valor de la aceleración es igual A + 9,81, que corresponde a la aceleración del dispositivo (+ A
m/s^2) menos la fuerza de la gravedad (- 9,81 m/s^2) y normalizada en G.
Velocidad de sensor
Más rápido: obtener los datos del sensor tan rápido como sea posible (no se garantiza la devolución en el
subproceso de interfaz de usuario).
Juego: velocidad adecuada para juegos (no se garantiza la devolución en el subproceso de interfaz de
usuario).
Normal: velocidad predeterminada adecuada para los cambios de orientación de pantalla.
Interfaz de usuario: velocidad adecuada para la interfaz de usuario general.
Si no se garantiza la ejecución del controlador de eventos en el subproceso de interfaz de usuario y si el
controlador de eventos necesita tener acceso a elementos de la interfaz de usuario, use el método
MainThread.BeginInvokeOnMainThread para ejecutar ese código en el subproceso de interfaz de usuario.

API
Código fuente de Accelerometer
Documentación de API para Accelerometer

Vídeo relacionado

Encuentre más vídeos de Xamarin en Channel 9 y YouTube.


Xamarin.Essentials: Información de la aplicación:
11/07/2019 • 2 minutes to read • Edit Online

La clase AppInfo proporciona información sobre la aplicación.

Primeros pasos
Para empezar a usar esta API, lea la guía de introducción para Xamarin.Essentials con el fin de asegurarse de que
la biblioteca está correctamente instalada y configurada en los proyectos.

Uso de AppInfo
Agregue una referencia a Xamarin.Essentials en su clase:

using Xamarin.Essentials;

Obtención de información de la aplicación:


La información siguiente se expone a través de la API:

// Application Name
var appName = AppInfo.Name;

// Package Name/Application Identifier (com.microsoft.testapp)


var packageName = AppInfo.PackageName;

// Application Version (1.0.0)


var version = AppInfo.VersionString;

// Application Build Number (1)


var build = AppInfo.BuildString;

Representación de la configuración de la aplicación


La clase AppInfo también puede mostrar una página de configuración mantenida por el sistema operativo para la
aplicación:

// Display settings page


AppInfo.ShowSettingsUI();

Esta página de configuración permite al usuario cambiar los permisos de la aplicación y realizar otras tareas
específicas de la plataforma.

Detalles de implementación de la plataforma


Android
iOS
UWP
La información sobre la aplicación se extrae de AndroidManifest.xml para estos campos:
Build: android:versionCode en el nodo manifest
Name - android:label en el nodo application
PackageName: package en el nodo manifest
VersionString: android:versionName en el nodo application

API
Código fuente de AppInfo
Documentación de API para AppInfo

Vídeo relacionado

Encuentre más vídeos de Xamarin en Channel 9 y YouTube.


Xamarin.Essentials: Barometer
11/07/2019 • 2 minutes to read • Edit Online

La clase Barometer permite supervisar el sensor del barómetro del dispositivo, que mide la presión.

Primeros pasos
Para empezar a usar esta API, lea la guía de introducción para Xamarin.Essentials con el fin de asegurarse de que
la biblioteca está correctamente instalada y configurada en los proyectos.

Uso de Barometer
Agregue una referencia a Xamarin.Essentials en su clase:

using Xamarin.Essentials;

Barometer funciona mediante una llamada a los métodos Start y Stop para escuchar los cambios en la lectura
de presión del barómetro en hectopascales. Los cambios se enviarán a través del evento ReadingChanged . A
continuación le mostramos un ejemplo de uso:
public class BarometerTest
{
// Set speed delay for monitoring changes.
SensorSpeed speed = SensorSpeed.UI;

public BarometerTest()
{
// Register for reading changes.
Barometer.ReadingChanged += Barometer_ReadingChanged;
}

void Barometer_ReadingChanged(object sender, BarometerChangedEventArgs e)


{
var data = e.Reading;
// Process Pressure
Console.WriteLine($"Reading: Pressure: {data.PressureInHectopascals} hectopascals");
}

public void ToggleBarometer()


{
try
{
if (Barometer.IsMonitoring)
Barometer.Stop();
else
Barometer.Start(speed);
}
catch (FeatureNotSupportedException fnsEx)
{
// Feature not supported on device
}
catch (Exception ex)
{
// Other error has occurred.
}
}
}

Velocidad de sensor
Más rápido: obtener los datos del sensor tan rápido como sea posible (no se garantiza la devolución en el
subproceso de interfaz de usuario).
Juego: velocidad adecuada para juegos (no se garantiza la devolución en el subproceso de interfaz de usuario).
Normal: velocidad predeterminada adecuada para los cambios de orientación de pantalla.
Interfaz de usuario: velocidad adecuada para la interfaz de usuario general.
Si no se garantiza la ejecución del controlador de eventos en el subproceso de interfaz de usuario y si el
controlador de eventos necesita tener acceso a elementos de la interfaz de usuario, use el método
MainThread.BeginInvokeOnMainThread para ejecutar ese código en el subproceso de interfaz de usuario.

Detalles de implementación de la plataforma


Android
iOS
UWP
Sin detalles de implementación específicos para la plataforma.
API
Código fuente de Barometer
Documentación de API para Barometer
Xamarin.Essentials: Batería
11/07/2019 • 5 minutes to read • Edit Online

La clase Battery le permite comprobar la información sobre la batería del dispositivo y supervisar los cambios.
Además, ofrece información sobre el estado de ahorro de energía del dispositivo, que indica si este se está
ejecutando en el modo de bajo consumo. Las aplicaciones deben evitar el procesamiento en segundo plano si el
estado de ahorro de energía del dispositivo está activado.

Primeros pasos
Para empezar a usar esta API, lea la guía de introducción para Xamarin.Essentials con el fin de asegurarse de que
la biblioteca está correctamente instalada y configurada en los proyectos.
Para acceder a la funcionalidad de Battery, se requiere la siguiente configuración específica para la plataforma.
Android
iOS
UWP
El permiso Battery es necesario y se debe configurar en el proyecto Android. Se puede agregar de las siguientes
maneras:
Abra el archivo AssemblyInfo.cs de la carpeta Propiedades y agregue lo siguiente:

[assembly: UsesPermission(Android.Manifest.Permission.BatteryStats)]

O BIEN, actualice el manifiesto de Android:


Abra el archivo AndroidManifest.xml de la carpeta Propiedades y agregue lo siguiente dentro del nodo
manifest.

<uses-permission android:name="android.permission.BATTERY_STATS" />

O haga clic con el botón derecho en el proyecto de Android y abra las propiedades del proyecto. En Manifiesto
de Android, busque el área Permisos requeridos: y active el permiso Battery (Batería). Esto actualizará
automáticamente el archivo AndroidManifest.xml.

Uso de Battery
Agregue una referencia a Xamarin.Essentials en su clase:

using Xamarin.Essentials;

Compruebe la información actual de la batería:


var level = Battery.ChargeLevel; // returns 0.0 to 1.0 or 1.0 when on AC or no battery.

var state = Battery.State;

switch (state)
{
case BatteryState.Charging:
// Currently charging
break;
case BatteryState.Full:
// Battery is full
break;
case BatteryState.Discharging:
case BatteryState.NotCharging:
// Currently discharging battery or not being charged
break;
case BatteryState.NotPresent:
// Battery doesn't exist in device (desktop computer)
case BatteryState.Unknown:
// Unable to detect battery state
break;
}

var source = Battery.PowerSource;

switch (source)
{
case BatteryPowerSource.Battery:
// Being powered by the battery
break;
case BatteryPowerSource.AC:
// Being powered by A/C unit
break;
case BatteryPowerSource.Usb:
// Being powered by USB cable
break;
case BatteryPowerSource.Wireless:
// Powered via wireless charging
break;
case BatteryPowerSource.Unknown:
// Unable to detect power source
break;
}

Cada vez que se cambia cualquiera de las propiedades de la batería, se desencadena un evento:

public class BatteryTest


{
public BatteryTest()
{
// Register for battery changes, be sure to unsubscribe when needed
Battery.BatteryInfoChanged += Battery_BatteryInfoChanged;
}

void Battery_BatteryInfoChanged(object sender, BatteryInfoChangedEventArgs e)


{
var level = e.ChargeLevel;
var state = e.State;
var source = e.PowerSource;
Console.WriteLine($"Reading: Level: {level}, State: {state}, Source: {source}");
}
}

Es posible poner los dispositivos que usan baterías en el modo de ahorro en caso de baja energía. A veces, los
dispositivos cambian automáticamente a este modo, por ejemplo, cuando la batería cae por debajo del 20 % de su
capacidad. El sistema operativo responde al modo de ahorro de energía reduciendo las actividades que tienden a
agotar la batería. Para ayudar, las aplicaciones pueden evitar el procesamiento en segundo plano u otras
actividades de alta potencia cuando el modo de ahorro de energía está activado.
También puede conocer el estado de ahorro de energía actual del dispositivo con la propiedad estática
Battery.EnergySaverStatus :

// Get energy saver status


var status = Battery.EnergySaverStatus;

Esta propiedad devuelve un miembro de la enumeración EnergySaverStatus , que es On , Off o Unknown . Si la


propiedad devuelve On , la aplicación debe evitar el procesamiento en segundo plano o cualquier otra actividad
que pueda tener un consumo energético grande.
La aplicación también debe instalar un controlador de eventos. La clase Battery expone un evento que se
desencadena cuando cambia el estado de ahorro de energía:

public class EnergySaverTest


{
public EnergySaverTest()
{
// Subscribe to changes of energy-saver status
Battery.EnergySaverStatusChanged += OnEnergySaverStatusChanged;
}

private void OnEnergySaverStatusChanged(EnergySaverStatusChangedEventArgs e)


{
// Process change
var status = e.EnergySaverStatus;
}
}

Si el estado de ahorro de energía cambia a On , la aplicación debe detener el procesamiento en segundo plano. Si
el estado cambia a Unknown o Off , la aplicación puede reanudar el procesamiento en segundo plano.

Diferencias entre plataformas


Android
iOS
UWP
No hay diferencias entre las plataformas.

API
Código fuente de Battery
Documentación de API para Battery

Vídeo relacionado
Encuentre más vídeos de Xamarin en Channel 9 y YouTube.
Xamarin.Essentials: Portapapeles
11/07/2019 • 2 minutes to read • Edit Online

La clase Clipboard permite copiar y pegar texto en el Portapapeles del sistema entre aplicaciones.

Primeros pasos
Para empezar a usar esta API, lea la guía de introducción para Xamarin.Essentials con el fin de asegurarse de que
la biblioteca está correctamente instalada y configurada en los proyectos.

Uso de Clipboard
Agregue una referencia a Xamarin.Essentials en su clase:

using Xamarin.Essentials;

Para comprobar si actualmente el Portapapeles tiene texto listo para pegar:

var hasText = Clipboard.HasText;

Para establecer texto en el Portapapeles:

await Clipboard.SetTextAsync("Hello World");

Para leer texto desde el Portapapeles:

var text = await Clipboard.GetTextAsync();

TIP
El acceso al Portapapeles debe realizarse en el subproceso de la interfaz de usuario principal. Consulte la API de MainThread
para ver cómo invocar métodos en el subproceso de la interfaz de usuario principal.

API
Código fuente de Clipboard
Documentación de API de Clipboard

Vídeo relacionado

Encuentre más vídeos de Xamarin en Channel 9 y YouTube.


Xamarin.Essentials: convertidores de color
11/07/2019 • 2 minutes to read • Edit Online

La clase ColorConverters de Xamarin.Essentials ofrece varios métodos auxiliares para System.Drawing.Color.

Primeros pasos
Para empezar a usar esta API, lea la guía de introducción para Xamarin.Essentials con el fin de asegurarse de que
la biblioteca está correctamente instalada y configurada en los proyectos.

Uso de los convertidores de color


Agregue una referencia a Xamarin.Essentials en su clase:

using Xamarin.Essentials;

Al trabajar con System.Drawing.Color , puede usar los convertidores integrados de Xamarin.Forms para crear un
color a partir de Hsl, Hex o UInt.

var blueHex = ColorConverters.FromHex("#3498db");


var blueHsl = ColorConverters.FromHsl(204, 70, 53);
var blueUInt = ColorConverers.FromUInt(3447003);

Uso de extensiones de color


Los método de extensión de System.Drawing.Color le permiten aplicar propiedades diferentes:

var blue = ColorConverters.FromHex("#3498db");

// Multiplies the current alpha by 50%


var blueWithAlpha = blue.MultiplyAlpha(.5f);

Hay varios métodos de extensión, por ejemplo:


ToUInt
MultiplyAlpha
WithHue
WithAlpha
WithSaturation
WithLuminosity

Uso de las extensiones de plataforma


Además, puede convertir System.Drawing.Color a la estructura de color específica de la plataforma. Estos
métodos solo se pueden llamar desde proyectos de UWP, iOS y Android.
var system = System.Drawing.Color.FromArgb(255, 52, 152, 219);

// Extension to convert to Android.Graphics.Color, UIKit.UIColor, or Windows.UI.Color


var platform = system.ToPlatformColor();

var platform = new Android.Graphics.Color(52, 152, 219, 255);

// Back to System.Drawing.Color
var system = platform.ToSystemColor();

El método ToSystemColor se aplica a Android.Graphics.Color, UIKit.UIColor y Windows.UI.Color.

API
Código fuente de los convertidores de color
Documentación sobre la API de los convertidores de color
Color fuente de las extensiones de color
Documentación sobre la API de las extensiones de color
Xamarin.Essentials: Brújula
11/07/2019 • 4 minutes to read • Edit Online

La clase Compass permite supervisar la dirección del norte magnético del dispositivo.

Primeros pasos
Para empezar a usar esta API, lea la guía de introducción para Xamarin.Essentials con el fin de asegurarse de que
la biblioteca está correctamente instalada y configurada en los proyectos.

Uso de Compass
Agregue una referencia a Xamarin.Essentials en su clase:

using Xamarin.Essentials;

La funcionalidad Compass funciona mediante una llamada a los métodos Start y Stop para realizar escuchas
de los cambios realizados en la brújula. Los cambios se enviarán a través del evento ReadingChanged . A
continuación se muestra un ejemplo:
public class CompassTest
{
// Set speed delay for monitoring changes.
SensorSpeed speed = SensorSpeed.UI;

public CompassTest()
{
// Register for reading changes, be sure to unsubscribe when finished
Compass.ReadingChanged += Compass_ReadingChanged;
}

void Compass_ReadingChanged(object sender, CompassChangedEventArgs e)


{
var data = e.Reading;
Console.WriteLine($"Reading: {data.HeadingMagneticNorth} degrees");
// Process Heading Magnetic North
}

public void ToggleCompass()


{
try
{
if (Compass.IsMonitoring)
Compass.Stop();
else
Compass.Start(speed);
}
catch (FeatureNotSupportedException fnsEx)
{
// Feature not supported on device
}
catch (Exception ex)
{
// Some other exception has occurred
}
}
}

Velocidad de sensor
Más rápido: obtener los datos del sensor tan rápido como sea posible (no se garantiza la devolución en el
subproceso de interfaz de usuario).
Juego: velocidad adecuada para juegos (no se garantiza la devolución en el subproceso de interfaz de usuario).
Normal: velocidad predeterminada adecuada para los cambios de orientación de pantalla.
Interfaz de usuario: velocidad adecuada para la interfaz de usuario general.
Si no se garantiza la ejecución del controlador de eventos en el subproceso de interfaz de usuario y si el
controlador de eventos necesita tener acceso a elementos de la interfaz de usuario, use el método
MainThread.BeginInvokeOnMainThread para ejecutar ese código en el subproceso de interfaz de usuario.

Detalles de implementación de la plataforma


Android
Android no proporciona una API para recuperar la dirección de la brújula. El acelerómetro y el magnetómetro se
usan para calcular la dirección del norte magnético, lo que recomienda Google.
En casos poco habituales, es posible que vea resultados incoherentes porque sea necesario calibrar los sensores,
lo que implica mover el dispositivo describiendo un ocho. La mejor manera de hacerlo es abrir Google Maps,
pulsar en el punto de la ubicación y seleccionar Calibrar la brújula.
Tenga en cuenta que la ejecución simultánea de varios sensores desde la aplicación puede ajustar la velocidad del
sensor.

Filtro de paso bajo


Debido a la forma de calcular y actualizar los valores de la brújula de Android, es posible que sea necesario
suavizarlos. Se puede aplicar un filtro de paso bajo que calcula el promedio de los valores de seno y coseno de los
ángulos, y se puede activar si se sobrecarga el método Start , que acepta el parámetro bool applyLowPassFilter :

Compass.Start(SensorSpeed.UI, applyLowPassFilter: true);

Esto solo se aplica a la plataforma Android; el parámetro se ignora en iOS y UWP. Puede leer más información
aquí.

API
Código fuente de Compass
Documentación de API para Compass
Xamarin.Essentials: Conectividad
18/07/2019 • 4 minutes to read • Edit Online

La clase Connectivity permite supervisar los cambios en las condiciones de red del dispositivo, revisar el acceso
actual a la red y cómo está conectado actualmente.

Primeros pasos
Para empezar a usar esta API, lea la guía de introducción para Xamarin.Essentials con el fin de asegurarse de que
la biblioteca está correctamente instalada y configurada en los proyectos.
Para acceder a la funcionalidad Connectivity, se requiere la siguiente configuración específica para la plataforma.
Android
iOS
UWP
El permiso AccessNetworkState es necesario y se debe configurar en el proyecto Android. Se puede agregar de las
siguientes maneras:
Abra el archivo AssemblyInfo.cs de la carpeta Propiedades y agregue lo siguiente:

[assembly: UsesPermission(Android.Manifest.Permission.AccessNetworkState)]

O BIEN, actualice el manifiesto de Android:


Abra el archivo AndroidManifest.xml de la carpeta Propiedades y agregue lo siguiente dentro del nodo
manifest.

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

O haga clic con el botón derecho en el proyecto de Android y abra las propiedades del proyecto. En Manifiesto
de Android, busque el área Permisos requeridos: y compruebe el permiso Access Network State (Estado de
red de acceso). Esto actualizará automáticamente el archivo AndroidManifest.xml.

Uso de Connectivity
Agregue una referencia a Xamarin.Essentials en su clase:

using Xamarin.Essentials;

Compruebe el acceso de red actual:

var current = Connectivity.NetworkAccess;

if (current == NetworkAccess.Internet)
{
// Connection to internet is available
}
Acceso a la red cae en estas categorías:
Internet: acceso a Internet y local.
ConstrainedInternet: acceso limitado a Internet. Indica la conectividad cautiva del portal, donde se
proporciona acceso local a un portal web, pero el acceso a Internet requiere que se proporcionen credenciales
específicas a través de un portal.
Local: solo acceso a la red local.
None: sin conectividad disponible.
Unknown: no se puede determinar la conectividad de Internet.
Puede comprobar qué tipo de perfil de conexión el dispositivo usa de manera activa:

var profiles = Connectivity.ConnectionProfiles;


if (profiles.Contains(ConnectionProfile.WiFi))
{
// Active Wi-Fi connection.
}

Cada vez que el perfil de conexión o el acceso a la red cambia, puede recibir un evento cuando se desencadena:

public class ConnectivityTest


{
public ConnectivityTest()
{
// Register for connectivity changes, be sure to unsubscribe when finished
Connectivity.ConnectivityChanged += Connectivity_ConnectivityChanged;
}

void Connectivity_ConnectivityChanged(object sender, ConnectivityChangedEventArgs e)


{
var access = e.NetworkAccess;
var profiles = e.ConnectionProfiles;
}
}

Limitaciones
Es importante tener en cuenta que puede que NetworkAccess informe Internet , pero no hay disponible acceso
total a la Web. Debido a cómo funciona la conectividad en cada plataforma, solo puede garantizar que hay
disponible una conexión. Por ejemplo, es posible que el dispositivo esté conectado a una red Wi-Fi, pero el
enrutador no está conectado a Internet. En esta instancia, puede que se indique que hay Internet, pero no hay
disponible ninguna conexión activa.

API
Código fuente de Connectivity
Documentación de API de Connectivity

Vídeo relacionado
Encuentre más vídeos de Xamarin en Channel 9 y YouTube.
Xamarin.Essentials: detección de agitaciones
18/07/2019 • 3 minutes to read • Edit Online

La clase Accelerometer permite supervisar el sensor del acelerómetro del dispositivo, que indica la aceleración
del dispositivo en un espacio tridimensional. Además, le permite registrar eventos que se realizarán cuando el
usuario agite el dispositivo.

Primeros pasos
Para empezar a usar esta API, lea la guía de introducción para Xamarin.Essentials con el fin de asegurarse de que
la biblioteca está correctamente instalada y configurada en los proyectos.

Uso de la detección de agitaciones


Agregue una referencia a Xamarin.Essentials en su clase:

using Xamarin.Essentials;

Para detectar la agitación del dispositivo, debe usar la funcionalidad Accelerometer mediante una llamada a los
métodos Start y Stop para realizar cambios en la aceleración y para detectar movimientos de agitación.
Siempre que se detecte agitación, se desencadenará un evento ShakeDetected . Se recomienda usar Game o faster
para SensorSpeed . A continuación le mostramos un ejemplo de uso:
public class DetectShakeTest
{
// Set speed delay for monitoring changes.
SensorSpeed speed = SensorSpeed.Game;

public DetectShakeTest()
{
// Register for reading changes, be sure to unsubscribe when finished
Accelerometer.ShakeDetected += Accelerometer_ShakeDetected ;
}

void Accelerometer_ShakeDetected (object sender, EventArgs e)


{
// Process shake event
}

public void ToggleAccelerometer()


{
try
{
if (Accelerometer.IsMonitoring)
Accelerometer.Stop();
else
Accelerometer.Start(speed);
}
catch (FeatureNotSupportedException fnsEx)
{
// Feature not supported on device
}
catch (Exception ex)
{
// Other error has occurred.
}
}
}

Velocidad de sensor
Más rápido: obtener los datos del sensor tan rápido como sea posible (no se garantiza la devolución en el
subproceso de interfaz de usuario).
Juego: velocidad adecuada para juegos (no se garantiza la devolución en el subproceso de interfaz de usuario).
Normal: velocidad predeterminada adecuada para los cambios de orientación de pantalla.
Interfaz de usuario: velocidad adecuada para la interfaz de usuario general.
Si no se garantiza la ejecución del controlador de eventos en el subproceso de interfaz de usuario y si el
controlador de eventos necesita tener acceso a elementos de la interfaz de usuario, use el método
MainThread.BeginInvokeOnMainThread para ejecutar ese código en el subproceso de interfaz de usuario.

Detalles de implementación
La API para la detección de agitaciones usa lecturas sin procesar del acelerómetro para calcular la aceleración.
Utiliza un mecanismo de cola simple para detectar si tres cuartos de los eventos recientes del acelerómetro se han
producido durante el último medio segundo. La aceleración se calcula añadiendo el cuadrado de las lecturas X, Y y
Z del acelerómetro y comparándolo con un umbral determinado.

API
Código fuente de Accelerometer
Documentación de API de Accelerometer

Vídeo relacionado

Encuentre más vídeos de Xamarin en Channel 9 y YouTube.


Xamarin.Essentials: Información de pantalla del
dispositivo
11/07/2019 • 2 minutes to read • Edit Online

La clase DeviceDisplay proporciona información sobre las métricas de la pantalla del dispositivo que determinan
cómo se ejecuta la aplicación. También puede solicitar que la pantalla no se apague mientras la aplicación se esté
ejecutando.

Primeros pasos
Para empezar a usar esta API, lea la guía de introducción para Xamarin.Essentials con el fin de asegurarse de que
la biblioteca está correctamente instalada y configurada en los proyectos.

Uso de DeviceDisplay
Agregue una referencia a Xamarin.Essentials en su clase:

using Xamarin.Essentials;

Información de la pantalla principal


Además de información básica del dispositivo, la clase DeviceDisplay contiene información sobre la pantalla y la
orientación del dispositivo.

// Get Metrics
var mainDisplayInfo = DeviceDisplay.MainDisplayInfo;

// Orientation (Landscape, Portrait, Square, Unknown)


var orientation = mainDisplayInfo.Orientation;

// Rotation (0, 90, 180, 270)


var rotation = mainDisplayInfo.Rotation;

// Width (in pixels)


var width = mainDisplayInfo.Width;

// Height (in pixels)


var height = mainDisplayInfo.Height;

// Screen density
var density = mainDisplayInfo.Density;

La clase DeviceDisplay también expone un evento al que se puede suscribir para que se desencadene siempre
que cambie cualquier métrica de pantalla:
public class DisplayInfoTest
{
public DisplayInfoTest()
{
// Subscribe to changes of screen metrics
DeviceDisplay.MainDisplayInfoChanged += OnMainDisplayInfoChanged;
}

void OnMainDisplayInfoChanged(object sender, DisplayInfoChangedEventArgs e)


{
// Process changes
var displayInfo = e.DisplayInfo;
}
}

La clase DeviceDisplay expone una propiedad bool con el nombre KeepScreenOn . Esta propiedad puede
establecerse para que intente impedir que la pantalla del dispositivo se apague o bloquee.

public class KeepScreenOnTest


{
public void ToggleScreenLock()
{
DeviceDisplay.KeepScreenOn = !DeviceDisplay.KeepScreenOn;
}
}

Diferencias entre plataformas


Android
iOS
UWP
No hay diferencias.

API
Código fuente de DeviceDisplay
Documentación de API de DeviceDisplay
Xamarin.Essentials: Información del dispositivo
11/07/2019 • 2 minutes to read • Edit Online

La clase DeviceInfo proporciona información sobre el dispositivo en el que se ejecuta la aplicación.

Primeros pasos
Para empezar a usar esta API, lea la guía de introducción para Xamarin.Essentials con el fin de asegurarse de que
la biblioteca está correctamente instalada y configurada en los proyectos.

Uso de DeviceInfo
Agregue una referencia a Xamarin.Essentials en su clase:

using Xamarin.Essentials;

La información siguiente se expone a través de la API:

// Device Model (SMG-950U, iPhone10,6)


var device = DeviceInfo.Model;

// Manufacturer (Samsung)
var manufacturer = DeviceInfo.Manufacturer;

// Device Name (Motz's iPhone)


var deviceName = DeviceInfo.Name;

// Operating System Version Number (7.0)


var version = DeviceInfo.VersionString;

// Platform (Android)
var platform = DeviceInfo.Platform;

// Idiom (Phone)
var idiom = DeviceInfo.Idiom;

// Device Type (Physical)


var deviceType = DeviceInfo.DeviceType;

Plataformas
DeviceInfo.Platformse correlaciona con una cadena de constante que se asigna al sistema operativo. Los valores
se pueden comprobar con el struct DevicePlatform :
DevicePlatform.iOS: iOS
DevicePlatform.Android: Android
DevicePlatform.UWP: UWP
DevicePlatform.Unknown: desconocido

Expresiones
DeviceInfo.Idiom se correlaciona con una cadena de constante que se asigna al tipo de dispositivo en el que se
ejecuta la aplicación. Los valores se pueden comprobar con el struct DeviceIdiom :
DeviceIdiom.Phone: teléfono
DeviceIdiom.Tablet: tableta
DeviceIdiom.Desktop: escritorio
DeviceIdiom.TV: TV
DeviceIdiom.Watch: reloj
DeviceIdiom.Unknown: desconocido

Tipo de dispositivo
DeviceInfo.DeviceType pone en correlación una enumeración para determinar si la aplicación se ejecuta en un
dispositivo físico o virtual. Un dispositivo virtual es un simulador o emulador.

Detalles de implementación de la plataforma


iOS
iOS no expone una API para que los desarrolladores obtengan el nombre del dispositivo iOS específico. En su
lugar, se devuelve un identificador de hardware, como iPhone10,6 que hace referencia al iPhone X. Apple no
proporciona una asignación de estos identificadores, pero se puede encontrar en The iPhone Wiki (una fuente no
oficial).

API
Código fuente de DeviceInfo
Documentación de API para DeviceInfo
Xamarin.Essentials: Correo electrónico
19/08/2019 • 3 minutes to read • Edit Online

La clase Email permite que una aplicación abra la aplicación de correo electrónico predeterminada con
información especificada incluido el asunto, el cuerpo y los destinatarios (PARA, CC, CCO ).

Primeros pasos
Para empezar a usar esta API, lea la guía de introducción para Xamarin.Essentials con el fin de asegurarse de que
la biblioteca está correctamente instalada y configurada en los proyectos.

TIP
Para usar la API de correo electrónico en iOS, debe ejecutarla en un dispositivo físico, si no, se producirá una excepción.

Uso de Email
Agregue una referencia a Xamarin.Essentials en su clase:

using Xamarin.Essentials;

Para usar la funcionalidad de Email se llama al método ComposeAsync con un valor EmailMessage que contiene
información sobre el correo electrónico:

public class EmailTest


{
public async Task SendEmail(string subject, string body, List<string> recipients)
{
try
{
var message = new EmailMessage
{
Subject = subject,
Body = body,
To = recipients,
//Cc = ccRecipients,
//Bcc = bccRecipients
};
await Email.ComposeAsync(message);
}
catch (FeatureNotSupportedException fbsEx)
{
// Email is not supported on this device
}
catch (Exception ex)
{
// Some other exception occurred
}
}
}

Datos adjuntos
El envío de archivos por correo electrónico está disponible como versión preliminar experimental en
Xamarin.Essentials versión 1.1.0. Esta característica permite que una aplicación envíe archivos por correo
electrónico a través de clientes de correo electrónico en el dispositivo. Para habilitar esta característica, establezca
la siguiente propiedad en el código de inicio de la aplicación:

ExperimentalFeatures.Enable(ExperimentalFeatures.EmailAttachments);

Una vez que se haya habilitado la característica, se puede enviar por correo electrónico cualquier archivo.
Xamarin.Essentials detectará automáticamente el tipo de archivo (MIME ) y solicitará que el archivo se agregue
como datos adjuntos. Cada cliente de correo electrónico es diferente y podría admitir únicamente algunas
extensiones de archivo o ninguna en absoluto.
A continuación se muestra un ejemplo en el que se escribe texto en el disco y se agrega como datos adjuntos a un
correo electrónico:

var message = new EmailMessage


{
Subject = "Hello",
Body = "World",
};

var fn = "Attachment.txt";
var file = Path.Combine(FileSystem.CacheDirectory, fn);
File.WriteAllText(file, "Hello World");

message.Attachments.Add(new EmailAttachment(file));

await Email.ComposeAsync(message);

Diferencias entre plataformas


Android
iOS
UWP
No todos los clientes de correo electrónico para Android admiten Html . Puesto que no hay ninguna manera de
detectar este problema, recomendamos usar PlainText para enviar correos electrónicos.

API
Código fuente de Email
Documentación de API para Email
Xamarin.Essentials: Asistentes del sistema de
archivos
09/08/2019 • 3 minutes to read • Edit Online

La clase FileSystem contiene una serie de aplicaciones auxiliares para buscar la caché y los directorios de datos
de la aplicación y abrir archivos dentro del paquete de aplicación.

Primeros pasos
Para empezar a usar esta API, lea la guía de introducción para Xamarin.Essentials con el fin de asegurarse de
que la biblioteca está correctamente instalada y configurada en los proyectos.

Uso de aplicaciones auxiliares de sistema de archivos


Agregue una referencia a Xamarin.Essentials en su clase:

using Xamarin.Essentials;

Para obtener el directorio de la aplicación para almacenar datos en caché. Los datos en caché se pueden usar
para cualquier dato que se tenga que conservar más tiempo que los temporales, pero no deben ser datos
necesarios para que el funcionamiento sea correcto, ya que el sistema operativo es el que determina el momento
en el que se borra el almacén.

var cacheDir = FileSystem.CacheDirectory;

Para obtener el directorio de nivel superior de la aplicación para todos los archivos que no son archivos de datos
de usuario. Se realiza una copia de seguridad de estos archivos con el marco de sincronización del sistema
operativo. Vea Detalles de implementación de la plataforma a continuación.

var mainDir = FileSystem.AppDataDirectory;

Para abrir un archivo que se incluye en el paquete de aplicación:

using (var stream = await FileSystem.OpenAppPackageFileAsync(templateFileName))


{
using (var reader = new StreamReader(stream))
{
var fileContents = await reader.ReadToEndAsync();
}
}

Detalles de implementación de la plataforma


Android
iOS
UWP
CacheDirectory: devuelve el CacheDir del contexto actual.
AppDataDirectory: devuelve el FilesDir del contexto actual y se realiza una copia de seguridad mediante
Copia de seguridad automática a partir de la API 23 y versiones posteriores.
Agregue un archivo a la carpeta Activos del proyecto de Android y marque la acción de compilación como
AndroidAsset para usarla con OpenAppPackageFileAsync .

API
Código fuente de las aplicaciones auxiliares de sistema de archivos
Documentación de API para FileSystem
Xamarin.Essentials: Linterna
11/07/2019 • 3 minutes to read • Edit Online

La clase Flashlight tiene la capacidad de activar o desactivar el flash de la cámara del dispositivo y convertirlo en
una linterna.

Primeros pasos
Para empezar a usar esta API, lea la guía de introducción para Xamarin.Essentials con el fin de asegurarse de que
la biblioteca está correctamente instalada y configurada en los proyectos.
Para acceder a la funcionalidad de Flashlight, se requiere la siguiente configuración específica para la plataforma.
Android
iOS
UWP
Los permisos Flashlight y Camera son obligatorios y se deben configurar en el proyecto de Android. Se puede
agregar de las siguientes maneras:
Abra el archivo AssemblyInfo.cs de la carpeta Propiedades y agregue lo siguiente:

[assembly: UsesPermission(Android.Manifest.Permission.Flashlight)]
[assembly: UsesPermission(Android.Manifest.Permission.Camera)]

O BIEN, actualice el manifiesto de Android:


Abra el archivo AndroidManifest.xml de la carpeta Propiedades y agregue lo siguiente dentro del nodo
manifest.

<uses-permission android:name="android.permission.FLASHLIGHT" />


<uses-permission android:name="android.permission.CAMERA" />

O haga clic con el botón derecho en el proyecto de Android y abra las propiedades del proyecto. En Manifiesto
de Android, busque el área Permisos necesarios: y active los permisos FLASHLIGHT (Linterna) y CAMERA
(Cámara). Esto actualizará automáticamente el archivo AndroidManifest.xml.
Mediante la adición de estos permisos Google Play filtrará automáticamente los dispositivos sin necesidad de
hardware específico. Para solucionarlo, agregue lo siguiente al archivo AssemblyInfo.cs del proyecto de Android:

[assembly: UsesFeature("android.hardware.camera", Required = false)]


[assembly: UsesFeature("android.hardware.camera.autofocus", Required = false)]

Uso de Flashlight
Agregue una referencia a Xamarin.Essentials en su clase:

using Xamarin.Essentials;

La linterna se puede activar y desactivar a través de los métodos TurnOnAsync y TurnOffAsync :


try
{
// Turn On
await Flashlight.TurnOnAsync();

// Turn Off
await Flashlight.TurnOffAsync();
}
catch (FeatureNotSupportedException fnsEx)
{
// Handle not supported on device exception
}
catch (PermissionException pEx)
{
// Handle permission exception
}
catch (Exception ex)
{
// Unable to turn on/off flashlight
}

Detalles de implementación de la plataforma


Android
iOS
UWP
La clase Flashlight se ha optimizado en función del sistema operativo del dispositivo.
Nivel de API 23 y superior
En los niveles de API más recientes, se usa el Modo Linterna para activar o desactivar la unidad de flash del
dispositivo.
Nivel de API 22 e inferior
Se crea una textura de la superficie de cámara para activar o desactivar el FlashMode de la unidad de la cámara.

API
Código fuente de Flashlight
Documentación de API para Flashlight
Xamarin.Essentials: Codificación geográfica
11/07/2019 • 3 minutes to read • Edit Online

La clase Geocoding proporciona API para geocodificar una marca de posición en coordenadas de posición e
invertir las coordenadas de código geográfico a una marca de posición.

Primeros pasos
Para empezar a usar esta API, lea la guía de introducción para Xamarin.Essentials con el fin de asegurarse de que
la biblioteca está correctamente instalada y configurada en los proyectos.
Para acceder a la funcionalidad de Geocoding, se requiere la siguiente configuración específica para la
plataforma.
Android
iOS
UWP
No se requiere configuración adicional.

Uso de Geocoding
Agregue una referencia a Xamarin.Essentials en su clase:

using Xamarin.Essentials;

Obtención de coordenadas de ubicación para una dirección:

try
{
var address = "Microsoft Building 25 Redmond WA USA";
var locations = await Geocoding.GetLocationsAsync(address);

var location = locations?.FirstOrDefault();


if (location != null)
{
Console.WriteLine($"Latitude: {location.Latitude}, Longitude: {location.Longitude}, Altitude:
{location.Altitude}");
}
}
catch (FeatureNotSupportedException fnsEx)
{
// Feature not supported on device
}
catch (Exception ex)
{
// Handle exception that may have occurred in geocoding
}

La altitud no siempre está disponible. Si no lo está, es posible que la propiedad Altitude sea null o que el valor
sea cero. Si lo está, el valor se expresa en metros sobre el nivel del mar.

Uso la geocodificación inversa


La geocodificación inversa es el proceso de obtener marcas de posición para un conjunto de coordenadas
existente:

try
{
var lat = 47.673988;
var lon = -122.121513;

var placemarks = await Geocoding.GetPlacemarksAsync(lat, lon);

var placemark = placemarks?.FirstOrDefault();


if (placemark != null)
{
var geocodeAddress =
$"AdminArea: {placemark.AdminArea}\n" +
$"CountryCode: {placemark.CountryCode}\n" +
$"CountryName: {placemark.CountryName}\n" +
$"FeatureName: {placemark.FeatureName}\n" +
$"Locality: {placemark.Locality}\n" +
$"PostalCode: {placemark.PostalCode}\n" +
$"SubAdminArea: {placemark.SubAdminArea}\n" +
$"SubLocality: {placemark.SubLocality}\n" +
$"SubThoroughfare: {placemark.SubThoroughfare}\n" +
$"Thoroughfare: {placemark.Thoroughfare}\n";

Console.WriteLine(geocodeAddress);
}
}
catch (FeatureNotSupportedException fnsEx)
{
// Feature not supported on device
}
catch (Exception ex)
{
// Handle exception that may have occurred in geocoding
}

Distancia entre dos ubicaciones


Las clases Location y LocationExtensions definen métodos para calcular la distancia entre dos ubicaciones.
Consulte el artículo Xamarin.Essentials: Geolocalización para ver un ejemplo.

API
Código fuente de Geocoding
Documentación de API para Geocoding

Vídeo relacionado

Encuentre más vídeos de Xamarin en Channel 9 y YouTube.


Xamarin.Essentials: Geolocalización
11/07/2019 • 7 minutes to read • Edit Online

La clase Geolocation proporciona las API para recuperar las coordenadas de geolocalización actuales del
dispositivo.

Primeros pasos
Para empezar a usar esta API, lea la guía de introducción para Xamarin.Essentials con el fin de asegurarse de que
la biblioteca está correctamente instalada y configurada en los proyectos.
Para acceder a la funcionalidad de Geolocation, se requiere la siguiente configuración específica para la
plataforma:
Android
iOS
UWP
Los permisos Coarse y Fine Location son requeridos y se deben configurar en el proyecto de Android. Además, si
la aplicación tiene como destino Android 5.0 (nivel de API 21) o versiones posteriores, debe declarar que la
aplicación usa las características de hardware en el archivo de manifiesto. Se puede agregar de las siguientes
maneras:
Abra el archivo AssemblyInfo.cs de la carpeta Propiedades y agregue lo siguiente:

[assembly: UsesPermission(Android.Manifest.Permission.AccessCoarseLocation)]
[assembly: UsesPermission(Android.Manifest.Permission.AccessFineLocation)]
[assembly: UsesFeature("android.hardware.location", Required = false)]
[assembly: UsesFeature("android.hardware.location.gps", Required = false)]
[assembly: UsesFeature("android.hardware.location.network", Required = false)]

O bien, actualice el manifiesto de Android:


Abra el archivo AndroidManifest.xml de la carpeta Propiedades y agregue lo siguiente dentro del nodo
manifest:

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />


<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-feature android:name="android.hardware.location" android:required="false" />
<uses-feature android:name="android.hardware.location.gps" android:required="false" />
<uses-feature android:name="android.hardware.location.network" android:required="false" />

O bien, haga clic con el botón derecho en el proyecto de Android y abra las propiedades del proyecto. En
Manifiesto de Android, busque el área Permisos requeridos: y active los permisos
ACCESS_COARSE_LOCATION y ACCESS_FINE_LOCATION. Esto actualizará automáticamente el archivo
AndroidManifest.xml.

Uso de Geolocation
Agregue una referencia a Xamarin.Essentials en su clase:
using Xamarin.Essentials;

La API Geolocation también le pedirá permisos al usuario cuando sea necesario.


Puede obtener la última ubicación conocida del dispositivo mediante una llamada al método
GetLastKnownLocationAsync . A menudo, esto es más rápido que hacer una consulta completa, pero puede ser
menos preciso y probablemente devuelva null si no existe ninguna ubicación en caché.

try
{
var location = await Geolocation.GetLastKnownLocationAsync();

if (location != null)
{
Console.WriteLine($"Latitude: {location.Latitude}, Longitude: {location.Longitude}, Altitude:
{location.Altitude}");
}
}
catch (FeatureNotSupportedException fnsEx)
{
// Handle not supported on device exception
}
catch (FeatureNotEnabledException fneEx)
{
// Handle not enabled on device exception
}
catch (PermissionException pEx)
{
// Handle permission exception
}
catch (Exception ex)
{
// Unable to get location
}

La altitud no siempre está disponible. Si no lo está, es posible que la propiedad Altitude sea null o que el valor
sea cero. Si lo está, el valor se expresa en metros sobre el nivel del mar.
Para consultar las coordenadas de ubicación del dispositivo actual, se puede usar GetLocationAsync . Es mejor
pasar un valor GeolocationRequest completo y CancellationToken , ya que se puede tardar algún tiempo en
obtener la ubicación del dispositivo.
try
{
var request = new GeolocationRequest(GeolocationAccuracy.Medium);
var location = await Geolocation.GetLocationAsync(request);

if (location != null)
{
Console.WriteLine($"Latitude: {location.Latitude}, Longitude: {location.Longitude}, Altitude:
{location.Altitude}");
}
}
catch (FeatureNotSupportedException fnsEx)
{
// Handle not supported on device exception
}
catch (FeatureNotEnabledException fneEx)
{
// Handle not enabled on device exception
}
catch (PermissionException pEx)
{
// Handle permission exception
}
catch (Exception ex)
{
// Unable to get location
}

Precisión de la ubicación geográfica


En la tabla siguiente se describe la precisión por plataforma:
Mínima
PLATAFORMA DISTANCIA (EN METROS)

Android 500

iOS 3000

UWP 1000 - 5000

Bajo
PLATAFORMA DISTANCIA (EN METROS)

Android 500

iOS 1000

UWP 300 - 3000

Media (valor predeterminado )


PLATAFORMA DISTANCIA (EN METROS)

Android 100 - 500


PLATAFORMA DISTANCIA (EN METROS)

iOS 100

UWP 30-500

Alto
PLATAFORMA DISTANCIA (EN METROS)

Android 0 - 100

iOS 10

UWP <= 10

Óptima
PLATAFORMA DISTANCIA (EN METROS)

Android 0 - 100

iOS ~0

UWP <= 10

Detección de ubicaciones ficticias


Algunos dispositivos pueden devolver una ubicación ficticia desde el proveedor o desde una aplicación que
proporciona ubicaciones ficticias. Puede detectarlo usando IsFromMockProvider en cualquier Location .

var request = new GeolocationRequest(GeolocationAccuracy.Medium);


var location = await Geolocation.GetLocationAsync(request);

if (location != null)
{
if(location.IsFromMockProvider)
{
// location is from a mock provider
}
}

Distancia entre dos ubicaciones


Las clases Location y LocationExtensions definen métodos CalculateDistance que permiten calcular la distancia
entre dos ubicaciones geográficas. Esta distancia calculada no tiene en cuenta las carreteras ni otros caminos, y
simplemente es la distancia más corta entre los dos puntos a lo largo de la superficie de la Tierra, lo que también
se conoce como distancia ortodrómica o coloquialmente, "distancia a vuelo de pájaro".
Por ejemplo:

Location boston = new Location(42.358056, -71.063611);


Location sanFrancisco = new Location(37.783333, -122.416667);
double miles = Location.CalculateDistance(boston, sanFrancisco, DistanceUnits.Miles);
El constructor Location tiene argumentos de latitud y longitud en ese orden. Los valores de latitud positivos
están al norte del Ecuador, y los valores de longitud positivos están al este del meridiano de Greenwich. Use el
argumento final CalculateDistance para especificar millas o kilómetros. La clase UnitConverters también define
los métodos KilometersToMiles y MilesToKilometers para la conversión entre las dos unidades.

API
Código fuente de Geolocation
Documentación de API para Geolocation
Xamarin.Essentials: Giroscopio
11/07/2019 • 2 minutes to read • Edit Online

La clase Gyroscope permite supervisar el sensor de giroscopio del dispositivo, que es la rotación sobre los tres
ejes principales del dispositivo.

Primeros pasos
Para empezar a usar esta API, lea la guía de introducción para Xamarin.Essentials con el fin de asegurarse de que
la biblioteca está correctamente instalada y configurada en los proyectos.

Uso de Gyroscope
Agregue una referencia a Xamarin.Essentials en su clase:

using Xamarin.Essentials;

La funcionalidad Gyroscope funciona mediante una llamada a los métodos Start y Stop para realizar escuchas
de los cambios realizados en el giroscopio. Los cambios se enviarán a través del evento ReadingChanged en rad/s.
A continuación le mostramos un ejemplo de uso:
public class GyroscopeTest
{
// Set speed delay for monitoring changes.
SensorSpeed speed = SensorSpeed.UI;

public GyroscopeTest()
{
// Register for reading changes.
Gyroscope.ReadingChanged += Gyroscope_ReadingChanged;
}

void Gyroscope_ReadingChanged(object sender, GyroscopeChangedEventArgs e)


{
var data = e.Reading;
// Process Angular Velocity X, Y, and Z reported in rad/s
Console.WriteLine($"Reading: X: {data.AngularVelocity.X}, Y: {data.AngularVelocity.Y}, Z:
{data.AngularVelocity.Z}");
}

public void ToggleGyroscope()


{
try
{
if (Gyroscope.IsMonitoring)
Gyroscope.Stop();
else
Gyroscope.Start(speed);
}
catch (FeatureNotSupportedException fnsEx)
{
// Feature not supported on device
}
catch (Exception ex)
{
// Other error has occurred.
}
}
}

Velocidad de sensor
Más rápido: obtener los datos del sensor tan rápido como sea posible (no se garantiza la devolución en el
subproceso de interfaz de usuario).
Juego: velocidad adecuada para juegos (no se garantiza la devolución en el subproceso de interfaz de usuario).
Normal: velocidad predeterminada adecuada para los cambios de orientación de pantalla.
Interfaz de usuario: velocidad adecuada para la interfaz de usuario general.
Si no se garantiza la ejecución del controlador de eventos en el subproceso de interfaz de usuario y si el
controlador de eventos necesita tener acceso a elementos de la interfaz de usuario, use el método
MainThread.BeginInvokeOnMainThread para ejecutar ese código en el subproceso de interfaz de usuario.

API
Código fuente de Gyroscope
Documentación de API para Gyroscope
Xamarin.Essentials: Selector
11/07/2019 • 2 minutes to read • Edit Online

La clase Launcher permite que una aplicación abra un URI por el sistema. A menudo se usa al vincular en
profundidad en los esquemas de URI personalizados de otra aplicación. Si quiere abrir el explorador en un sitio
web, debe hacer referencia a la API Browser.

Primeros pasos
Para empezar a usar esta API, lea la guía de introducción para Xamarin.Essentials con el fin de asegurarse de que
la biblioteca está correctamente instalada y configurada en los proyectos.

Uso de Launcher
Agregue una referencia a Xamarin.Essentials en su clase:

using Xamarin.Essentials;

Para usar la funcionalidad Launcher, llame al método OpenAsync y pase un string o Uri para abrirla. Si quiere,
el método CanOpenAsync se puede usar para comprobar si el esquema de URI se puede administrar desde una
aplicación del dispositivo.

public class LauncherTest


{
public async Task OpenRideShareAsync()
{
var supportsUri = await Launcher.CanOpenAsync("lyft://");
if (supportsUri)
await Launcher.OpenAsync("lyft://ridetype?id=lyft_line");
}
}

Diferencias entre plataformas


Android
iOS
UWP
La tarea devuelta desde CanOpenAsync se completa de inmediato.

API
Código fuente de Launcher
Documentación de API para Launcher
Xamarin.Essentials: Magnetómetro
11/07/2019 • 2 minutes to read • Edit Online

La clase Magnetometer permite supervisar el sensor de magnetómetro del dispositivo, que indica la orientación
del dispositivo con respecto al campo magnético de la Tierra.

Primeros pasos
Para empezar a usar esta API, lea la guía de introducción para Xamarin.Essentials con el fin de asegurarse de que
la biblioteca está correctamente instalada y configurada en los proyectos.

Uso de Magnetometer
Agregue una referencia a Xamarin.Essentials en su clase:

using Xamarin.Essentials;

La funcionalidad Magnetometer funciona mediante una llamada a los métodos Start y Stop para realizar
escuchas de los cambios en el magnetómetro. Los cambios se enviarán a través del evento ReadingChanged . A
continuación le mostramos un ejemplo de uso:
public class MagnetometerTest
{
// Set speed delay for monitoring changes.
SensorSpeed speed = SensorSpeed.UI;

public MagnetometerTest()
{
// Register for reading changes.
Magnetometer.ReadingChanged += Magnetometer_ReadingChanged;
}

void Magnetometer_ReadingChanged(object sender, MagnetometerChangedEventArgs e)


{
var data = e.Reading;
// Process MagneticField X, Y, and Z
Console.WriteLine($"Reading: X: {data.MagneticField.X}, Y: {data.MagneticField.Y}, Z:
{data.MagneticField.Z}");
}

public void ToggleMagnetometer()


{
try
{
if (Magnetometer.IsMonitoring)
Magnetometer.Stop();
else
Magnetometer.Start(speed);
}
catch (FeatureNotSupportedException fnsEx)
{
// Feature not supported on device
}
catch (Exception ex)
{
// Other error has occurred.
}
}
}

Todos los datos se devuelven en µ (microteslas).

Velocidad de sensor
Más rápido: obtener los datos del sensor tan rápido como sea posible (no se garantiza la devolución en el
subproceso de interfaz de usuario).
Juego: velocidad adecuada para juegos (no se garantiza la devolución en el subproceso de interfaz de usuario).
Normal: velocidad predeterminada adecuada para los cambios de orientación de pantalla.
Interfaz de usuario: velocidad adecuada para la interfaz de usuario general.
Si no se garantiza la ejecución del controlador de eventos en el subproceso de interfaz de usuario y si el
controlador de eventos necesita tener acceso a elementos de la interfaz de usuario, use el método
MainThread.BeginInvokeOnMainThread para ejecutar ese código en el subproceso de interfaz de usuario.

API
Código fuente de Magnetometer
Documentación de API para Magnetometer
Xamarin.Essentials: MainThread
11/07/2019 • 5 minutes to read • Edit Online

La clase MainThread permite que las aplicaciones ejecuten código en el subproceso de ejecución principal y
determinen si un bloque de código determinado se ejecuta actualmente en el subproceso principal.

Fondo
La mayoría de los sistemas operativos, incluidos iOS, Android y Plataforma universal de Windows, usan un
modelo de un único subproceso para el código que participa en la interfaz de usuario. Este modelo resulta
necesario para serializar de manera adecuada los eventos de la interfaz de usuario, incluidas pulsaciones de
teclas y entradas táctiles. Con frecuencia, este subproceso se denomina el subproceso principal, el subproceso
de interfaz de usuario o el subproceso de UI. La desventaja que presenta este modelo es que todo el código
que accede a los elementos de la interfaz de usuario se deben ejecutar en el subproceso principal de la
aplicación.
Algunas veces, las aplicaciones deben usar eventos que llamar al controlador de eventos en un subproceso de
ejecución secundario. (Es posible que las clases Accelerometer , Compass , Gyroscope , Magnetometer y
OrientationSensor de Xamarin.Essentials devuelvan información en un subproceso secundario cuando se usa
con velocidades más rápidas). Si el controlador de eventos debe acceder a los elementos de la interfaz de
usuario, debe ejecutar ese código en el subproceso principal. La clase MainThread permite que la aplicación
ejecute este código en el subproceso principal.

Primeros pasos
Para empezar a usar esta API, lea la guía de introducción para Xamarin.Essentials con el fin de asegurarse de
que la biblioteca está correctamente instalada y configurada en los proyectos.

Ejecución de código en el subproceso principal


Agregue una referencia a Xamarin.Essentials en su clase:

using Xamarin.Essentials;

Para ejecutar código en el subproceso principal, llame al método MainThread.BeginInvokeOnMainThread estático.


El argumento es un objeto Action , que no es más que un método sin argumentos y sin valor devuelto:

MainThread.BeginInvokeOnMainThread(() =>
{
// Code to run on the main thread
});

También es posible definir un método independiente para el código que se debe ejecutar en el subproceso
principal:

void MyMainThreadCode()
{
// Code to run on the main thread
}
Luego, para ejecutar este método en el subproceso principal, haga referencia a él en el método
BeginInvokeOnMainThread :

MainThread.BeginInvokeOnMainThread(MyMainThreadCode);

NOTE
Xamarin.Forms tiene un método llamado Device.BeginInvokeOnMainThread(Action) que hace lo mismo que
MainThread.BeginInvokeOnMainThread(Action) . Si bien puede usar cualquier método en una aplicación de
Xamarin.Forms, considere si el código de llamada necesita o no una dependencia de Xamarin.Forms. Si no es así,
MainThread.BeginInvokeOnMainThread(Action) probablemente sea una mejor opción.

Determinación de si el código se ejecuta en el subproceso principal


La clase MainThread también permite que una aplicación determine si un bloque de código determinado se
ejecuta en el subproceso principal. La propiedad IsMainThread devuelve true si el código que llama a la
propiedad se ejecuta en el subproceso principal. Un programa puede usar esta propiedad para ejecutar
código diferente para el subproceso principal o secundario:

if (MainThread.IsMainThread)
{
// Code to run if this is the main thread
}
else
{
// Code to run if this is a secondary thread
}

Tal vez se pregunte si debe comprobar que el código se esté ejecutando en un subproceso secundario antes
de llamar a BeginInvokeOnMainThread , por ejemplo, de esta manera:

if (MainThread.IsMainThread)
{
MyMainThreadCode();
}
else
{
MainThread.BeginInvokeOnMainThread(MyMainThreadCode);
}

Quizás sospeche que esta comprobación puede mejorar el rendimiento si el bloque de código ya se ejecuta
en el subproceso principal.
Sin embargo, esta comprobación no es necesaria. Las implementaciones de plataforma de los
BeginInvokeOnMainThread mismos comprueban si la llamada se realiza en el subproceso principal. La
penalización de rendimiento si llama a BeginInvokeOnMainThread cuando no es realmente necesario es muy
pequeña.

API
Código fuente de MainThread
Documentación de API de MainThread
Xamarin.Essentials: Asignación
11/07/2019 • 3 minutes to read • Edit Online

La clase Map permite que una aplicación abra la aplicación de mapas instalada en una ubicación o marca de
posición específica.

Primeros pasos
Para empezar a usar esta API, lea la guía de introducción para Xamarin.Essentials con el fin de asegurarse de que
la biblioteca está correctamente instalada y configurada en los proyectos.

Uso de Map
Agregue una referencia a Xamarin.Essentials en su clase:

using Xamarin.Essentials;

Map funciona mediante una llamada al método OpenAsync con Location o Placemark abierto con
MapLaunchOptions opcional.

public class MapTest


{
public async Task NavigateToBuilding25()
{
var location = new Location(47.645160, -122.1306032);
var options = new MapLaunchOptions { Name = "Microsoft Building 25" };

await Map.OpenAsync(location, options);


}
}

Cuando se abre con Placemark , se requiere la siguiente información:


CountryName
AdminArea
Thoroughfare
Locality
public class MapTest
{
public async Task NavigateToBuilding25()
{
var placemark = new Placemark
{
CountryName = "United States",
AdminArea = "WA",
Thoroughfare = "Microsoft Building 25",
Locality = "Redmond"
};
var options = new MapLaunchOptions { Name = "Microsoft Building 25" };

await Map.OpenAsync(placemark, options);


}
}

Métodos de extensión.
Si ya tiene una referencia a Location o a Placemark , puede usar el método de extensión integrado OpenMapAsync
con MapLaunchOptions opcional:

public class MapTest


{
public async Task OpenPlacemarkOnMap(Placemark placemark)
{
await placemark.OpenMapAsync();
}
}

Modo de instrucciones
Si llama a OpenMapAsync sin MapLaunchOptions , el mapa se iniciará en la ubicación especificada. Si quiere, puede
hacer que se calcule una ruta de navegación desde la posición actual del dispositivo. Para ello, establezca
NavigationMode en MapLaunchOptions :

public class MapTest


{
public async Task NavigateToBuilding25()
{
var location = new Location(47.645160, -122.1306032);
var options = new MapLaunchOptions { NavigationMode = NavigationMode.Driving };

await Map.OpenAsync(location, options);


}
}

Diferencias entre plataformas


Android
iOS
UWP
NavigationMode admite Bicycling (Bicicleta), Driving (Automóvil) y Walking (A pie).

Detalles de implementación de la plataforma


Android
iOS
UWP
Android usa el esquema geo: de URI para iniciar la aplicación de mapas en el dispositivo. Esto podría pedirle al
usuario que seleccione de una aplicación existente que admite este esquema de URI. Xamarin.Essentials se probó
con Google Maps, que admite este esquema.

API
Código fuente de Map
Documentación de API para Map

Vídeo relacionado
Encuentre más vídeos de Xamarin en Channel 9 y YouTube.
Xamarin.Essentials: Explorador
11/07/2019 • 2 minutes to read • Edit Online

La clase Browser permite que una aplicación abra un vínculo web en el explorador optimizado preferido del
sistema o en el explorador externo.

Primeros pasos
Para empezar a usar esta API, lea la guía de introducción para Xamarin.Essentials con el fin de asegurarse de que
la biblioteca está correctamente instalada y configurada en los proyectos.

Uso de Browser
Agregue una referencia a Xamarin.Essentials en su clase:

using Xamarin.Essentials;

La funcionalidad Browser funciona mediante una llamada al método OpenAsync con Uri y BrowserLaunchMode .

public class BrowserTest


{
public async Task<bool> OpenBrowser(Uri uri)
{
return await Browser.OpenAsync(uri, BrowserLaunchMode.SystemPreferred);
}
}

Este método devuelve un valor después de que el usuario inicie el explorador, a veces sin que tenga que llegar a
cerrarlo. El resultado bool indica si el inicio ha sido correcto o no.

Personalización
Al usar el explorador preferido por el sistema, tiene disponibles varias opciones de personalización para iOS y
Android, por ejemplo, TitleMode (solo en Android), preferencias para las opciones de color para la Toolbar (en
iOS y Android) y Controls que se muestran (solo en iOS ).
Estas opciones se especifican usando BrowserLaunchOptions al llamar a OpenAsync .

await Browser.OpenAsync(uri, new BrowserLaunchOptions


{
LaunchMode = BrowserLaunchMode.SystemPreferred,
TitleMode = BrowserTitleMode.Show,
PreferredToolbarColor = Color.AliceBlue,
PreferredControlColor = Color.Violet
});
Detalles de implementación de la plataforma
Android
iOS
UWP
El modo de inicio determina cómo se inicia el explorador:

Preferencia del sistema


Se intentará usar las pestañas personalizadas de Chrome para cargar el URI y mantener el reconocimiento de la
navegación.

Externo
Se usará Intent para solicitar que se abra el URI a través del explorador normal del sistema.

API
Código fuente de Browser
Documentación de API para Browser

Vídeo relacionado

Encuentre más vídeos de Xamarin en Channel 9 y YouTube.


Xamarin.Essentials: OrientationSensor
11/07/2019 • 7 minutes to read • Edit Online

La clase OrientationSensor permite supervisar la orientación de un dispositivo en un espacio tridimensional.

NOTE
Esta clase se usa para determinar la orientación de un dispositivo en un espacio tridimensional. Si tiene que determinar si la
visualización de vídeo del dispositivo está en modo vertical u horizontal, use la propiedad Orientation del objeto
ScreenMetrics disponible en la clase DeviceDisplay .

Primeros pasos
Para empezar a usar esta API, lea la guía de introducción para Xamarin.Essentials con el fin de asegurarse de que
la biblioteca está correctamente instalada y configurada en los proyectos.

Uso de OrientationSensor
Agregue una referencia a Xamarin.Essentials en su clase:

using Xamarin.Essentials;

OrientationSensor se habilita mediante una llamada al método Start para supervisar los cambios en la
orientación del dispositivo y se deshabilita al llamar al método Stop . Los cambios se enviarán a través del evento
ReadingChanged . Este es un uso de ejemplo:
public class OrientationSensorTest
{
// Set speed delay for monitoring changes.
SensorSpeed speed = SensorSpeed.UI;

public OrientationSensorTest()
{
// Register for reading changes, be sure to unsubscribe when finished
OrientationSensor.ReadingChanged += OrientationSensor_ReadingChanged;
}

void OrientationSensor_ReadingChanged(object sender, OrientationSensorChangedEventArgs e)


{
var data = e.Reading;
Console.WriteLine($"Reading: X: {data.Orientation.X}, Y: {data.Orientation.Y}, Z:
{data.Orientation.Z}, W: {data.Orientation.W}");
// Process Orientation quaternion (X, Y, Z, and W)
}

public void ToggleOrientationSensor()


{
try
{
if (OrientationSensor.IsMonitoring)
OrientationSensor.Stop();
else
OrientationSensor.Start(speed);
}
catch (FeatureNotSupportedException fnsEx)
{
// Feature not supported on device
}
catch (Exception ex)
{
// Other error has occurred.
}
}
}

Las lecturas de OrientationSensor se informan como un Quaternion que describe la orientación del dispositivo
en función de dos sistemas de coordenadas tridimensionales:
El dispositivo (generalmente un teléfono o tableta) tiene un sistema de coordenadas tridimensional con los
siguientes ejes:
El eje X positivo apunta a la derecha de la visualización en modo vertical.
El eje Y positivo apunta a la parte de arriba del dispositivo en modo horizontal.
El eje Z positivo apunta fuera de la pantalla.
El sistema de coordenadas tridimensional de la Tierra tiene estos ejes:
El eje X positivo es tangente a la superficie de la Tierra y apunta al este.
El eje Y positivo también es tangente a la superficie de la Tierra y apunta al norte.
El eje Z positivo es perpendicular a la superficie de la Tierra y apunta hacia arriba.
Quaternion describe la rotación del sistema de coordenadas del dispositivo en relación con el sistema de
coordenadas de la Tierra.
Un valor Quaternion está estrechamente relacionado con la rotación alrededor de un eje. Si un eje de rotación es
el vector normalizado (ax, ay, az) y el ángulo de rotación es Θ, los componentes (X, Y, Z, W ) del cuaternión son:
(ax·sin(Θ/2), ay·sin(Θ/2), az·sin(Θ/2), cos(Θ/2))
x y z

Estos son los sistemas de coordenadas de la derecha por lo que, con el pulgar de la mano derecha apuntando en
la dirección positiva del eje de rotación, la curva de los dedos indica la dirección de la rotación de los ángulos
positivos.
Ejemplos:
Cuando el dispositivo está pantalla arriba sobre una mesa, con la parte superior del mismo (en el modo
vertical) apuntando al norte, los dos sistemas de coordenadas están alineados. El valor Quaternion
representa el cuaternión de identidad (0, 0, 0, 1). Todas las rotaciones se pueden analizar en relación con
esta posición.
Cuando el dispositivo está pantalla arriba sobre una mesa y la parte superior del mismo (en el modo
vertical) apunta al oeste, el valor de Quaternion es (0, 0, 0.707, 0.707). El dispositivo se giró 90 grados
alrededor del eje Z de la Tierra.
Cuando el dispositivo se sostiene de manera vertical, con la parte superior (en el modo vertical) apuntando
al cielo y la parte posterior orientada al norte, es porque el dispositivo se giró 90 grados alrededor del eje
X. El valor de Quaternion es (0.707, 0, 0, 0.707).
Si el dispositivo se coloca de manera tal que el borde izquierdo esté sobre una mesa y la parte superior
apunte al norte, es porque el dispositivo se giró –90 grados alrededor del eje Y (o 90 grados alrededor del
eje Y negativo). El valor de Quaternion es (0, -0.707, 0, 0.707).

Velocidad de sensor
Más rápido: obtener los datos del sensor tan rápido como sea posible (no se garantiza la devolución en el
subproceso de interfaz de usuario).
Juego: velocidad adecuada para juegos (no se garantiza la devolución en el subproceso de interfaz de
usuario).
Normal: velocidad predeterminada adecuada para los cambios de orientación de pantalla.
Interfaz de usuario: velocidad adecuada para la interfaz de usuario general.
Si no se garantiza la ejecución del controlador de eventos en el subproceso de interfaz de usuario y si el
controlador de eventos necesita tener acceso a elementos de la interfaz de usuario, use el método
MainThread.BeginInvokeOnMainThread para ejecutar ese código en el subproceso de interfaz de usuario.

API
Código fuente de OrientationSensor
Documentación de API de OrientationSensor
Xamarin.Essentials: Marcador telefónico
11/07/2019 • 2 minutes to read • Edit Online

La clase PhoneDialer permite que una aplicación abra un número de teléfono en el marcador telefónico.

Primeros pasos
Para empezar a usar esta API, lea la guía de introducción para Xamarin.Essentials con el fin de asegurarse de que
la biblioteca está correctamente instalada y configurada en los proyectos.

Uso del marcador telefónico


Agregue una referencia a Xamarin.Essentials en su clase:

using Xamarin.Essentials;

La funcionalidad de marcador telefónico funciona mediante una llamada al método Open con un número de
teléfono con el que abrir el marcador. Cuando se solicita Open , la API intentará automáticamente dar formato al
número en función del código de país, si se especifica.

public class PhoneDialerTest


{
public void PlacePhoneCall(string number)
{
try
{
PhoneDialer.Open(number);
}
catch (ArgumentNullException anEx)
{
// Number was null or white space
}
catch (FeatureNotSupportedException ex)
{
// Phone Dialer is not supported on this device.
}
catch (Exception ex)
{
// Other error has occurred.
}
}
}

API
Código fuente del marcador telefónico
Documentación de API para PhoneDialer
Xamarin.Essentials: extensiones de plataforma
11/07/2019 • 2 minutes to read • Edit Online

Xamarin.Essentials ofrece varios métodos de extensión de plataforma al trabajar con tipos de plataforma como
Rect, Size y Point. Esto significa que puede convertir la versión System de estos tipos a tipos específicos de iOS,
Android y UWP.

Primeros pasos
Para empezar a usar esta API, lea la guía de introducción para Xamarin.Essentials con el fin de asegurarse de que
la biblioteca está correctamente instalada y configurada en los proyectos.

Uso de las extensiones de plataforma


Agregue una referencia a Xamarin.Essentials en su clase:

using Xamarin.Essentials;

Todas las extensiones de plataforma solo se pueden llamar desde proyectos UWP, iOS o Android.
Punto

var system = new System.Drawing.Point(x, y);

// Convert to CoreGraphics.CGPoint, Android.Graphics.Point, and Windows.Foundation.Point


var platform = system.ToPlatformSize();

// Back to System.Drawing.Size
var system2 = platform.ToSystemSize();

Tamaño

var system = new System.Drawing.Size(width, height);

// Convert to CoreGraphics.CGSize, Android.Util.Size, and Windows.Foundation.Size


var platform = system.ToPlatformSize();

// Back to System.Drawing.Size
var system2 = platform.ToSystemSize();

Rectángulo

var system = new System.Drawing.Rectangle(x, y, width, height);

// Convert to CoreGraphics.CGRect, Android.Graphics.Rect, and Windows.Foundation.Rect


var platform = system.ToPlatformSize();

// Back to System.Drawing.Size
var system2 = platform.ToSystemSize();

API
Código fuente de los convertidores
Documentación sobre la API de los convertidores de puntos
Documentación sobre la API de los convertidores de rectángulos
Documentación sobre la API de los convertidores de tamaño
Xamarin.Essentials: Preferencias
11/07/2019 • 4 minutes to read • Edit Online

La clase Preferences ayuda a almacenar las preferencias de la aplicación en un almacén de clave y valor.

Primeros pasos
Para empezar a usar esta API, lea la guía de introducción para Xamarin.Essentials con el fin de asegurarse de que
la biblioteca está correctamente instalada y configurada en los proyectos.

Uso de Preferences
Agregue una referencia a Xamarin.Essentials en su clase:

using Xamarin.Essentials;

Para guardar un valor para una clave determinada en las preferencias:

Preferences.Set("my_key", "my_value");

Para recuperar un valor de las preferencias o un valor predeterminado si no se establece:

var myValue = Preferences.Get("my_key", "default_value");

Para quitar la clave de las preferencias:

Preferences.Remove("my_key");

Para quitar todas las preferencias:

Preferences.Clear();

Además de estos métodos, cada una toma un valor sharedName opcional que se puede usar para crear
contenedores adicionales para la preferencia. Lea los detalles de implementación de la plataforma a continuación.

Tipos de datos admitidos


En Preferences se admiten los tipos de datos siguientes:
bool
double
int
float
long
string
DateTime
Detalles de implementación
Los valores de DateTime se almacenan en un formato binario de 64 bits (entero largo) mediante dos métodos
definidos por la clase DateTime : El método ToBinary se usa para codificar el valor DateTime , mientras que el
método FromBinary descodifica el valor. Vea la documentación de estos métodos para obtener los ajustes que se
podrían realizar en los valores descodificados cuando se almacena un valor DateTime que no es de hora universal
coordinada (UTC ).

Detalles de implementación de la plataforma


Android
iOS
UWP
Todos los datos se almacenan en Preferencias compartidas. Si no se especifica ningún sharedName , se usan las
preferencias compartidas predeterminadas; en caso contrario, el nombre se usa para obtener una preferencia
compartida privada con el nombre especificado.

Persistencia
Al desinstalar la aplicación se quitarán todas las Preferencias. Hay una excepción, para las aplicaciones que se
destinan y se ejecutan en Android 6.0 (nivel de API 23) o versiones posteriores en las que se usa Copia de
seguridad automática. Esta característica está activada de forma predeterminada y conserva los datos de
aplicación, incluidas las preferencias compartidas, que son las que usa la API Preferences. Se puede
deshabilitar si se sigue la documentación de Google.

Limitaciones
Cuando se almacena una cadena, esta API está pensada para almacenar pequeñas cantidades de texto. El
rendimiento puede ser inferior si se intenta usar para almacenar grandes cantidades de texto.

API
Código fuente de Preferences
Documentación de API para Preferences

Vídeo relacionado
Encuentre más vídeos de Xamarin en Channel 9 y YouTube.
Xamarin.Essentials: Almacenamiento seguro
11/07/2019 • 8 minutes to read • Edit Online

La clase SecureStorage ayuda a almacenar pares de clave-valor sencillos de manera segura.

Primeros pasos
Para empezar a usar esta API, lea la guía de introducción para Xamarin.Essentials con el fin de asegurarse de que
la biblioteca está correctamente instalada y configurada en los proyectos.
Para acceder a la funcionalidad SecureStorage, se requiere la siguiente configuración específica para la
plataforma:
Android
iOS
UWP

TIP
Copia de seguridad para aplicaciones es una característica de Android 6.0 (nivel de API 23) y versiones posteriores que crea
copias de seguridad de los datos de aplicación del usuario (preferencias compartidas, archivos en el almacenamiento interno
de la aplicación y otros archivos específicos). Los datos se restauran cuando se reinstala o instala una aplicación en un
dispositivo nuevo. Esto puede afectar a SecureStorage , que utiliza las preferencias compartidas de las que se creó una
copia de seguridad y que no se pueden descifrar cuando se realiza la restauración. Xamarin.Essentials controla
automáticamente este caso al quitar la clave para que se pueda restablecer, pero puede dar un paso adicional si deshabilita
Copia de seguridad automática.

Habilitación o deshabilitación de copia de seguridad


Puede elegir deshabilitar Copia de seguridad automática para toda la aplicación al establecer el valor
android:allowBackup en false en el archivo AndroidManifest.xml . Este enfoque solo se recomienda si planea
restaurar los datos de otra manera.

<manifest ... >


...
<application android:allowBackup="false" ... >
...
</application>
</manifest>

Copia de seguridad selectiva


Es posible configurar Copia de seguridad automática para deshabilitar la copia de seguridad de contenido
específico. Puede crear un conjunto de reglas personalizadas para excluir los elementos SecureStore de la copia
de seguridad.
1. Establezca el atributo android:fullBackupContent en AndroidManifest.xml:

<application ...
android:fullBackupContent="@xml/auto_backup_rules">
</application>
2. Cree un archivo XML denominado auto_backup_rules.xml en el directorio Resources/xml con la acción
de compilación AndroidResource. Luego, establezca este contenido que incluye todas las preferencias
compartidas, excepto SecureStorage :

<?xml version="1.0" encoding="utf-8"?>


<full-backup-content>
<include domain="sharedpref" path="."/>
<exclude domain="sharedpref" path="${applicationId}.xamarinessentials.xml"/>
</full-backup-content>

Uso de Secure Storage


Agregue una referencia a Xamarin.Essentials en su clase:

using Xamarin.Essentials;

Para guardar un valor para una clave determinada en el almacenamiento seguro:

try
{
await SecureStorage.SetAsync("oauth_token", "secret-oauth-token-value");
}
catch (Exception ex)
{
// Possible that device doesn't support secure storage on device.
}

Para recuperar un valor desde el almacenamiento seguro:

try
{
var oauthToken = await SecureStorage.GetAsync("oauth_token");
}
catch (Exception ex)
{
// Possible that device doesn't support secure storage on device.
}

NOTE
Si no hay ningún valor asociado con la clave solicitada, GetAsync devolverá null .

Para quitar una clave específica, llame a:

SecureStorage.Remove("oauth_token");

Para quitar todas las claves, llame a:

SecureStorage.RemoveAll();

Detalles de implementación de la plataforma


Android
iOS
UWP
Android KeyStore se usa para almacenar la clave de cifrado con la que se cifra el valor antes de guardarlo en
Preferencias compartidas con un nombre de archivo [ID -PAQUETE -APLICACIÓN ].xamarinessentials. La
clave (no una clave criptográfica, la clave para el valor) usada en el archivo de preferencias compartido es un hash
MD5 de la clave pasada a las API SecureStorage .

Nivel de API 23 y superior


En los niveles de API más nuevos, una clave AES se obtiene de Android KeyStore y se usa con una cifra
AES/GCM/NoPadding para cifrar el valor antes de que se almacene en el archivo de preferencias compartidas.

Nivel de API 22 e inferior


En los niveles de API anteriores, Android KeyStore solo admite el almacenamiento de claves RSA, que se usa con
una cifra RSA/ECB/PKCS1Padding para cifrar una clave AES (generada de manera aleatoria en tiempo de
ejecución) y se almacena en el archivo de preferencias compartidas en la clave SecureStorageKey, si todavía no se
ha generado una.
SecureStorage usa la API Preferences y sigue la misma persistencia de datos que se describe en la
documentación sobre Preferencias. Si se actualiza un dispositivo desde Nivel de API 22 o inferior a Nivel de API
23 y superior, se seguirá usando este tipo de cifrado a menos que la aplicación se desinstale o se llame a
RemoveAll.

Limitaciones
Esta API está pensada para almacenar pequeñas cantidades de texto. El rendimiento puede ser lento si intenta
usarla para almacenar grandes cantidades de texto.

API
Código fuente de SecureStorage
Documentación de API de SecureStorage

Vídeo relacionado

Encuentre más vídeos de Xamarin en Channel 9 y YouTube.


Xamarin.Essentials: Compartir
11/07/2019 • 2 minutes to read • Edit Online

La clase Share permite que una aplicación comparta datos como texto y vínculos web con otras aplicaciones del
dispositivo.

Primeros pasos
Para empezar a usar esta API, lea la guía de introducción para Xamarin.Essentials con el fin de asegurarse de que
la biblioteca está correctamente instalada y configurada en los proyectos.

Uso de Share
Agregue una referencia a Xamarin.Essentials en su clase:

using Xamarin.Essentials;

Share funciona mediante una llamada al método RequestAsync con una carga de solicitud de datos que incluye
información para compartir con otras aplicaciones. Se pueden combinar texto y Uri, cada plataforma controlara el
filtrado basado en el contenido.

public class ShareTest


{
public async Task ShareText(string text)
{
await Share.RequestAsync(new ShareTextRequest
{
Text = text,
Title = "Share Text"
});
}

public async Task ShareUri(string uri)


{
await Share.RequestAsync(new ShareTextRequest
{
Uri = uri,
Title = "Share Web Link"
});
}
}

Interfaz de usuario para compartir con una aplicación externa que aparece cuando se realiza la solicitud:
Diferencias entre plataformas
Android
iOS
UWP
La propiedad Subject se usa para el asunto deseado de un mensaje.

Archivos

El uso compartido de archivos está disponible como versión preliminar experimental en Xamarin.Essentials
versión 1.1.0. Esta característica permite que una aplicación comparta archivos con otras aplicaciones del
dispositivo. Para habilitar esta característica, establezca la siguiente propiedad en el código de inicio de la
aplicación:

ExperimentalFeatures.Enable(ExperimentalFeatures.ShareFileRequest);

Una vez que se haya habilitado la característica, se puede compartir cualquier archivo. Xamarin.Essentials
detectará automáticamente el tipo de archivo (MIME ) y solicitará el uso compartido. Cada plataforma podría
admitir únicamente determinadas extensiones de archivo.
A continuación se muestra un ejemplo en el que se escribe texto en el disco y se comparte con otras aplicaciones:

var fn = "Attachment.txt";
var file = Path.Combine(FileSystem.CacheDirectory, fn);
File.WriteAllText(file, "Hello World");

await Share.RequestAsync(new ShareFileRequest


{
Title = Title,
File = new ShareFile(file)
});
API
Código fuente de Share
Documentación de API para Share

Vídeo relacionado
Encuentre más vídeos de Xamarin en Channel 9 y YouTube.
Xamarin.Essentials: SMS
11/07/2019 • 2 minutes to read • Edit Online

La clase SMS permite que una aplicación abra la aplicación SMS predeterminada con un mensaje especificado
para enviar un destinatario.

Primeros pasos
Para empezar a usar esta API, lea la guía de introducción para Xamarin.Essentials con el fin de asegurarse de que
la biblioteca está correctamente instalada y configurada en los proyectos.

Uso de SMS
Agregue una referencia a Xamarin.Essentials en su clase:

using Xamarin.Essentials;

La funcionalidad SMS funciona mediante una llamada al método ComposeAsync , un SmsMessage que contiene el
destinatario del mensaje y el cuerpo del mismo, ambos opcionales.

public class SmsTest


{
public async Task SendSms(string messageText, string recipient)
{
try
{
var message = new SmsMessage(messageText, new []{ recipient });
await Sms.ComposeAsync(message);
}
catch (FeatureNotSupportedException ex)
{
// Sms is not supported on this device.
}
catch (Exception ex)
{
// Other error has occurred.
}
}
}

Si quiere, puede pasar varios destinatarios a un SmsMessage :


public class SmsTest
{
public async Task SendSms(string messageText, string[] recipients)
{
try
{
var message = new SmsMessage(messageText, recipients);
await Sms.ComposeAsync(message);
}
catch (FeatureNotSupportedException ex)
{
// Sms is not supported on this device.
}
catch (Exception ex)
{
// Other error has occurred.
}
}
}

API
Código fuente de SMS
Documentación de API para SMS
Xamarin.Essentials: Texto a voz
11/07/2019 • 3 minutes to read • Edit Online

La clase TextToSpeech permite que una aplicación utilice los motores de texto a voz para responder a texto del
dispositivo y también para consultar los idiomas disponibles que el motor puede admitir.

Primeros pasos
Para empezar a usar esta API, lea la guía de introducción para Xamarin.Essentials con el fin de asegurarse de que
la biblioteca está correctamente instalada y configurada en los proyectos.

Uso de Text-to-Speech
Agregue una referencia a Xamarin.Essentials en su clase:

using Xamarin.Essentials;

Text-to-Speech funciona mediante una llamada al método SpeakAsync con parámetros opcionales y de texto y se
devuelve una vez que finaliza la declaración.

public async Task SpeakNowDefaultSettings()


{
await TextToSpeech.SpeakAsync("Hello World");

// This method will block until utterance finishes.


}

public void SpeakNowDefaultSettings2()


{
TextToSpeech.SpeakAsync("Hello World").ContinueWith((t) =>
{
// Logic that will run after utterance finishes.

}, TaskScheduler.FromCurrentSynchronizationContext());
}

Este método toma un elemento CancellationToken opcional para detener la declaración una vez que se inicia.
CancellationTokenSource cts;
public async Task SpeakNowDefaultSettings()
{
cts = new CancellationTokenSource();
await TextToSpeech.SpeakAsync("Hello World", cancelToken: cts.Token);

// This method will block until utterance finishes.


}

// Cancel speech if a cancellation token exists & hasn't been already requested.
public void CancelSpeech()
{
if (cts?.IsCancellationRequested ?? true)
return;

cts.Cancel();
}

Text-to-Speech pondrá automáticamente en la cola las solicitudes de voz del mismo subproceso.

bool isBusy = false;


public void SpeakMultiple()
{
isBusy = true;
Task.Run(async () =>
{
await TextToSpeech.SpeakAsync("Hello World 1");
await TextToSpeech.SpeakAsync("Hello World 2");
await TextToSpeech.SpeakAsync("Hello World 3");
isBusy = false;
});

// or you can query multiple without a Task:


Task.WhenAll(
TextToSpeech.SpeakAsync("Hello World 1"),
TextToSpeech.SpeakAsync("Hello World 2"),
TextToSpeech.SpeakAsync("Hello World 3"))
.ContinueWith((t) => { isBusy = false; }, TaskScheduler.FromCurrentSynchronizationContext());
}

Configuración de voz
Para más información sobre cómo se responde el audio, SpeechOptions permite ajustar el volumen, el tono y la
configuración regional.

public async Task SpeakNow()


{
var settings = new SpeechOptions()
{
Volume = .75f,
Pitch = 1.0f
};

await TextToSpeech.SpeakAsync("Hello World", settings);


}

Los siguientes son los valores compatibles para estos parámetros:

PARÁMETRO MÍNIMA MÁXIMO

Tono 0 2.0
PARÁMETRO MÍNIMA MÁXIMO

Volumen 0 1.0

Configuraciones regionales de voz


Cada plataforma admite distintas configuraciones regionales para responder texto en distintos idiomas y acentos.
Las plataformas tienen distintos códigos y formas de especificar la configuración regional, que es la razón por la
que Xamarin.Essentials proporciona una clase Locale multiplataforma y una manera de hacer consultas con
GetLocalesAsync .

public async Task SpeakNow()


{
var locales = await TextToSpeech.GetLocalesAsync();

// Grab the first locale


var locale = locales.FirstOrDefault();

var settings = new SpeechOptions()


{
Volume = .75f,
Pitch = 1.0f,
Locale = locale
};

await TextToSpeech.SpeakAsync("Hello World", settings);


}

Limitaciones
No se garantiza la cola de declaraciones si se llama a través de varios subprocesos.
La reproducción de audio en segundo plano no se admite de manera oficial.

API
Código fuente de TextToSpeech
Documentación de TextToSpeech API
Xamarin.Essentials: convertidores de unidades
11/07/2019 • 2 minutes to read • Edit Online

La clase UnitConverters proporciona varios convertidores de unidades para ayudar a los desarrolladores que
usan Xamarin.Essentials.

Primeros pasos
Para empezar a usar esta API, lea la guía de introducción para Xamarin.Essentials con el fin de asegurarse de que
la biblioteca está correctamente instalada y configurada en los proyectos.

Uso de convertidores de unidades


Agregue una referencia a Xamarin.Essentials en su clase:

using Xamarin.Essentials;

Todos los convertidores de unidades están disponibles mediante el uso de la clase estática UnitConverters de
Xamarin.Essentials. Por ejemplo, puede convertir fácilmente grados Fahrenheit a Celsius.

var celcius = UnitConverters.FahrenheitToCelsius(32.0);

Esta es una lista de las conversiones disponibles:


FahrenheitToCelsius
CelsiusToFahrenheit
CelsiusToKelvin
KelvinToCelsius
MilesToMeters
MilesToMeters
KilometersToMiles
DegreesToRadians
RadiansToDegrees
DegreesPerSecondToRadiansPerSecond
RadiansPerSecondToDegreesPerSecond
DegreesPerSecondToHertz
DegreesPerSecondToHertz
HertzToDegreesPerSecond
HertzToDegreesPerSecond
KilopascalsToHectopascals
HectopascalsToKilopascals
KilopascalsToPascals
HectopascalsToKilopascals
AtmospheresToPascals
PascalsToAtmospheres
CoordinatesToMiles
CoordinatesToKilometers

API
Código fuente de los convertidores de unidades
Documentación sobre la API de los convertidores de unidades
Xamarin.Essentials: Seguimiento de versiones
11/07/2019 • 2 minutes to read • Edit Online

La clase VersionTracking permite comprobar los números de versión y compilación de las aplicaciones además
de ver información adicional, por ejemplo si es la primera vez que se ha iniciado la aplicación o para la versión
actual, obtener información de la compilación anterior y mucho más.

Primeros pasos
Para empezar a usar esta API, lea la guía de introducción para Xamarin.Essentials con el fin de asegurarse de que
la biblioteca está correctamente instalada y configurada en los proyectos.

Uso de Seguimiento de versiones


Agregue una referencia a Xamarin.Essentials en su clase:

using Xamarin.Essentials;

La primera vez que use la clase VersionTracking, se iniciará el seguimiento de la versión actual. Solo se debe
llamar a Track al principio de la aplicación cada vez que se cargue para asegurarse de que se realiza el
seguimiento de la información de versión actual:

VersionTracking.Track();

Después de la llamada inicial a Track , se puede leer la información de la versión:


// First time ever launched application
var firstLaunch = VersionTracking.IsFirstLaunchEver;

// First time launching current version


var firstLaunchCurrent = VersionTracking.IsFirstLaunchForCurrentVersion;

// First time launching current build


var firstLaunchBuild = VersionTracking.IsFirstLaunchForCurrentBuild;

// Current app version (2.0.0)


var currentVersion = VersionTracking.CurrentVersion;

// Current build (2)


var currentBuild = VersionTracking.CurrentBuild;

// Previous app version (1.0.0)


var previousVersion = VersionTracking.PreviousVersion;

// Previous app build (1)


var previousBuild = VersionTracking.PreviousBuild;

// First version of app installed (1.0.0)


var firstVersion = VersionTracking.FirstInstalledVersion;

// First build of app installed (1)


var firstBuild = VersionTracking.FirstInstalledBuild;

// List of versions installed (1.0.0, 2.0.0)


var versionHistory = VersionTracking.VersionHistory;

// List of builds installed (1, 2)


var buildHistory = VersionTracking.BuildHistory;

Detalles de implementación de la plataforma


Toda la información de la versión se almacena mediante la API Preferences de Xamarin.Essentials y se almacena
con un nombre de archivo de [ID -DEL -PAQUETE -DE -LA -
APLICACIÓN ].xamarinessentials.versiontracking, y sigue la misma persistencia de datos que se describe en
la documentación de Preferences.

API
Código fuente de VersionTracking
Documentación de API para VersionTracking

Vídeo relacionado

Encuentre más vídeos de Xamarin en Channel 9 y YouTube.


Xamarin.Essentials: Vibración
11/07/2019 • 2 minutes to read • Edit Online

La clase Vibration permite iniciar y detener la funcionalidad de vibración durante un período de tiempo
determinado.

Primeros pasos
Para empezar a usar esta API, lea la guía de introducción para Xamarin.Essentials con el fin de asegurarse de que
la biblioteca está correctamente instalada y configurada en los proyectos.
Para acceder a la funcionalidad de Vibration, se requiere la siguiente configuración específica para la plataforma.
Android
iOS
UWP
El permiso Vibrate (Vibrar) es necesario y se debe configurar en el proyecto de Android. Se puede agregar de las
siguientes maneras:
Abra el archivo AssemblyInfo.cs de la carpeta Propiedades y agregue lo siguiente:

[assembly: UsesPermission(Android.Manifest.Permission.Vibrate)]

O BIEN, actualice el manifiesto de Android:


Abra el archivo AndroidManifest.xml de la carpeta Propiedades y agregue lo siguiente dentro del nodo
manifest.

<uses-permission android:name="android.permission.VIBRATE" />

O haga clic con el botón derecho en el proyecto de Android y abra las propiedades del proyecto. En Manifiesto
de Android, busque el área Permisos requeridos: y active el permiso VIBRATE (Vibrar). Esto actualizará
automáticamente el archivo AndroidManifest.xml.

Uso de Vibration
Agregue una referencia a Xamarin.Essentials en su clase:

using Xamarin.Essentials;

La funcionalidad de Vibration se puede solicitar para un período de tiempo concreto o el valor predeterminado de
500 milisegundos.
try
{
// Use default vibration length
Vibration.Vibrate();

// Or use specified time


var duration = TimeSpan.FromSeconds(1);
Vibration.Vibrate(duration);
}
catch (FeatureNotSupportedException ex)
{
// Feature not supported on device
}
catch (Exception ex)
{
// Other error has occurred.
}

Se puede solicitar la cancelación de la vibración del dispositivo con el método Cancel :

try
{
Vibration.Cancel();
}
catch (FeatureNotSupportedException ex)
{
// Feature not supported on device
}
catch (Exception ex)
{
// Other error has occurred.
}

Diferencias entre plataformas


Android
iOS
UWP
No hay diferencias entre las plataformas.

API
Código fuente de Vibration
Documentación de API para Vibration
Xamarin.Essentials: Solución de problemas
11/07/2019 • 2 minutes to read • Edit Online

Error: Se detectó un conflicto de versión para


Xamarin.Android.Support.Compat
El error siguiente se puede producir al actualizar paquetes NuGet (o agregar un paquete) nuevo con un proyecto
de Xamarin.Forms que usa Xamarin.Essentials:

NU1107: Version conflict detected for Xamarin.Android.Support.Compat. Reference the package directly from the
project to resolve this issue.
MyApp -> Xamarin.Essentials 1.1.0 -> Xamarin.Android.Support.CustomTabs 28.0.0.1 ->
Xamarin.Android.Support.Compat (= 28.0.0.1)
MyApp -> Xamarin.Forms 3.1.0.583944 -> Xamarin.Android.Support.v4 25.4.0.2 -> Xamarin.Android.Support.Compat
(= 25.4.0.2).

El problema es que no coinciden las dependencias de los dos paquetes NuGet. Esto se puede resolver agregando
de forma manual una versión específica de la dependencia (en este caso Xamarin.Android.Support.Compat)
que puede admitir los dos.
Para ello, agregue de forma manual el paquete NuGet que es el origen del conflicto y use la lista Versión para
seleccionar una versión específica. Actualmente, la versión 28.0.0.1 del paquete NuGet
Xamarin.Android.Support.Compat & Xamarin.Android.Support.Core.Util resolverá este error.
Consulte esta entrada de blog para obtener más información y ver un vídeo sobre cómo resolver el problema.
Si surge algún problema o encuentra un error, notifíquelo en el repositorio de Xamarin.Essentials de GitHub.
Datos y servicios en la nube
11/07/2019 • 2 minutes to read • Edit Online

Datos y servicios en la nube


Las aplicaciones de Xamarin.Android suelen necesitar acceso a datos (desde una base de datos local o desde la
nube), y muchas de estas aplicaciones consumen servicios web implementados utilizando una amplia variedad de
tecnologías. Las guías de esta sección examina cómo tener acceso a datos y hacer uso de servicios en la nube.

Acceso a datos
Esta sección describe el acceso a datos en Xamarin.Android usa SQLite como el motor de base de datos.

Mensajería de Google
Google Proporciona servicios de Google Cloud Messaging heredados para facilitar la mensajería entre
aplicaciones móviles y aplicaciones de servidor y Firebase Cloud Messaging. Esta sección proporciona información
general para cada servicio que proporciona una explicación paso a paso sobre cómo usar estos servicios para
implementar notificaciones remotas (también denominadas notificaciones push) en las aplicaciones de
Xamarin.Android.
Microsoft Azure Active Directory
11/07/2019 • 2 minutes to read • Edit Online

Azure Active Directory permite a los desarrolladores proteger los recursos como archivos, vínculos y las API Web,
Office 365 y más con la misma cuenta organizativa que los empleados usan para iniciar sesión en sus sistemas o
comprobar sus correos electrónicos.

Introducción
Siga el instrucciones de introducción para configurar el portal de Azure y agregar autenticación de Active Directory
a las aplicaciones de Xamarin.
1. Registrar con Azure Active Directory en el windowsazure.com portal, a continuación,
2. Configurar servicios.
3. Enlazar una de las siguientes:

Office 365
Una vez haya agregado la autenticación de Active Directory a una aplicación, también puede usar las credenciales
para interactuar con Office 365.

Graph API
Obtenga información sobre cómo obtener acceso a la Graph API con Xamarin (también se tratan en nuestra blog).
Azure Active Directory
11/07/2019 • 2 minutes to read • Edit Online

Registrar una aplicación para usar Azure Active Directory


Azure Active Directory permite a los desarrolladores a proteger los recursos como archivos, vínculos y API Web
con la misma cuenta organizativa que los empleados usan para iniciar sesión en sus sistemas o comprobar sus
correos electrónicos.
Desarrollo de aplicaciones móviles que pueden autenticarse con Azure Active Directory implica tres pasos. Los dos
primeros pasos suelen ser el mismo, independientemente de qué servicios que se va a usar. El tercer paso es
diferente para cada tipo de servicio:
1. Registrar con Azure Active Directory en el windowsazure.com portal, a continuación,
2. Configurar servicios.
3. Desarrollar aplicaciones móviles mediante los servicios.
Ejemplos de servicios diferentes que puede tener acceso a:
Graph API
Web API
Office365

Conclusión
Mediante los pasos anteriores puede autenticar sus aplicaciones móviles en Azure Active Directory. La biblioteca
de autenticación de Active Directory (ADAL ) facilita en gran medida con menos líneas de código, al tiempo que
mantiene la mayor parte del código de la misma y, por tanto, lo que puede compartir entre plataformas.

Vínculos relacionados
Microsoft NativeClient sample
Paso 1. Registrar una aplicación para usar Azure
Active Directory
13/07/2019 • 2 minutes to read • Edit Online

1. Vaya a windowsazure.com e inicie sesión con su cuenta de organización en el Portal de Azure o Account de
Microsoft. Si no tiene una suscripción de Azure, puede obtener una versión de prueba de azure.com
2. Después de iniciar sesión, vaya a la Active Directory sección (1) y elija el directorio donde desea registrar
la aplicación (2)

3. Haga clic en agregar para crear nueva aplicación, a continuación, seleccione agregar una aplicación que
mi organización está desarrollando

4. En la siguiente pantalla, asigne a la aplicación un nombre (p ej. XAM -DEMO ). Asegúrese de seleccionar
aplicación cliente nativa como el tipo de aplicación.
5. En la pantalla final, proporcione un *URI de redireccionamiento que es único para su aplicación como
devolverá a este URI cuando se completa la autenticación.

6. Una vez creada la aplicación, navegue hasta la configurar ficha. Anote el Id. de cliente que utilizaremos
en nuestra aplicación más adelante. Además, en esta pantalla puede permitir que la aplicación móvil tenga
acceso a Active Directory o agregar otra aplicación, como Office 365, que se puede usar la aplicación móvil
una vez completada la autenticación o de API Web.
Vínculos relacionados
Microsoft NativeClient sample
Paso 2. Configurar el acceso de servicio para
aplicaciones móviles
13/07/2019 • 2 minutes to read • Edit Online

Siempre que cualquier recurso, por ejemplo, la aplicación web, servicio web, etc. debe protegerse con Azure
Active Directory, deberá estar registrado. Se pueden ver todos los servicios o aplicaciones seguras en
aplicaciones ficha. Aquí puede seleccionar la aplicación que necesita para tener acceso desde aplicaciones
móviles y proporcionar acceso a él.
1. En el configurar pestaña, busque permisos para otras aplicaciones sección:

2. Haga clic en Agregar aplicación botón. En la siguiente pantalla emergente debería ver la lista de todas las
aplicaciones que están protegidos por Azure Active Directory. Seleccione las aplicaciones que necesita para
tener acceso desde la aplicación móvil.
3. Después de seleccionar la aplicación, seleccione una vez más la aplicación recién agregada en permisos
para otras aplicaciones sección y conceder los derechos adecuados.

4. Por último, guardar la configuración. Estos servicios deberían estar ahora disponibles en las aplicaciones
móviles.
Vínculos relacionados
Microsoft NativeClient sample
Acceso a Graph API
11/07/2019 • 5 minutes to read • Edit Online

Siga estos pasos para usar la API Graph desde dentro de una aplicación de Xamarin:
1. Registrar con Azure Active Directory en el windowsazure.com portal, a continuación,
2. Configurar servicios.

Paso 3. Adición de autenticación de Active Directory a una aplicación


En la aplicación, agregue una referencia a Azure Active Directory Authentication Library (ADAL de Azure)
con el Administrador de paquetes de NuGet en Visual Studio o Visual Studio para Mac. Asegúrese de seleccionar
mostrar los paquetes preliminares para incluir este paquete, ya que es aún en versión preliminar.

IMPORTANT
Nota: 3.0 ADAL Azure actualmente es una versión preliminar y puede haber cambios importantes antes de que se publique
la versión final.

En la aplicación, ahora deberá agregar las siguientes variables de nivel de clase que son necesarias para el flujo de
autenticación.
//Client ID
public static string clientId = "25927d3c-.....-63f2304b90de";
public static string commonAuthority = "https://login.windows.net/common"
//Redirect URI
public static Uri returnUri = new Uri("http://xam-demo-redirect");
//Graph URI if you've given permission to Azure Active Directory
const string graphResourceUri = "https://graph.windows.net";
public static string graphApiVersion = "2013-11-08";
//AuthenticationResult will hold the result after authentication completes
AuthenticationResult authResult = null;

Hay que destacar aquí es commonAuthority . Cuando el punto de conexión de autenticación es common , la aplicación
se convierte en multiinquilino, lo que significa que cualquier usuario puede utilizar inicio de sesión con sus
credenciales de Active Directory. Después de la autenticación, dicho usuario funcionará en el contexto de su
propio Active Directory: es decir, verá los detalles relacionados con su Active Directory.
Método para adquirir un Token de acceso de escritura
El código siguiente (para Android), inicie la autenticación y la finalización asignará el resultado en authResult . Las
implementaciones de Windows Phone y iOS difieren ligeramente: el segundo parámetro ( Activity ) es diferente
en iOS y no están presentes en Windows Phone.

public static async Task<AuthenticationResult> GetAccessToken


(string serviceResourceId, Activity activity)
{
authContext = new AuthenticationContext(Authority);
if (authContext.TokenCache.ReadItems().Count() > 0)
authContext = new AuthenticationContext(authContext.TokenCache.ReadItems().First().Authority);
var authResult = await authContext.AcquireTokenAsync(serviceResourceId, clientId, returnUri, new
AuthorizationParameters(activity));
return authResult;
}

En el código anterior, el AuthenticationContext es responsable de la autenticación con commonAuthority. Tiene


un AcquireTokenAsync método, que toman parámetros como un recurso que debe tener acceso, en este caso
graphResourceUri , clientId , y returnUri . La aplicación volverá a la returnUri cuando se completa la
autenticación. Este código seguirá siendo el mismo para todas las plataformas, sin embargo, el último parámetro,
AuthorizationParameters , serán diferentes en distintas plataformas y es responsable de la que rige el flujo de
autenticación.
En el caso de Android o iOS, pasamos this parámetro AuthorizationParameters(this) para compartir el
contexto, mientras que en Windows que se pasa sin ningún parámetro como nuevo AuthorizationParameters() .
Identificador de continuación para Android
Una vez completada la autenticación, el flujo debe volver a la aplicación. En el caso de Android se controla
mediante el código siguiente, que deben agregarse a MainActivity.cs:

protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)


{
base.OnActivityResult(requestCode, resultCode, data);
AuthenticationAgentContinuationHelper.SetAuthenticationAgentContinuationEventArgs(requestCode, resultCode,
data);

Identificador de continuación para Windows Phone


Para Windows Phone, modifique la OnActivated método en el App.xaml.cs archivo con el siguiente código:

protected override void OnActivated(IActivatedEventArgs args)


{
#if WINDOWS_PHONE_APP
if (args is IWebAuthenticationBrokerContinuationEventArgs)
{
WebAuthenticationBrokerContinuationHelper.SetWebAuthenticationBrokerContinuationEventArgs(args as
IWebAuthenticationBrokerContinuationEventArgs);
}
#endif
base.OnActivated(args);
}

Ahora si ejecuta la aplicación, debería ver un cuadro de diálogo de autenticación. Tras una autenticación correcta,
se le pedirá sus permisos para tener acceso a los recursos (en nuestro caso, Graph API):

Si la autenticación se realiza correctamente y ha autorizado la aplicación para tener acceso a los recursos, debe
obtener un AccessToken y RefreshToken combinado en authResult . Estos tokens son necesarios para aún más las
llamadas de API y autorización con Azure Active Directory en segundo plano.
Por ejemplo, el código siguiente permite obtener una lista de usuarios de Active Directory. Puede reemplazar la
dirección URL de API Web con la API Web que está protegida por Azure AD.

var client = new HttpClient();


var request = new HttpRequestMessage(HttpMethod.Get,
"https://graph.windows.net/tendulkar.onmicrosoft.com/users?api-version=2013-04-05");
request.Headers.Authorization =
new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
var response = await client.SendAsync(request);
var content = await response.Content.ReadAsStringAsync();
Microsoft Azure Mobile Apps
16/08/2019 • 3 minutes to read • Edit Online

Ejemplos y descargas de código para la documentación de Azure Portal.


Estos vínculos son para la documentación de Xamarin disponible en el sitio web de Azure Mobile Apps . Agregar la
funcionalidad de Azure a una aplicación de Xamarin mediante la descarga del cliente móvil de Azure.

Trabajar con el componente de Azure de Xamarin


Documentación general sobre cómo trabajar con la biblioteca de cliente de Xamarin (componente) para realizar
diversas tareas con Azure Mobile Apps. Esta página contiene muchos fragmentos de código de ejemplo, sin las
explicaciones y los ejemplos detallados disponibles en cada uno de los artículos del tutorial que se enumeran a
continuación.

Introducción
En este artículo se proporcionan instrucciones paso a paso para poner en marcha su primera aplicación de
Xamarin Azure. Describe la creación de una nueva aplicación móvil de Azure en el portal y, después, la descarga y
ejecución de la aplicación preconfigurada.
iOS
Android
Xamarin.Forms

Introducción a los usuarios


Proporciona instrucciones completas para configurar y codificar una pantalla de inicio de sesión con Azure Mobile
Services. Entre los proveedores de autenticación admitidos se incluyen Microsoft, Google, Facebook y Twitter.
iOS
Android

Autorización de usuarios en scripts


Código de ejemplo de back-ends de JavaScript
Todo.js

Introducción a la instalación
Complete las instrucciones para configurar las notificaciones de envío en los sitios web de Apple y Google y envíe
una notificación de envío desde Azure Mobile Services a un dispositivo.
iOS
Android

Introducción a Notification Hubs


Complete las instrucciones para configurar las notificaciones de envío en los sitios web de Apple y Google,
configure el centro de notificaciones de Azure y, después, genere notificaciones de envío a los dispositivos.
iOS
Android

Vínculos relacionados
GettingStarted (ejemplo)
GetStartedWithData (ejemplo)
GetStartedWithUsers (ejemplo)
GetStartedWithPush (ejemplo)
NotificationHubs (ejemplo)
Cliente móvil de Azure
Ruta de aprendizaje de Azure Mobile Apps
Acceso a datos de Xamarin.Android
11/07/2019 • 3 minutes to read • Edit Online

Mayoría de las aplicaciones tiene algún requisito para guardar los datos en el dispositivo de forma local. A menos
que la cantidad de datos pequeña, esto normalmente requiere una base de datos y una capa de datos en la
aplicación para administrar el acceso de la base de datos. Android tiene el motor de base de datos de SQLite
'integrado' y acceso para almacenar y recuperar los datos se simplifica mediante la plataforma de Xamarin. Este
documento muestra cómo obtener acceso a una base de datos de SQLite de forma multiplataforma.

Información general sobre el acceso de datos


Mayoría de las aplicaciones tiene algún requisito para guardar los datos en el dispositivo de forma local. A menos
que la cantidad de datos pequeña, esto normalmente requiere una base de datos y una capa de datos en la
aplicación para administrar el acceso de la base de datos. Android ambos tiene el motor de base de datos de
SQLite "integrado" y el acceso a los datos se simplifica mediante la plataforma de Xamarin que se incluye con el
proveedor de datos de SQLite.
Xamarin.Android admite las API de acceso de base de datos, como:
Marco de trabajo ADO.NET.
Biblioteca de terceros 3rd SQLite-NET.
La mayoría del código en esta sección es completamente multiplataforma y se ejecuta en iOS o Android sin
modificaciones. Hay dos aplicaciones de ejemplo descritas:
DataAccess_Basic – las operaciones de datos Simple escribe los resultados en un texto de mostrarán el
control;
DataAccess_Advanced – integra las operaciones de datos en una pequeña aplicación de trabajo que
muestra y edita una estructura de datos simple.
Ambas soluciones de ejemplo contienen proyectos de aplicación de ejemplo de Android y iOS.
Para las aplicaciones de Xamarin.Forms, lea trabajar con bases de datos que explica cómo trabajar con SQLite en
una biblioteca PCL con Xamarin.Forms.
Los temas de esta sección describen el acceso a datos en Xamarin.Android usa SQLite como el motor de base de
datos. Se puede tener acceso a la base de datos "directamente" mediante la sintaxis ADO.NET o puede incluir el
SQLite.NET ORM y realizar operaciones de datos en C#.
Se revisan los dos ejemplos: uno que contiene el código de acceso a datos muy simple que salidas para un campo
de texto y una aplicación simple que incluye creación, leer, actualizar y eliminar funciones. También se analiza el
subprocesamiento y cómo inicializar la aplicación con una base de datos de SQLite rellenada previamente.
Para obtener ejemplos adicionales de acceso a datos multiplataforma, consulte nuestra Tasky Pro caso práctico.

Vínculos relacionados
DataAccess Basic (ejemplo)
DataAccess avanzada (ejemplo)
Recetas de datos de Android
Acceso a datos de Xamarin.Forms
Introducción
16/08/2019 • 7 minutes to read • Edit Online

Cuándo usar una base de datos


Aunque las capacidades de almacenamiento y procesamiento de los dispositivos móviles están aumentando, los
teléfonos y las tabletas siguen retrasando sus homólogos de escritorio y portátiles. Por esta razón, merece la pena
dedicar algún tiempo a planear la arquitectura de almacenamiento de datos de la aplicación en lugar de asumir
simplemente que una base de datos es la respuesta correcta en todo momento. Hay varias opciones diferentes que
se adaptan a diferentes requisitos, como:
Preferencias : Android ofrece un mecanismo integrado para almacenar pares de datos de clave-valor simples.
Si va a almacenar una configuración de usuario simple o pequeñas partes de datos (como información de
personalización), use las características nativas de la plataforma para almacenar este tipo de información.
Archivos de texto : datos proporcionados por el usuario o memorias caché del contenido descargado (por
ejemplo, HTML ) se puede almacenar directamente en el sistema de archivos. Use una Convención de
nomenclatura de archivos adecuada para ayudarle a organizar los archivos y a encontrar los datos.
Archivos de datos serializados: los objetos se pueden almacenar como XML o JSON en el sistema de
archivos. .NET Framework incluye bibliotecas que facilitan la serialización y la deserialización de objetos. Use los
nombres adecuados para organizar los archivos de datos.
Base de datos: el motor de base de datos SQLite está disponible en la plataforma Android y es útil para
almacenar datos estructurados que necesita consultar, ordenar o manipular de otra manera. El almacenamiento
de base de datos es adecuado para listas de datos con muchas propiedades.
Archivos de imagen : aunque es posible almacenar datos binarios en la base de datos en un dispositivo móvil,
se recomienda almacenarlos directamente en el sistema de archivos. Si es necesario, puede almacenar los
nombres de archivo en una base de datos para asociar la imagen a otros datos. Cuando se trabaja con imágenes
de gran tamaño, o muchas imágenes, es recomendable planear una estrategia de almacenamiento en caché que
elimine los archivos que ya no necesita para evitar consumir todo el espacio de almacenamiento del usuario.
Si una base de datos es el mecanismo de almacenamiento adecuado para su aplicación, en el resto de este
documento se explica cómo usar SQLite en la plataforma de Xamarin.

Ventajas del uso de una base de datos


Hay varias ventajas en el uso de una base de datos SQL en la aplicación móvil:
Las bases de datos SQL permiten un almacenamiento eficaz de datos estructurados.
Los datos específicos se pueden extraer con consultas complejas.
Los resultados de la consulta se pueden ordenar.
Los resultados de la consulta se pueden agregar.
Los desarrolladores con conocimientos de bases de datos existentes pueden aprovechar sus conocimientos para
diseñar la base de datos y el código de acceso a datos.
El modelo de datos del componente de servidor de una aplicación conectada se puede volver a usar (en su
totalidad o en parte) en la aplicación móvil.

Motor de base de datos SQLite


SQLite es un motor de base de datos de código abierto adoptado por Google para su plataforma móvil. El motor
de base de datos de SQLite está integrado en ambos sistemas operativos, por lo que no hay trabajo adicional para
que los desarrolladores puedan aprovecharlo. SQLite es idóneo para el desarrollo móvil multiplataforma porque:
El motor de base de datos es pequeño, rápido y fácil de transportar.
Una base de datos se almacena en un único archivo, que es fácil de administrar en dispositivos móviles.
El formato de archivo es fácil de usar entre plataformas: si se trata de sistemas de 32 o 64 bits y de Big-Endian.
Implementa la mayor parte del estándar SQL92.
Dado que SQLite está diseñado para ser pequeño y rápido, hay algunas advertencias sobre su uso:
No se admiten algunas sintaxis de combinación externa.
Solo se admiten Rename de tabla y ADDCOLUMN. No se pueden realizar otras modificaciones en el esquema.
Las vistas son de solo lectura.
Puede obtener más información acerca de SQLite en el sitio Web- SQLite.org ; sin embargo, toda la información
que necesita para usar SQLite con Xamarin se incluye en este documento y en los ejemplos asociados. El motor de
base de datos SQLite se admitía en Android desde Android 2. Aunque no se trata en este capítulo, SQLite también
está disponible para su uso en Windows Phone y aplicaciones Windows.

Windows y Windows Phone


SQLite también puede usarse en plataformas Windows, aunque dichas plataformas no se describen en este
documento. Lea más en la tarea y en los casos prácticos de Pro con tareas y revise el blog de Tim Heuer.

Vínculos relacionados
Acceso a datos básico (ejemplo)
Acceso a la configuración avanzada (ejemplo)
Recetas de datos de Android
Acceso a datos de Xamarin. Forms
Configuración
11/07/2019 • 3 minutes to read • Edit Online

Usar SQLite en la aplicación de Xamarin.Android que necesita para determinar la ubicación de archivo correcto
para el archivo de base de datos.

Ruta de acceso de archivo de base de datos


Independientemente de qué método de acceso de datos que use, debe crear un archivo de base de datos antes de
que se pueden almacenar datos con SQLite. Dependiendo de la plataforma de destino es la ubicación del archivo
será diferente. Para Android puede usar Environment (clase) para construir una ruta válida, como se muestra en el
siguiente fragmento de código:

string dbPath = Path.Combine (


Environment.GetFolderPath (Environment.SpecialFolder.Personal),
"database.db3");
// dbPath contains a valid file path for the database file to be stored

Hay otras cosas a tener en cuenta al decidir dónde se almacenará el archivo de base de datos. Por ejemplo, en
Android puede elegir si desea utilizar almacenamiento interno o externo.
Si desea usar una ubicación diferente en cada plataforma en la aplicación de plataforma cruzada puede usar una
directiva de compilador tal como se muestra para generar una ruta de acceso diferente para cada plataforma:

var sqliteFilename = "MyDatabase.db3";


#if __ANDROID__
// Just use whatever directory SpecialFolder.Personal returns
string libraryPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal); ;
#else
// we need to put in /Library/ on iOS5.1 to meet Apple's iCloud terms
// (they don't want non-user-generated data in Documents)
string documentsPath = Environment.GetFolderPath (Environment.SpecialFolder.Personal); // Documents folder
string libraryPath = Path.Combine (documentsPath, "..", "Library"); // Library folder instead
#endif
var path = Path.Combine (libraryPath, sqliteFilename);

Para obtener indicaciones sobre el uso del sistema de archivos en Android, consulte el examinar archivos receta.
Consulte la Building Cross Platform Applications documento para obtener más información sobre el uso de
directivas de compilador para escribir código específico para cada plataforma.

Subprocesos
No se debe usar la misma conexión de base de datos de SQLite en varios subprocesos. Tenga cuidado al abrir, usar
y, a continuación, cierre las conexiones que se crea en el mismo subproceso.
Para asegurarse de que el código no está intentando obtener acceso a la base de datos de SQLite desde varios
subprocesos al mismo tiempo, realizar un bloqueo manualmente cada vez que se va a obtener acceso a la base de
datos, similar al siguiente:
object locker = new object(); // class level private field
// rest of class code
lock (locker){
// Do your query or insert here
}

Todos los accesos de base de datos (lecturas, escrituras, actualizaciones, etc.) deben incluirse con el mismo bloqueo.
Debe tener cuidado para evitar una situación de interbloqueo, asegúrese de que el trabajo dentro de la cláusula de
bloqueo se mantiene simple y no llamar a otros métodos que también se pueden realizar un bloqueo.

Vínculos relacionados
DataAccess Basic (ejemplo)
DataAccess avanzada (ejemplo)
Recetas de datos de Android
Acceso a datos de Xamarin.Forms
Uso de SQLite.NET con Android
16/08/2019 • 13 minutes to read • Edit Online

La biblioteca SQLite.NET que Xamarin recomienda es un ORM muy básico que le permite almacenar y recuperar
fácilmente objetos en la base de datos SQLite local en un dispositivo Android. ORM representa la asignación –
relacional de objetos API que permite guardar y recuperar "objetos" de una base de datos sin escribir instrucciones
SQL.
Para incluir la biblioteca de SQLite.NET en una aplicación de Xamarin, agregue el siguiente paquete de NuGet al
proyecto:
Nombre del paquete: SQLite-net-PCL
Autor: Frank A. Krueger
Id.: sqlite-net-pcl
Url: nuget.org/packages/sqlite-net-pcl

TIP
Hay varios paquetes de SQLite disponibles: Asegúrese de elegir el correcto (puede que no sea el resultado superior en la
búsqueda).

Una vez que tenga la biblioteca SQLite.NET disponible, siga estos tres pasos para usarla para tener acceso a una
base de datos:
1. Agregar una instrucción using Agregue la siguiente instrucción a los C# archivos en los que se requiere
acceso a los datos: –

using SQLite;

2. Crear una base de datos en blanco – Se puede crear una referencia de base de datos pasando la ruta de
acceso del archivo al constructor de la clase SQLiteConnection. No es necesario comprobar si el archivo ya
existe – , se creará automáticamente si es necesario; de lo contrario, se abrirá el archivo de base de datos
existente. La dbPath variable se debe determinar según las reglas descritas anteriormente en este
documento:

var db = new SQLiteConnection (dbPath);


3. Guardar datos – Una vez que haya creado un objeto SQLiteConnection, los comandos de base de datos se
ejecutan llamando a sus métodos, como createTable e insertan de la siguiente manera:

db.CreateTable<Stock> ();
db.Insert (newStock); // after creating the newStock object

4. Recuperación de datos – Para recuperar un objeto (o una lista de objetos), use la sintaxis siguiente:

var stock = db.Get<Stock>(5); // primary key id of 5


var stockList = db.Table<Stock>();

Ejemplo de acceso a datos básico


El código de ejemplo DataAccess_Basic de este documento tiene este aspecto cuando se ejecuta en Android. En el
código se muestra cómo realizar operaciones simples de SQLite.NET y se muestra el resultado como texto en la
ventana principal de la aplicación.
Android

En el ejemplo de código siguiente se muestra una interacción completa de la base de datos mediante la biblioteca
SQLite.NET para encapsular el acceso a la base de datos subyacente. Muestra lo siguiente:
1. Crear el archivo de base de datos
2. Inserción de datos mediante la creación de objetos y su almacenamiento
3. Consultar los datos
Deberá incluir estos espacios de nombres:

using SQLite; // from the github SQLite.cs class

La última requiere que haya agregado SQLite al proyecto. Tenga en cuenta que la tabla de base de datos SQLite se
define agregando atributos Stock a una clase (la clase) en lugar de un comando CREATE TABLE.
[Table("Items")]
public class Stock {
[PrimaryKey, AutoIncrement, Column("_id")]
public int Id { get; set; }
[MaxLength(8)]
public string Symbol { get; set; }
}
public static void DoSomeDataAccess () {
Console.WriteLine ("Creating database, if it doesn't already exist");
string dbPath = Path.Combine (
Environment.GetFolderPath (Environment.SpecialFolder.Personal),
"ormdemo.db3");
var db = new SQLiteConnection (dbPath);
db.CreateTable<Stock> ();
if (db.Table<Stock> ().Count() == 0) {
// only insert the data if it doesn't already exist
var newStock = new Stock ();
newStock.Symbol = "AAPL";
db.Insert (newStock);
newStock = new Stock ();
newStock.Symbol = "GOOG";
db.Insert (newStock);
newStock = new Stock ();
newStock.Symbol = "MSFT";
db.Insert (newStock);
}
Console.WriteLine("Reading data");
var table = db.Table<Stock> ();
foreach (var s in table) {
Console.WriteLine (s.Id + " " + s.Symbol);
}
}

El uso [Table] del atributo sin especificar un parámetro de nombre de tabla hará que la tabla de base de datos
subyacente tenga el mismo nombre que la clase (en este caso, "stock"). El nombre de tabla real es importante si
escribe consultas SQL directamente en la base de datos en lugar de usar los métodos de acceso a datos de ORM.
Del mismo [Column("_id")] modo, el atributo es opcional y, si no está presente, se agregará una columna a la tabla
con el mismo nombre que la propiedad de la clase.

Atributos de SQLite
Los atributos comunes que se pueden aplicar a las clases para controlar cómo se almacenan en la base de datos
subyacente incluyen:
[PrimaryKey] – Este atributo se puede aplicar a una propiedad de entero para obligarlo a ser la clave
principal de la tabla subyacente. No se admiten las claves principales compuestas.
[Incremento automático] – Este atributo hará que el valor de una propiedad de entero se incremente
automáticamente para cada nuevo objeto insertado en la base de datos.
[Column (Name)] Si se proporciona name el parámetro opcional, se invalidará el valor predeterminado
del nombre de la columna de base de datos subyacente (que es igual que la propiedad). –
[Tabla (nombre)] – Marca la clase como capaz de almacenarse en una tabla subyacente de SQLite. Si se
especifica el parámetro de nombre opcional, se invalidará el valor predeterminado del nombre de la tabla de
base de datos subyacente (que es igual que el nombre de clase).
[MaxLength (valor)] – Restrinja la longitud de una propiedad de texto cuando se intente realizar una
inserción de base de datos. El consumo de código debe validar esto antes de insertar el objeto, ya que este
atributo solo es ' checked ' cuando se intenta realizar una operación de actualización o inserción de base de
datos.
[Omitir] – Hace que SQLite.net omita esta propiedad. Esto es especialmente útil para las propiedades que
tienen un tipo que no se puede almacenar en la base de datos, o propiedades que modelan recopilaciones
que no se pueden resolver automáticamente mediante SQLite.
[Único] – Garantiza que los valores de la columna de base de datos subyacente son únicos.

La mayoría de estos atributos son opcionales, SQLite usará los valores predeterminados para los nombres de tabla
y columna. Siempre debe especificar una clave principal de tipo entero para que las consultas de selección y
eliminación se puedan realizar de forma eficaz en los datos.

Consultas más complejas


Los siguientes métodos de SQLiteConnection se pueden usar para realizar otras operaciones de datos:
Insertar – Agrega un nuevo objeto a la base de datos.
Obtener<T>intentarecuperar un objeto mediantelaclaveprincipal– .
La<tablaT> devuelve– todos los objetos de la tabla.
Eliminar – Elimina un objeto utilizando su clave principal.
Query<T>realizauna consulta SQL quedevuelveunnúmerodefilas(comoobjetos).–
Ejecutar Use este método (y no Query ) cuando no espere filas de SQL (como las instrucciones INSERT,
Update y Delete). –
Obtener un objeto por la clave principal
SQLite.Net proporciona el método get para recuperar un solo objeto basado en su clave principal.

var existingItem = db.Get<Stock>(3);

Seleccionar un objeto mediante Linq


Los métodos que devuelven la compatibilidad con IEnumerable<T> colecciones, por lo que puede usar LINQ para
consultar u ordenar el contenido de una tabla. En el código siguiente se muestra un ejemplo de uso de LINQ para
filtrar todas las entradas que comienzan por la letra "A":

var apple = from s in db.Table<Stock>()


where s.Symbol.StartsWith ("A")
select s;
Console.WriteLine ("-> " + apple.FirstOrDefault ().Symbol);

Seleccionar un objeto mediante SQL


Aunque SQLite.Net puede proporcionar acceso basado en objetos a los datos, a veces es posible que tenga que
realizar una consulta más compleja de lo que permite LINQ (o puede necesitar un rendimiento más rápido). Puede
usar comandos SQL con el método de consulta, como se muestra aquí:

var stocksStartingWithA = db.Query<Stock>("SELECT * FROM Items WHERE Symbol = ?", "A");


foreach (var s in stocksStartingWithA) {
Console.WriteLine ("a " + s.Symbol);
}
NOTE
Al escribir instrucciones SQL directamente, se crea una dependencia de los nombres de las tablas y columnas de la base de
datos, que se han generado a partir de las clases y sus atributos. Si cambia estos nombres en el código, debe recordar
actualizar las instrucciones SQL escritas manualmente.

Eliminar un objeto
La clave principal se usa para eliminar la fila, como se muestra aquí:

var rowcount = db.Delete<Stock>(someStock.Id); // Id is the primary key

Puede comprobar el para rowcount confirmar el número de filas afectadas (eliminadas en este caso).

Usar SQLite.NET con varios subprocesos


SQLite admite tres modos de subprocesamiento diferentes: Subproceso único, multiprocesoy serializado. Si desea
tener acceso a la base de datos desde varios subprocesos sin restricciones, puede configurar SQLite para usar el
modo de subproceso serializado. Es importante establecer este modo pronto en la aplicación (por ejemplo, al
principio del OnCreate método).
Para cambiar el modo de subprocesos SqliteConnection.SetConfig , llame a. Por ejemplo, esta línea de código
configura SQLite para el modo de serialización:

using using Mono.Data.Sqlite;


...
SqliteConnection.SetConfig(SQLiteConfig.Serialized);

La versión de Android de SQLite tiene una limitación que requiere algunos pasos más. Si la llamada a
SqliteConnection.SetConfig genera una excepción de SQLite library used incorrectly como, debe usar la
siguiente solución alternativa:
1. Vínculo a la biblioteca libsqlite.so nativa para que las sqlite3_shutdown API sqlite3_initialize y estén
disponibles para la aplicación:

[DllImport("libsqlite.so")]
internal static extern int sqlite3_shutdown();

[DllImport("libsqlite.so")]
internal static extern int sqlite3_initialize();

2. Al principio del método, agregue OnCreate este código al cierre de SQLite, configúrelo para el modo de
serialización y reinicialice SQLite:

using using Mono.Data.Sqlite;


...
sqlite3_shutdown();
SqliteConnection.SetConfig(SQLiteConfig.Serialized);
sqlite3_initialize();

Esta solución alternativa también funciona para Mono.Data.Sqlite la biblioteca. Para obtener más información
acerca de SQLite y multithreading, consulte SQLite y variossubprocesos.
Vínculos relacionados
Acceso a datos básico (ejemplo)
Acceso a la configuración avanzada (ejemplo)
Acceso a datos de Xamarin. Forms
Uso de ADO.NET con Android
16/08/2019 • 9 minutes to read • Edit Online

Xamarin tiene compatibilidad integrada para la base de datos SQLite que está disponible en Android y se puede
exponer con la conocida sintaxis de ADO.NET. El uso de estas API requiere la escritura de instrucciones SQL
procesadas por SQLite, como CREATE TABLE , INSERT y SELECT las instrucciones.

Referencias de ensamblado
Para usar Access SQLite a través de ADO.net, System.Data debe Mono.Data.Sqlite agregar referencias y a su
proyecto de Android, como se muestra aquí:
Visual Studio
Visual Studio para Mac

Haga clic con el botón secundario en referencias > Editar referencias... y, a continuación, haga clic para
seleccionar los ensamblados necesarios.

Acerca de mono. Data. SQLite


Usaremos la Mono.Data.Sqlite.SqliteConnection clase para crear un archivo de base de datos en blanco y,
SqliteCommand a continuación, crear una instancia de los objetos que se pueden usar para ejecutar instrucciones
SQL en la base de datos.
Crear una base de datos vacía – Llame al CreateFile método con una ruta de acceso de archivo válida (es decir,
grabable). Debe comprobar si el archivo ya existe antes de llamar a este método; de lo contrario, se creará una
nueva base de datos (en blanco) en la parte superior de la antigua y se perderán los datos del archivo anterior.
Mono.Data.Sqlite.SqliteConnection.CreateFile (dbPath); La dbPath variable se debe determinar según las reglas
descritas anteriormente en este documento.
Crear una conexión de base de datos – Una vez creado el archivo de base de datos de SQLite, puede crear un
objeto de conexión para obtener acceso a los datos. La conexión se crea con una cadena de conexión que toma la
forma Data Source=file_path de, como se muestra a continuación:

var connection = new SqliteConnection ("Data Source=" + dbPath);


connection.Open();
// do stuff
connection.Close();

Como se mencionó anteriormente, nunca se debe volver a usar una conexión entre subprocesos diferentes. En caso
de duda, cree la conexión según sea necesario y ciérrela cuando haya terminado. pero sea consciente de hacerlo
con más frecuencia de lo requerido.
Crear y ejecutar un comando de base de datos – Una vez que tenemos una conexión, podemos ejecutar
comandos SQL arbitrarios en ella. En el código siguiente se CREATE TABLE muestra una instrucción que se está
ejecutando.

using (var command = connection.CreateCommand ()) {


command.CommandText = "CREATE TABLE [Items] ([_id] int, [Symbol] ntext, [Name] ntext);";
var rowcount = command.ExecuteNonQuery ();
}

Al ejecutar SQL directamente en la base de datos, debe tomar las precauciones normales para no realizar
solicitudes no válidas, como intentar crear una tabla que ya existe. Realice un seguimiento de la estructura de la
base de datos para que no SqliteException cause una tabla de errores de SQLite [items] ya existe.

Acceso a datos básico


El código de ejemplo DataAccess_Basic de este documento tiene este aspecto cuando se ejecuta en Android:

En el código siguiente se muestra cómo realizar operaciones de SQLite simples y se muestra el resultado como
texto en la ventana principal de la aplicación.
Deberá incluir estos espacios de nombres:

using System;
using System.IO;
using Mono.Data.Sqlite;

En el ejemplo de código siguiente se muestra una interacción completa de la base de datos:


1. Crear el archivo de base de datos
2. Insertar algunos datos
3. Consultar los datos
Normalmente, estas operaciones aparecen en varios lugares en todo el código; por ejemplo, puede crear el archivo
y las tablas de base de datos cuando la aplicación se inicia por primera vez y realizar lecturas y escrituras de datos
en pantallas individuales de la aplicación. En el ejemplo siguiente, se ha agrupado en un único método para este
ejemplo:
public static SqliteConnection connection;
public static string DoSomeDataAccess ()
{
// determine the path for the database file
string dbPath = Path.Combine (
Environment.GetFolderPath (Environment.SpecialFolder.Personal),
"adodemo.db3");

bool exists = File.Exists (dbPath);

if (!exists) {
Console.WriteLine("Creating database");
// Need to create the database before seeding it with some data
Mono.Data.Sqlite.SqliteConnection.CreateFile (dbPath);
connection = new SqliteConnection ("Data Source=" + dbPath);

var commands = new[] {


"CREATE TABLE [Items] (_id ntext, Symbol ntext);",
"INSERT INTO [Items] ([_id], [Symbol]) VALUES ('1', 'AAPL')",
"INSERT INTO [Items] ([_id], [Symbol]) VALUES ('2', 'GOOG')",
"INSERT INTO [Items] ([_id], [Symbol]) VALUES ('3', 'MSFT')"
};
// Open the database connection and create table with data
connection.Open ();
foreach (var command in commands) {
using (var c = connection.CreateCommand ()) {
c.CommandText = command;
var rowcount = c.ExecuteNonQuery ();
Console.WriteLine("\tExecuted " + command);
}
}
} else {
Console.WriteLine("Database already exists");
// Open connection to existing database file
connection = new SqliteConnection ("Data Source=" + dbPath);
connection.Open ();
}

// query the database to prove data was inserted!


using (var contents = connection.CreateCommand ()) {
contents.CommandText = "SELECT [_id], [Symbol] from [Items]";
var r = contents.ExecuteReader ();
Console.WriteLine("Reading data");
while (r.Read ())
Console.WriteLine("\tKey={0}; Value={1}",
r ["_id"].ToString (),
r ["Symbol"].ToString ());
}
connection.Close ();
}

Consultas más complejas


Dado que SQLite permite ejecutar CREATE comandos SQL arbitrarios en los datos, puede realizar las instrucciones,
INSERT , UPDATE , DELETE o SELECT que desee. Puede leer acerca de los comandos SQL compatibles con SQLite en
el sitio web de SQLite. Las instrucciones SQL se ejecutan con uno de los tres métodos SqliteCommand de un objeto:
ExecuteNonQuery – Se utiliza normalmente para la creación de tablas o la inserción de datos. El valor
devuelto para algunas operaciones es el número de filas afectadas; de lo contrario, es-1.
ExecuteReader Se usa cuando se debe devolver una colección de filas SqlDataReader como. –
ExecuteScalar – Recupera un valor único (por ejemplo, un agregado).
EXECUTENONQUERY
INSERT las UPDATE instrucciones, DELETE y devolverán el número de filas afectadas. Todas las demás instrucciones
SQL devolverán-1.

using (var c = connection.CreateCommand ()) {


c.CommandText = "INSERT INTO [Items] ([_id], [Symbol]) VALUES ('1', 'APPL')";
var rowcount = c.ExecuteNonQuery (); // rowcount will be 1
}

EXECUTEREADER
El método siguiente muestra una WHERE cláusula en la SELECT instrucción. Dado que el código está creando una
instrucción SQL completa, debe tener cuidado de escapar caracteres reservados como la comilla (') en torno a las
cadenas.

public static string MoreComplexQuery ()


{
var output = "";
output += "\nComplex query example: ";
string dbPath = Path.Combine (
Environment.GetFolderPath (Environment.SpecialFolder.Personal), "ormdemo.db3");

connection = new SqliteConnection ("Data Source=" + dbPath);


connection.Open ();
using (var contents = connection.CreateCommand ()) {
contents.CommandText = "SELECT * FROM [Items] WHERE Symbol = 'MSFT'";
var r = contents.ExecuteReader ();
output += "\nReading data";
while (r.Read ())
output += String.Format ("\n\tKey={0}; Value={1}",
r ["_id"].ToString (),
r ["Symbol"].ToString ());
}
connection.Close ();

return output;
}

El método ExecuteReader devuelve un objeto SqliteDataReader . Además del Read método mostrado en el
ejemplo, otras propiedades útiles incluyen:
RowsAffected – Recuento de las filas afectadas por la consulta.
HasRows – Si se devolvieron filas.
EXECUTESCALAR
Utilice esto para SELECT las instrucciones que devuelven un valor único (como un agregado).

using (var contents = connection.CreateCommand ()) {


contents.CommandText = "SELECT COUNT(*) FROM [Items] WHERE Symbol <> 'MSFT'";
var i = contents.ExecuteScalar ();
}

El ExecuteScalar tipo de valor devuelto object del método es – que debe convertir el resultado en función de la
consulta de la base de datos. El resultado puede ser un entero de una COUNT consulta o una cadena de una
consulta de una sola columna. SELECT Tenga en cuenta que esto es diferente Execute a otros métodos que
devuelven un objeto de lector o un recuento del número de filas afectadas.
Vínculos relacionados
Acceso a datos básico (ejemplo)
Acceso a la configuración avanzada (ejemplo)
Recetas de datos de Android
Acceso a datos de Xamarin. Forms
Uso de datos en una aplicación
16/08/2019 • 6 minutes to read • Edit Online

En el ejemplo DataAccess_Adv se muestra una aplicación de trabajo que permite la entrada del usuario y la
funcionalidad de la base de datos CRUD (crear, leer, actualizar y eliminar). La aplicación consta de dos pantallas:
una lista y un formulario de entrada de datos. Todo el código de acceso a datos se puede volver a usar en iOS y
Android sin modificarlo.
Después de agregar algunos datos, las pantallas de la aplicación tienen el siguiente aspecto en Android:

El proyecto de Android se muestra – debajo del código que se muestra en esta sección se encuentra en el directorio
ORM :
El código de interfaz de usuario nativo para las actividades en Android está fuera del ámbito de este documento.
Consulte la guía de los adaptadores y ListView de Android para obtener más información sobre los controles de
interfaz de usuario.

Lectura
Hay un par de operaciones de lectura en el ejemplo:
Lectura de la lista
Leer registros individuales
Los dos métodos de la StockDatabase clase son:

public IEnumerable<Stock> GetStocks ()


{
lock (locker) {
return (from i in Table<Stock> () select i).ToList ();
}
}
public Stock GetStock (int id)
{
lock (locker) {
return Table<Stock>().FirstOrDefault(x => x.Id == id);
}
}

Android representa los datos como un ListView .

Crear y actualizar
Para simplificar el código de la aplicación, se proporciona un único método Save que realiza una inserción o una
actualización dependiendo de si se ha establecido PrimaryKey. Dado que Id la propiedad está marcada con
[PrimaryKey] un atributo, no debe establecerla en el código. Este método detectará si el valor se ha guardado
previamente (comprobando la propiedad de clave principal) e inserta o actualiza el objeto en consecuencia:
public int SaveStock (Stock item)
{
lock (locker) {
if (item.Id != 0) {
Update (item);
return item.Id;
} else {
return Insert (item);
}
}
}

Normalmente, las aplicaciones reales requerirán alguna validación (por ejemplo, campos obligatorios, longitud
mínima u otras reglas de negocios). Una buena aplicación multiplataforma implementa tanto como sea posible la
validación lógica en el código compartido, pasando los errores de validación a la interfaz de usuario para su
presentación de acuerdo con las capacidades de la plataforma.

Eliminar
A diferencia de Insert los Update métodos y, Delete<T> el método solo puede aceptar el valor de clave principal
en lugar Stock de un objeto completo. En este ejemplo, Stock se pasa un objeto al método, pero solo la
propiedad ID se pasa Delete<T> al método.

public int DeleteStock(Stock stock)


{
lock (locker) {
return Delete<Stock> (stock.Id);
}
}

Usar un archivo de base de datos SQLite rellenado previamente


Algunas aplicaciones se incluyen con una base de datos que ya se ha rellenado con datos. Puede hacerlo fácilmente
en la aplicación móvil si envía un archivo de base de datos de SQLite existente a la aplicación y lo copia en un
directorio de escritura antes de tener acceso a él. Dado que SQLite es un formato de archivo estándar que se usa
en muchas plataformas, hay una serie de herramientas disponibles para crear un archivo de base de datos de
SQLite:
Extensión de administrador de SQLite de SQLite – Funciona en Mac y Windows y genera archivos que
son compatibles con iOS y Android.
Línea de comandos Vea www.SQLite.org/SQLite.html . –
Al crear un archivo de base de datos para su distribución con la aplicación, tenga cuidado con el nombre de las
tablas y columnas para asegurarse de que coinciden con lo que espera el código, especialmente si usa SQLite.NET,
lo C# que esperará que los nombres coincidan con sus clases y propiedades ( o los atributos personalizados
asociados).
Para asegurarse de que algún código se ejecuta antes que cualquier otro elemento de la aplicación Android, puede
colocarlo en la primera actividad que se va a Application cargar o puede crear una subclase que se cargue antes
de cualquier actividad. En el código siguiente se Application muestra una subclase que copia un archivo de base
de datos existente. SQLite fuera del directorio /Resources/RAW/ .
[Application]
public class YourAndroidApp : Application {
public override void OnCreate ()
{
base.OnCreate ();
var docFolder = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
Console.WriteLine ("Data path:" + Database.DatabaseFilePath);
var dbFile = Path.Combine(docFolder, "data.sqlite"); // FILE NAME TO USE WHEN COPIED
if (!System.IO.File.Exists(dbFile)) {
var s = Resources.OpenRawResource(Resource.Raw.data); // DATA FILE RESOURCE ID
FileStream writeStream = new FileStream(dbFile, FileMode.OpenOrCreate, FileAccess.Write);
ReadWriteStream(s, writeStream);
}
}
// readStream is the stream you need to read
// writeStream is the stream you want to write to
private void ReadWriteStream(Stream readStream, Stream writeStream)
{
int Length = 256;
Byte[] buffer = new Byte[Length];
int bytesRead = readStream.Read(buffer, 0, Length);
// write the required bytes
while (bytesRead > 0)
{
writeStream.Write(buffer, 0, bytesRead);
bytesRead = readStream.Read(buffer, 0, Length);
}
readStream.Close();
writeStream.Close();
}
}

Vínculos relacionados
Acceso a datos básico (ejemplo)
Acceso a la configuración avanzada (ejemplo)
Recetas de datos de Android
Acceso a datos de Xamarin. Forms
Mensajería de Google
11/07/2019 • 2 minutes to read • Edit Online

Esta sección contiene a guías que describen cómo implementar aplicaciones de Xamarin.Android mediante
servicios de mensajería de Google.

Mensajería en la nube de Firebase


Firebase Cloud Messaging (FCM ) es un servicio que facilita la mensajería entre aplicaciones móviles y aplicaciones
de servidor. FCM es el sucesor de Google en Google Cloud Messaging. Este artículo proporciona información
general del funcionamiento de FCM y proporciona un procedimiento paso a paso para la adquisición de
credenciales para que la aplicación puede usar los servicios FCM.

Notificaciones remotas con Firebase Cloud Messaging


Este tutorial proporciona una explicación paso a paso sobre cómo utilizar Firebase Cloud Messaging para
implementar notificaciones remotas (también denominadas notificaciones push) en una aplicación de
Xamarin.Android. Muestra cómo implementar las distintas clases que son necesarios para las comunicaciones con
Firebase Cloud Messaging (FCM ), se proporcionan ejemplos de cómo configurar el manifiesto de Android para
tener acceso a FCM y muestra la mensajería de nivel inferior con el Firebase Consola.

Google Cloud Messaging


Esta sección proporciona una descripción general de cómo se enruta los mensajes entre la aplicación y un servidor
de aplicaciones en Google Cloud Messaging (GCM ), y proporciona un procedimiento paso a paso para adquirir las
credenciales para que la aplicación puede usar los servicios GCM. (Tenga en cuenta que GCM ha sido reemplazado
por FCM ).

NOTE
GCM ha sido reemplazado por Firebase Cloud Messaging (FCM). GCM API de cliente y servidor han quedado en desuso y ya
no estará disponible tan pronto como el 11 de abril de 2019.

Notificaciones remotas con Google Cloud Messaging


Esta sección proporciona una explicación paso a paso sobre cómo implementar notificaciones remotas en
Xamarin.Android mediante Google Cloud Messaging. Explica los distintos componentes que deben usarse para
habilitar Google Cloud Messaging en una aplicación de Android.
Mensajería en la nube de Firebase
16/08/2019 • 17 minutes to read • Edit Online

Firebase Cloud Messaging (FCM ) es un servicio que facilita la mensajería entre aplicaciones móviles y
aplicaciones de servidor. En este artículo se proporciona información general sobre cómo funciona FCM y se
explica cómo configurar Google Services para que la aplicación pueda usar FCM.

En este tema se proporciona información general de alto nivel sobre cómo Firebase Cloud Messaging enruta los
mensajes entre la aplicación de Xamarin. Android y un servidor de aplicaciones, y proporciona un procedimiento
paso a paso para adquirir credenciales para que la aplicación pueda usar los servicios de FCM.

Información general
Firebase Cloud Messaging (FCM ) es un servicio multiplataforma que controla el envío, el enrutamiento y la
puesta en cola de los mensajes entre las aplicaciones de servidor y las aplicaciones de cliente móvil. FCM es el
sucesor de Google Cloud Messaging (GCM ) y se basa en Google Play Services.
Como se muestra en el diagrama siguiente, FCM actúa como intermediario entre los remitentes de mensajes y
los clientes. Una aplicación cliente es una aplicación habilitada para FCM que se ejecuta en un dispositivo. El
servidor de aplicaciones (proporcionado por usted o su empresa) es el servidor habilitado para FCM con el que
se comunica la aplicación cliente a través de FCM. A diferencia de GCM, FCM permite enviar mensajes a las
aplicaciones cliente directamente a través de la GUI de notificaciones de la consola de Firebase:
Con FCM, los servidores de aplicaciones pueden enviar mensajes a un único dispositivo, a un grupo de
dispositivos o a una serie de dispositivos que están suscritos a un tema. Una aplicación cliente puede usar FCM
para suscribirse a mensajes de nivel inferior desde un servidor de aplicaciones (por ejemplo, para recibir
notificaciones remotas). Para obtener más información sobre los diferentes tipos de mensajes de Firebase, vea
About FCM messages.

Mensajería en la nube Firebase en acción


Cuando se envía un mensaje de nivel inferior a una aplicación cliente desde un servidor de aplicaciones, el
servidor de aplicaciones envía el mensaje a un servidor de conexión FCM proporcionado por Google; el servidor
de conexión FCM, a su vez, reenvía el mensaje a un dispositivo que ejecuta la aplicación cliente. Los mensajes se
pueden enviar a través de HTTP o XMPP (Protocolo de mensajería y presencia extensible). Dado que las
aplicaciones cliente no siempre están conectadas o en ejecución, el servidor de conexión FCM pone en cola y
almacena los mensajes, enviándolos a las aplicaciones cliente a medida que se vuelven a conectar y están
disponibles. Del mismo modo, FCM pondrá en cola los mensajes ascendentes desde la aplicación cliente al
servidor de aplicaciones si el servidor de aplicaciones no está disponible. Para obtener más información sobre
los servidores de conexión de FCM, consulte acerca de Firebase Cloud Messaging Server.
FCM usa las credenciales siguientes para identificar el servidor de aplicaciones y la aplicación cliente, y usa estas
credenciales para autorizar las transacciones de mensajes a través de FCM:
ID. de remitente El ID. de remitente es un valor numérico único que se asigna al crear el proyecto
Firebase. – El identificador del remitente se usa para identificar cada servidor de aplicaciones que puede
enviar mensajes a la aplicación cliente. El identificador del remitente también es el número del proyecto; al
registrar el proyecto, se obtiene el identificador de remitente de la consola de Firebase. Un ejemplo de un
identificador de remitente es 496915549731 .
Clave de API La clave de API proporciona al servidor de aplicaciones acceso a Firebase Services. – FCM
usa esta clave para autenticar el servidor de aplicaciones. Esta credencial también se conoce como la clave
de servidor o la clave de API Web. Un ejemplo de una clave de API
AJzbSyCTcpfRT1YRqbz-jIwp1h06YdauvewGDzk es.

Identificador de la aplicación – La identidad de la aplicación cliente (independiente de cualquier


dispositivo determinado) que se registra para recibir mensajes de FCM. Un ejemplo de un identificador
de aplicación 1:415712510732:android:0e1eb7a661af2460 es.
Token de registro El token de registro (también conocido como ID. de instancia) es la identidad FCM de
la aplicación cliente en un dispositivo determinado. – El token de registro se genera en tiempo – de
ejecución. la aplicación recibe un token de registro cuando se registra por primera vez con FCM mientras
se ejecuta en un dispositivo. El token de registro autoriza a una instancia de la aplicación cliente (que se
ejecuta en ese dispositivo concreto) a recibir mensajes de FCM. Un ejemplo de token de registro es
fkBQTHxKKhs:AP91bHuEedxM4xFAUn0z ... JKZS (una cadena muy larga).

Configuración de la mensajería en la nube Firebase (más adelante en esta guía) se proporcionan instrucciones
detalladas para crear un proyecto y generar estas credenciales. Al crear un nuevo proyecto en la consola de
Firebase, se crea – un archivo de credenciales denominado Google-Services. JSON. agregue este archivo al
proyecto de Xamarin. Android, como se explica en notificaciones remotas con FCM.
En las secciones siguientes se explica cómo se usan estas credenciales cuando las aplicaciones cliente se
comunican con los servidores de aplicaciones a través de FCM.
Registro con FCM
Una aplicación cliente debe registrarse primero con FCM antes de que pueda tener lugar la mensajería. La
aplicación cliente debe completar los pasos de registro que se muestran en el diagrama siguiente:

1. La aplicación cliente se pone en contacto con FCM para obtener un token de registro, pasando el
identificador del remitente, la clave de API y el identificador de la aplicación a FCM.
2. FCM devuelve un token de registro a la aplicación cliente.
3. La aplicación cliente (opcionalmente) reenvía el token de registro al servidor de aplicaciones.
El servidor de aplicaciones almacena en caché el token de registro para las comunicaciones posteriores con la
aplicación cliente. El servidor de aplicaciones puede devolver una confirmación a la aplicación cliente para
indicar que se recibió el token de registro. Una vez que se realiza este protocolo de enlace, la aplicación cliente
puede recibir mensajes de (o enviar mensajes a) el servidor de aplicaciones. La aplicación cliente puede recibir
un nuevo token de registro si el token anterior se ve comprometido (consulte notificaciones remotas con FCM
para obtener un ejemplo de cómo una aplicación recibe actualizaciones de token de registro).
Cuando la aplicación cliente ya no quiere recibir mensajes del servidor de aplicaciones, puede enviar una
solicitud al servidor de aplicaciones para eliminar el token de registro. Si se desinstala la aplicación cliente de un
dispositivo, FCM lo detecta y notifica automáticamente al servidor de aplicaciones que elimine el token de
registro.
Mensajería de nivel inferior
En el diagrama siguiente se ilustra el modo en que la mensajería en la nube Firebase almacena y reenvía
mensajes de nivel inferior:

Cuando el servidor de aplicaciones envía un mensaje de nivel inferior a la aplicación cliente, usa los siguientes
pasos tal y como se enumera en el diagrama anterior:
1. El servidor de aplicaciones envía el mensaje a FCM.
2. Si el dispositivo cliente no está disponible, el servidor FCM almacena el mensaje en una cola para su
transmisión posterior. Los mensajes se retienen en el almacenamiento de FCM durante un máximo de 4
semanas (para obtener más información, consulte configuración de la duración de un mensaje).
3. Cuando el dispositivo cliente está disponible, FCM reenvía el mensaje a la aplicación cliente en ese
dispositivo.
4. La aplicación cliente recibe el mensaje de FCM, lo procesa y lo muestra al usuario. Por ejemplo, si el
mensaje es una notificación remota, se presenta al usuario en el área de notificación.
En este escenario de mensajería (donde el servidor de aplicaciones envía un mensaje a una sola aplicación
cliente), los mensajes pueden tener una longitud de hasta 4 KB.
Para obtener información detallada sobre cómo recibir mensajes FCM de bajada en Android, consulte
notificaciones remotas con FCM.
Mensajería de temas
La mensajería de temas permite que un servidor de aplicaciones envíe un mensaje a varios dispositivos que
hayan participado en un tema determinado. También puede crear y enviar mensajes de tema a través de la GUI
de notificaciones de la consola de Firebase. FCM controla el enrutamiento y la entrega de mensajes de tema a
los clientes suscritos. Esta característica se puede usar para mensajes tales como alertas meteorológicas,
cotizaciones bursátiles y noticias de titulares.
Los pasos siguientes se usan en la mensajería de temas (después de que la aplicación cliente obtenga un token
de registro, como se explicó anteriormente):
1. La aplicación cliente se suscribe a un tema mediante el envío de un mensaje de suscripción a FCM.
2. El servidor de aplicaciones envía mensajes de tema a FCM para su distribución.
3. FCM reenvía los mensajes de tema a los clientes que se han suscrito a ese tema.
Para obtener más información sobre la mensajería de temas de Firebase, vea el tema sobre mensajería en
Androidde Google.

Configuración de la mensajería en la nube Firebase


Antes de poder usar FCM Services en la aplicación, debe crear un nuevo proyecto (o importar un proyecto
existente) a través de la consola de Firebase. Use los pasos siguientes para crear un proyecto de mensajería en la
nube de Firebase para la aplicación:
1. Inicie sesión en la consola de Firebase con su cuenta de Google (es decir, su dirección de Gmail) y haga
clic en crear nuevo proyecto:

Si tiene un proyecto existente, haga clic en importar un proyecto de Google.


2. En el cuadro de diálogo crear un proyecto , escriba el nombre del proyecto y haga clic en crear
proyecto. En el ejemplo siguiente, se crea un nuevo proyecto denominado XamarinFCM :
3. En la Introduccióna la consola de Firebase, haga clic en Agregar Firebase a la aplicación Android:

4. En la siguiente pantalla, escriba el nombre del paquete de la aplicación. En este ejemplo, el nombre del
paquete es com. Xamarin. fcmexample. Este valor debe coincidir con el nombre del paquete de la
aplicación Android. También se puede escribir un alias de aplicación en el campo sobrenombre de la
aplicación :
5. Si su aplicación usa vínculos dinámicos, invitados o Google auth, también debe especificar el certificado
de firma de depuración. Para obtener más información sobre cómo buscar el certificado de firma,
consulte búsqueda de la firma MD5 o SHA1 de su almacén de claves. En este ejemplo, el certificado de
firma se deja en blanco.
6. Haga clic en Agregar aplicación:

Se genera automáticamente una clave de API de servidor y un identificador de cliente para la aplicación.
Esta información se empaqueta en un archivo Google-Services. JSON que se descarga
automáticamente al hacer clic en Agregar aplicación. Asegúrese de guardar este archivo en un lugar
seguro.
Para obtener un ejemplo detallado de cómo agregar Google-Services. JSON a un proyecto de aplicación para
recibir mensajes de notificación de envío de FCM en Android, consulte notificaciones remotas con FCM.
Para obtener más información
La mensajería en la nube Firebase de Google proporciona una visión general de las funcionalidades clave
de la mensajería en la nube de Firebase, una explicación de cómo funciona y las instrucciones de
configuración.
En las solicitudes de envío del servidor de aplicaciones de Google, se explica cómo enviar mensajes con el
servidor de aplicaciones.
Rfc 6120 y RFC 6121 explican y definen el protocolo de mensajería y presencia extensible (XMPP ).
Acerca de los mensajes de FCM describe los distintos tipos de mensajes que se pueden enviar con la
mensajería en la nube de Firebase.

Resumen
En este artículo se proporciona información general sobre Firebase Cloud Messaging (FCM ). Se han explicado
las distintas credenciales que se usan para identificar y autorizar la mensajería entre los servidores de
aplicaciones y las aplicaciones cliente. Se ilustran los escenarios de registro y mensajería de nivel inferior, y se
detallan los pasos para registrar la aplicación con FCM para usar los servicios de FCM.

Vínculos relacionados
Mensajería en la nube de Firebase
Notificaciones remotas con mensajería en la nube
de Firebase
16/08/2019 • 46 minutes to read • Edit Online

En este tutorial se proporciona una explicación paso a paso de cómo usar la mensajería en la nube Firebase
para implementar notificaciones remotas (también denominadas notificaciones de envío ) en una aplicación de
Xamarin. Android. Muestra cómo implementar las distintas clases que se necesitan para las comunicaciones con
Firebase Cloud Messaging (FCM ), proporciona ejemplos de cómo configurar el manifiesto de Android para el
acceso a FCM y muestra la mensajería de nivel inferior mediante Firebase Console.

Información general sobre las notificaciones de FCM


En este tutorial, se creará una aplicación básica denominada FCMClient para ilustrar los aspectos básicos de la
mensajería de FCM. FCMClient comprueba la presencia de Google Play Services, recibe los tokens de registro
de FCM, muestra las notificaciones remotas que se envían desde la consola de Firebase y se suscribe a los
mensajes de tema:

Se explorarán las siguientes áreas de temas:


1. Notificaciones en segundo plano
2. Mensajes de tema
3. Notificaciones en primer plano
Durante este tutorial, agregará funcionalidad a FCMClient de forma incremental y la ejecutará en un dispositivo
o emulador para comprender cómo interactúa con FCM. Usará el registro para notificar las transacciones de
aplicaciones activas con servidores de FCM y observará cómo se generan las notificaciones a partir de los
mensajes de FCM que especifique en la GUI de notificaciones de la consola de Firebase.

Requisitos
Le resultará útil familiarizarse con los distintos tipos de mensajes que se pueden enviar mediante la mensajería
en la nube de Firebase. La carga del mensaje determinará el modo en que una aplicación cliente recibirá y
procesará el mensaje.
Para poder continuar con este tutorial, debe adquirir las credenciales necesarias para usar los servidores de FCM
de Google. Este proceso se explica en Firebase Cloud Messaging. En concreto, debe descargar el archivo
Google-Services. JSON para usarlo con el código de ejemplo que se muestra en este tutorial. Si aún no ha
creado un proyecto en la consola de Firebase (o si aún no ha descargado el archivo Google-Services. JSON ),
consulte Firebase Cloud Messaging.
Para ejecutar la aplicación de ejemplo, necesitará un emulador o dispositivo de prueba de Android que se
permitía con Firebase. La mensajería en la nube de Firebase admite clientes que se ejecutan en Android 4,0 o
posterior, y estos dispositivos también deben tener la aplicación Google Play Store instalada (Google Play
Services se requiere 9.2.1 o posterior). Si aún no tiene la aplicación Google Play Store instalada en el dispositivo,
visite el sitio web de Google Play para descargarla e instalarla. Como alternativa, puede usar el emulador de
Android SDK con Google Play Services instalado en lugar de un dispositivo de prueba (no es necesario instalar
el Google Play Store si usa el emulador de Android SDK).

Iniciar un proyecto de aplicación


Para empezar, cree un nuevo proyecto de Xamarin. Android vacío llamado FCMClient. Si no está familiarizado
con la creación de proyectos de Xamarin. Android, consulte Hello, Android. Una vez creada la nueva aplicación,
el siguiente paso es establecer el nombre del paquete e instalar varios paquetes de NuGet que se usarán para la
comunicación con FCM.
Establecer el nombre del paquete
En Firebase Cloud Messaging, ha especificado un nombre de paquete para la aplicación habilitada para FCM.
Este nombre de paquete también sirve como identificador de la aplicación que está asociado a la clave de API.
Configure la aplicación para que use este nombre de paquete:
Visual Studio
Visual Studio para Mac
1. Abra las propiedades del proyecto FCMClient .
2. En la página manifiesto de Android , establezca el nombre del paquete.
En el ejemplo siguiente, el nombre del paquete se establece com.xamarin.fcmexample en:
Mientras actualiza el manifiesto de Android, asegúrese también de que está habilitado el Internet permiso.

IMPORTANT
La aplicación cliente no podrá recibir un token de registro de FCM si el nombre del paquete no coincide exactamente con
el nombre del paquete que se especificó en la consola de Firebase.

Agregar el paquete base de Xamarin Google Play Services


Dado que la mensajería en la nube de Firebase depende de Google Play Services, se debe agregar el paquete de
NuGet de la base de Google Play Services de Xamarin al proyecto de Xamarin. Android. Necesitará la versión
29.0.0.2 o posterior.
Visual Studio
Visual Studio para Mac
1. En Visual Studio, haga clic con el botón derecho en referencias > administrar paquetes NuGet. ...
2. Haga clic en la pestaña examinar y busque Xamarin. GooglePlayServices. base.
3. Instale este paquete en el proyecto FCMClient :

Si recibe un error durante la instalación de NuGet, cierre el proyecto FCMClient , ábralo de nuevo y vuelva a
intentar la instalación de NuGet.
Al instalar Xamarin. GooglePlayServices. base, también se instalan todas las dependencias necesarias. Edite
MainActivity.CS y agregue la using siguiente instrucción:

using Android.Gms.Common;

Esta instrucción hace que GoogleApiAvailability la clase de Xamarin. GooglePlayServices. base esté
disponible para el código FCMClient . GoogleApiAvailability se utiliza para comprobar la presencia de Google
Play Services.
Adición del paquete de mensajería de Xamarin Firebase
Para recibir mensajes de FCM, el paquete de NuGet de Xamarin Firebase-Messaging debe agregarse al
proyecto de la aplicación. Sin este paquete, una aplicación de Android no puede recibir mensajes de los
servidores de FCM.
Visual Studio
Visual Studio para Mac
1. En Visual Studio, haga clic con el botón derecho en referencias > administrar paquetes NuGet. ...
2. Busque Xamarin. Firebase. Messaging.
3. Instale este paquete en el proyecto FCMClient :

Al instalar Xamarin. Firebase. Messaging, también se instalan todas las dependencias necesarias.
A continuación, edite MainActivity.CS y agregue using las siguientes instrucciones:

using Firebase.Messaging;
using Firebase.Iid;
using Android.Util;

Las dos primeras instrucciones hacen que los tipos del paquete de NuGet Xamarin. Firebase. Messaging
estén disponibles para el código FCMClient . Android. util agrega funcionalidad de registro que se usará para
observar las transacciones con FMS.
Adición del archivo JSON de Google Services
El siguiente paso consiste en agregar el archivo Google-Services. JSON al directorio raíz del proyecto:
Visual Studio
Visual Studio para Mac
1. Copie Google-Services. JSON en la carpeta del proyecto.
2. Agregue Google-Services. JSON al proyecto de aplicación (haga clic en Mostrar todos los archivos
en el Explorador de soluciones, haga clic con el botón secundario en Google-Services. JSONy
seleccione incluir en el proyecto).
3. Seleccione Google-Services. JSON en la ventana de Explorador de soluciones .
4. En el panel propiedades , establezca la acción de compilación en GoogleServicesJson:
NOTE
Si no se muestra la acción de compilación GoogleServicesJson , guarde y cierre la solución y vuelva a abrirla.

Cuando se agrega Google-Services. JSON al proyecto (y se establece la acción de compilación


GoogleServicesJson ), el proceso de compilación extrae el identificador de cliente y la clave de API y, a
continuación, agrega estas credenciales a la combinación/generada . Archivo AndroidManifest. XML que
reside en obj/Debug/Android/archivo AndroidManifest. XML. Este proceso de mezcla agrega
automáticamente los permisos y otros elementos FCM necesarios para la conexión con los servidores de FCM.

Comprobación de Google Play Services y creación de un canal de


notificación
Google recomienda que las aplicaciones Android comprueben la presencia del Google Play Services APK antes
de tener acceso a Google Play Services características (para obtener más información, consulte comprobación
de servicios de Google Play).
Primero se creará un diseño inicial para la interfaz de usuario de la aplicación. Edite Resources /layout/main.
axml y reemplace su contenido por el siguiente código XML:

<?xml version="1.0" encoding="utf-8"?>


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp">
<TextView
android:text=" "
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/msgText"
android:textAppearance="?android:attr/textAppearanceMedium"
android:padding="10dp" />
</LinearLayout>

TextView Se usará para mostrar mensajes que indiquen si Google Play Services está instalado. Guarde los
cambios en Main. axml.
Edite MainActivity.CS y agregue las siguientes variables de instancia MainActivity a la clase:
public class MainActivity : AppCompatActivity
{
static readonly string TAG = "MainActivity";

internal static readonly string CHANNEL_ID = "my_notification_channel";


internal static readonly int NOTIFICATION_ID = 100;

TextView msgText;

Las variables CHANNEL_ID y NOTIFICATION_ID se usarán en el método CreateNotificationChannel que se


agregará MainActivity posteriormente en este tutorial.
En el ejemplo siguiente, el OnCreate método comprobará que Google Play Services está disponible antes de
que la aplicación intente usar los servicios de FCM. Agregue el método siguiente a la MainActivity clase:

public bool IsPlayServicesAvailable ()


{
int resultCode = GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable (this);
if (resultCode != ConnectionResult.Success)
{
if (GoogleApiAvailability.Instance.IsUserResolvableError (resultCode))
msgText.Text = GoogleApiAvailability.Instance.GetErrorString (resultCode);
else
{
msgText.Text = "This device is not supported";
Finish ();
}
return false;
}
else
{
msgText.Text = "Google Play Services is available.";
return true;
}
}

Este código comprueba el dispositivo para ver si está instalado el Google Play Services APK. Si no está
instalado, se muestra un mensaje en el TextBox que indica al usuario que descargue una apk del Google Play
Store (o para habilitarla en la configuración del sistema del dispositivo).
Las aplicaciones que se ejecutan en Android 8,0 (nivel de API 26) o superior deben crear un canal de
notificación para publicar sus notificaciones. Agregue el método siguiente a la MainActivity clase, que creará el
canal de notificación (si es necesario):
void CreateNotificationChannel()
{
if (Build.VERSION.SdkInt < BuildVersionCodes.O)
{
// Notification channels are new in API 26 (and not a part of the
// support library). There is no need to create a notification
// channel on older versions of Android.
return;
}

var channel = new NotificationChannel(CHANNEL_ID,


"FCM Notifications",
NotificationImportance.Default)
{

Description = "Firebase Cloud Messages appear in this channel"


};

var notificationManager =
(NotificationManager)GetSystemService(Android.Content.Context.NotificationService);
notificationManager.CreateNotificationChannel(channel);
}

Reemplace el método OnCreate con el código siguiente:

protected override void OnCreate (Bundle bundle)


{
base.OnCreate (bundle);
SetContentView (Resource.Layout.Main);
msgText = FindViewById<TextView> (Resource.Id.msgText);

IsPlayServicesAvailable ();

CreateNotificationChannel();
}

IsPlayServicesAvailable se llama al final de OnCreate para que la comprobación de Google Play Services se
ejecute cada vez que se inicie la aplicación. Se llama CreateNotificationChannel al método para asegurarse de
que existe un canal de notificación para dispositivos que ejecutan Android 8 o posterior. Si la aplicación tiene un
OnResume método, debe llamar también IsPlayServicesAvailable a OnResume desde. Vuelva a compilar y
ejecutar la aplicación completamente. Si todo está configurado correctamente, debería ver una pantalla similar a
la siguiente captura de pantalla:
Si no obtiene este resultado, compruebe que el Google Play Services APK está instalado en el dispositivo (para
obtener más información, consulte configuración de Google Play Services). Compruebe también que ha
agregado el paquete Xamarin. Google. Play. Services. base al proyecto FCMClient como se explicó
anteriormente.

Agregar el receptor de ID. de instancia


El siguiente paso consiste en agregar un servicio que se FirebaseInstanceIdService extienda para controlar la
creación, la rotación y la actualización de los tokens de registro de Firebase. El FirebaseInstanceIdService
servicio es necesario para que FCM pueda enviar mensajes al dispositivo. Cuando el FirebaseInstanceIdService
servicio se agrega a la aplicación cliente, la aplicación recibirá automáticamente mensajes FCM y los mostrará
como notificaciones cada vez que la aplicación esté en el fondo.
Declarar el receptor en el manifiesto de Android
Edite archivo AndroidManifest. XML e inserte los <receiver> siguientes elementos en <application> la
sección:

<receiver
android:name="com.google.firebase.iid.FirebaseInstanceIdInternalReceiver"
android:exported="false" />
<receiver
android:name="com.google.firebase.iid.FirebaseInstanceIdReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="${applicationId}" />
</intent-filter>
</receiver>

Este XML hace lo siguiente:


Declara una FirebaseInstanceIdReceiver implementación de que proporciona un identificador único para
cada instancia de la aplicación. También este receptor se autentica y autoriza las acciones.
Declara una instancia interna FirebaseInstanceIdInternalReceiver implementación que se utiliza para
iniciar los servicios de forma segura.
El identificador de la aplicación se almacena en el archivo Google-Services. JSON que se agregó al
proyecto. Los enlaces de Firebase de Xamarin. Android reemplazarán el ${applicationId} token por el
identificador de la aplicación; la aplicación cliente no necesita código adicional para proporcionar el
identificador de la aplicación.
FirebaseInstanceIdReceiver Es FirebaseInstanceIdService un WakefulBroadcastReceiver que recibe
FirebaseInstanceId eventos y FirebaseMessaging y los entrega a la clase de la que deriva.
Implementar el servicio de ID. de instancia de Firebase
El trabajo de registro de la aplicación con FCM se controla mediante el servicio FirebaseInstanceIdService
personalizado proporcionado por el usuario. FirebaseInstanceIdService realiza los pasos siguientes:
1. Usa la API de ID. de instancia para generar tokens de seguridad que autorizan a la aplicación cliente para
acceder a FCM y el servidor de aplicaciones. A cambio, la aplicación devuelve un token de registro de
FCM.
2. Reenvía el token de registro al servidor de aplicaciones si lo requiere el servidor de aplicaciones.
Agregue un nuevo archivo denominado MyFirebaseIIDService.CS y reemplace el código de plantilla por lo
siguiente:

using System;
using Android.App;
using Firebase.Iid;
using Android.Util;

namespace FCMClient
{
[Service]
[IntentFilter(new[] { "com.google.firebase.INSTANCE_ID_EVENT" })]
public class MyFirebaseIIDService : FirebaseInstanceIdService
{
const string TAG = "MyFirebaseIIDService";
public override void OnTokenRefresh()
{
var refreshedToken = FirebaseInstanceId.Instance.Token;
Log.Debug(TAG, "Refreshed token: " + refreshedToken);
SendRegistrationToServer(refreshedToken);
}
void SendRegistrationToServer(string token)
{
// Add custom implementation, as needed.
}
}
}

Este servicio implementa un OnTokenRefresh método que se invoca cuando el token de registro se crea o cambia
inicialmente. Cuando OnTokenRefresh se ejecuta, recupera el token más reciente de la
FirebaseInstanceId.Instance.Token propiedad (que FCM se actualiza de forma asincrónica). En este ejemplo, el
token actualizado se registra para que se pueda ver en la ventana de salida:

var refreshedToken = FirebaseInstanceId.Instance.Token;


Log.Debug(TAG, "Refreshed token: " + refreshedToken);
OnTokenRefresh se invoca con poca frecuencia: se usa para actualizar el token en las siguientes circunstancias:
Cuando la aplicación se instala o se desinstala.
Cuando el usuario elimina los datos de la aplicación.
Cuando la aplicación borra el ID. de instancia.
Cuando se ha puesto en peligro la seguridad del token.
Según la documentación del ID. de instancia de Google, el servicio de ID. de instancia de FCM solicitará que la
aplicación actualice su token periódicamente (normalmente, cada 6 meses).
OnTokenRefresh también llama SendRegistrationToAppServer a para asociar el token de registro del usuario a la
cuenta del servidor (si existe) que mantiene la aplicación:

void SendRegistrationToAppServer (string token)


{
// Add custom implementation here as needed.
}

Dado que esta implementación depende del diseño del servidor de aplicaciones, en este ejemplo se proporciona
un cuerpo de método vacío. Si el servidor de aplicaciones requiere información de registro de
SendRegistrationToAppServer FCM, modifique para asociar el token de ID. de instancia de FCM del usuario con
cualquier cuenta de servidor que mantenga la aplicación. (Tenga en cuenta que el token es opaco a la aplicación
cliente).
Cuando un token se envía al servidor de aplicaciones, SendRegistrationToAppServer debe mantener un valor
booleano para indicar si el token se ha enviado al servidor. Si este valor booleano es false
SendRegistrationToAppServer , envía el token al servidor – de aplicaciones; de lo contrario, el token ya se envió al
servidor de aplicaciones en una llamada anterior. En algunos casos (como este FCMClient ejemplo), el servidor
de aplicaciones no necesita el token; por lo tanto, este método no es necesario para este ejemplo.

Implementar código de aplicación cliente


Ahora que los servicios del receptor están en su lugar, se puede escribir el código de la aplicación cliente para
aprovechar estos servicios. En las secciones siguientes, se agrega un botón a la interfaz de usuario para registrar
el token de registro (también denominado token de identificador de instancia) y se agrega MainActivity más
código Intent a para ver información cuando la aplicación se inicia desde una notificación:
Tokens de registro
El código agregado en este paso está pensado únicamente para fines – de demostración. una aplicación cliente
de producción no tendría necesidad de registrar tokens de registro. Edite Resources /layout/main. axml y
Button agregue la siguiente declaración TextView inmediatamente después del elemento:

<Button
android:id="@+id/logTokenButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="Log Token" />

Agregue el código siguiente al final del método MainActivity.OnCreate :

var logTokenButton = FindViewById<Button>(Resource.Id.logTokenButton);


logTokenButton.Click += delegate {
Log.Debug(TAG, "InstanceID token: " + FirebaseInstanceId.Instance.Token);
};

Este código registra el token actual en la ventana de salida cuando se puntea el botón del token de registro .
Controlar los intentos de notificación
Cuando el usuario pulsa una notificación emitida desde FCMClient, los datos que acompañan a ese mensaje de
notificación se Intent ponen a disposición de los extras. Edite MainActivity.CS y agregue el siguiente código
al principio del OnCreate método (antes de la llamada a IsPlayServicesAvailable ):
if (Intent.Extras != null)
{
foreach (var key in Intent.Extras.KeySet())
{
var value = Intent.Extras.GetString(key);
Log.Debug(TAG, "Key: {0} Value: {1}", key, value);
}
}

El iniciador Intent de la aplicación se activa cuando el usuario puntea el mensaje de notificación, por lo que
este código registrará los Intent datos que lo acompañan en la ventana de salida. Si se debe Intent
desencadenar un diferente, click_action el campo del mensaje de notificación se Intent debe establecer en (el
iniciador Intent se utiliza cuando click_action no se especifica).

Notificaciones en segundo plano


Compile y ejecute la aplicación FCMClient . Se muestra el botón registro del token :

Puntee en el botón token de registro . Se debe mostrar un mensaje similar al siguiente en la ventana de salida
del IDE:

La cadena larga etiquetada con token es el token de identificador de instancia que se pegará en la – consola de
Firebase seleccione y copie esta cadena en el portapapeles. Si no ve un token de identificador de instancia,
agregue la siguiente línea en la parte superior del OnCreate método para comprobar que Google-Services.
JSON se analizó correctamente:

Log.Debug(TAG, "google app id: " + GetString(Resource.String.google_app_id));

El google_app_id valor registrado en la ventana de salida debe coincidir con el mobilesdk_app_id valor
registrado en Google-Services. JSON.
Enviar un mensaje
Inicie sesión en la consola de Firebase, seleccione el proyecto, haga clic en notificacionesy haga clic en enviar
su primer mensaje:

En la página redactar mensaje , escriba el texto del mensaje y seleccione dispositivo único. Copie el token de
identificador de instancia de la ventana de salida del IDE y péguelo en el campo token de registro de FCM de
la consola de Firebase:
En el dispositivo (o emulador) Android, en segundo plano, puntee en el botón información general de Android
y toque en la pantalla principal. Cuando el dispositivo esté listo, haga clic en Enviar mensaje en la consola de
Firebase:

Cuando aparezca el cuadro de diálogo Revisar mensaje , haga clic en Enviar. El icono de notificación debe
aparecer en el área de notificación del dispositivo (o emulador):
Abra el icono de notificación para ver el mensaje. El mensaje de notificación debe ser exactamente lo que se
escribió en el campo texto del mensaje de la consola de Firebase:

Pulse el icono de notificación para iniciar la aplicación FCMClient . Los Intent extras enviados a FCMClient se
muestran en la ventana de salida del IDE:

En este ejemplo, la clave from se establece en el número de proyecto Firebase de la aplicación (en este ejemplo
41590732 ,) y collapse_key se establece en su nombre de paquete (com. Xamarin. fcmexample ). Si no recibe
un mensaje, intente eliminar la aplicación FCMClient en el dispositivo (o emulador) y repita los pasos
anteriores.

NOTE
Si fuerza el cierre de la aplicación, FCM dejará de entregar notificaciones. Android impide que se realicen difusiones de
servicio en segundo plano desde el inicio accidental o innecesario de componentes de aplicaciones detenidas. (Para
obtener más información sobre este comportamiento, vea iniciar controles en aplicacionesdetenidas). Por esta razón, es
necesario desinstalar manualmente la aplicación cada vez que la ejecuta y detenerla en una sesión – de depuración, lo que
obliga a FCM a generar un nuevo token para que los mensajes se sigan recibiendo.

Agregar un icono de notificación predeterminada personalizado


En el ejemplo anterior, el icono de notificación se establece en el icono de la aplicación. El siguiente código XML
configura un icono predeterminado personalizado para las notificaciones. Android muestra este icono
predeterminado personalizado para todos los mensajes de notificación en los que no se establece explícitamente
el icono de notificación.
Para agregar un icono de notificación predeterminada personalizado, agregue el icono al directorio Resources
/drawable , edite archivo AndroidManifest. XMLe inserte <meta-data> el siguiente elemento <application>
en la sección:

<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@drawable/ic_stat_ic_notification" />

En este ejemplo, el icono de notificación que se encuentra en Resources/drawable_/_IC_stat. png se usará


como el icono de notificación predeterminada personalizado. Si un icono predeterminado personalizado no está
configurado en archivo AndroidManifest. XML y no se ha establecido ningún icono en la carga de
notificación, Android usa el icono de la aplicación como el icono de notificación (como se ha mostrado en el
icono de notificación de la captura de pantalla anterior).

Controlar mensajes de temas


El código escrito de forma que controla los tokens de registro y agrega la funcionalidad de notificación remota a
la aplicación. En el ejemplo siguiente se agrega código que realiza escuchas para los mensajes de tema y los
reenvía al usuario como notificaciones remotas. Los mensajes de tema son mensajes FCM que se envían a uno o
varios dispositivos que se suscriben a un tema determinado. Para obtener más información acerca de los
mensajes de tema, vea el tema sobre mensajería.
Suscripción a un tema
Edite Resources /layout/main. axml y Button agregue la siguiente declaración inmediatamente Button
después del elemento anterior:

<Button
android:id="@+id/subscribeButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="20dp"
android:text="Subscribe to Notifications" />

Este XML agrega un botón de suscripción a la notificación al diseño. Edite MainActivity.CS y agregue el
código siguiente al final del OnCreate método:
var subscribeButton = FindViewById<Button>(Resource.Id.subscribeButton);
subscribeButton.Click += delegate {
FirebaseMessaging.Instance.SubscribeToTopic("news");
Log.Debug(TAG, "Subscribed to remote notifications");
};

Este código busca el botón suscribirse a notificación en el diseño y asigna el controlador de clic al código que
llama FirebaseMessaging.Instance.SubscribeToTopic , pasando el tema suscrito, noticias. Cuando el usuario pulsa
el botón subscribe , la aplicación se suscribe al tema News . En la siguiente sección, se enviará un mensaje de
tema de noticias desde la GUI de notificaciones de la consola de Firebase.
Enviar un mensaje de tema
Desinstale la aplicación, vuelva a compilarla y ejecútela de nuevo. Haga clic en el botón suscribirse a
notificaciones :

Si la aplicación se ha suscrito correctamente, debería ver el tema la sincronización se realizó correctamente


en la ventana de salida del IDE:
Siga estos pasos para enviar un mensaje de tema:
1. En la consola de Firebase, haga clic en nuevo mensaje.
2. En la página redactar mensaje , escriba el texto del mensaje y seleccione tema.
3. En el menú desplegable del tema , seleccione el tema integrado News:

4. En el dispositivo (o emulador) Android, en segundo plano, puntee en el botón información general de


Android y toque en la pantalla principal.
5. Cuando el dispositivo esté listo, haga clic en Enviar mensaje en la consola de Firebase.
6. Compruebe la ventana de salida del IDE para ver /topics/News en la salida del registro:
Cuando este mensaje se muestra en la ventana de salida, el icono de notificación también debe aparecer en el
área de notificación del dispositivo Android. Abra el icono de notificación para ver el mensaje del tema:

Si no recibe un mensaje, intente eliminar la aplicación FCMClient en el dispositivo (o emulador) y repita los
pasos anteriores.

Notificaciones en primer plano


Para recibir notificaciones en aplicaciones en primer plano, debe implementar FirebaseMessagingService . Este
servicio también es necesario para recibir cargas de datos y para enviar mensajes de nivel superior. En los
siguientes ejemplos se muestra cómo implementar un servicio que FirebaseMessagingService extiende – la
aplicación resultante podrá controlar las notificaciones remotas mientras se ejecuta en primer plano.
Implementación de FirebaseMessagingService
El FirebaseMessagingService servicio es responsable de recibir y procesar los mensajes de Firebase. Cada
aplicación debe subclase de este tipo e invalidar OnMessageReceived para procesar un mensaje entrante. Cuando
una aplicación está en primer plano, la OnMessageReceived devolución de llamada siempre controlará el mensaje.

NOTE
Las aplicaciones solo tienen 10 segundos para controlar un mensaje de nube de Firebase entrante. Cualquier trabajo que
tarde más tiempo se debe programar para la ejecución en segundo plano mediante una biblioteca como el programador
de trabajos de Android o el distribuidor de trabajos de Firebase.

Agregue un nuevo archivo denominado MyFirebaseMessagingService.CS y reemplace el código de plantilla


por lo siguiente:
using System;
using Android.App;
using Android.Content;
using Android.Media;
using Android.Util;
using Firebase.Messaging;

namespace FCMClient
{
[Service]
[IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
public class MyFirebaseMessagingService : FirebaseMessagingService
{
const string TAG = "MyFirebaseMsgService";
public override void OnMessageReceived(RemoteMessage message)
{
Log.Debug(TAG, "From: " + message.From);
Log.Debug(TAG, "Notification Message Body: " + message.GetNotification().Body);
}
}
}

Tenga en cuenta que el filtro de intención se debe declarar para que los mensajes de
MESSAGING_EVENT
MyFirebaseMessagingService FCM nuevos se dirijan a:

[IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]

Cuando la aplicación cliente recibe un mensaje de FCM, OnMessageReceived extrae el contenido del mensaje del
RemoteMessage objeto pasado llamando a su GetNotification método. Después, registra el contenido del
mensaje para que se pueda ver en la ventana de salida del IDE:

var body = message.GetNotification().Body;


Log.Debug(TAG, "Notification Message Body: " + body);

NOTE
Si establece puntos de interrupción en FirebaseMessagingService , la sesión de depuración puede o no alcanzar estos
puntos de interrupción debido al modo en que FCM entrega los mensajes.

Enviar otro mensaje


Desinstale la aplicación, vuelva a compilarla, ejecútela de nuevo y siga estos pasos para enviar otro mensaje:
1. En la consola de Firebase, haga clic en nuevo mensaje.
2. En la página redactar mensaje , escriba el texto del mensaje y seleccione dispositivo único.
3. Copie la cadena de token de la ventana de salida del IDE y péguela en el campo token de registro de
FCM de la consola de Firebase como antes.
4. Asegúrese de que la aplicación se está ejecutando en primer plano y haga clic en Enviar mensaje en la
consola de Firebase:
5. Cuando aparezca el cuadro de diálogo Revisar mensaje , haga clic en Enviar.
6. El mensaje entrante se registra en la ventana de salida del IDE:

Agregar un remitente de notificación local


En este ejemplo restante, el mensaje FCM entrante se convertirá en una notificación local que se inicia mientras
la aplicación se ejecuta en primer plano. Edite MyFirebaseMessageService.CS y agregue las using siguientes
instrucciones:

using FCMClient;
using System.Collections.Generic;

Agregue el método siguiente a MyFirebaseMessagingService :


void SendNotification(string messageBody, IDictionary<string, string> data)
{
var intent = new Intent(this, typeof(MainActivity));
intent.AddFlags(ActivityFlags.ClearTop);
foreach (var key in data.Keys)
{
intent.PutExtra(key, data[key]);
}

var pendingIntent = PendingIntent.GetActivity(this,


MainActivity.NOTIFICATION_ID,
intent,
PendingIntentFlags.OneShot);

var notificationBuilder = new NotificationCompat.Builder(this, MainActivity.CHANNEL_ID)


.SetSmallIcon(Resource.Drawable.ic_stat_ic_notification)
.SetContentTitle("FCM Message")
.SetContentText(messageBody)
.SetAutoCancel(true)
.SetContentIntent(pendingIntent);

var notificationManager = NotificationManagerCompat.From(this);


notificationManager.Notify(MainActivity.NOTIFICATION_ID, notificationBuilder.Build());
}

Para distinguir esta notificación de las notificaciones en segundo plano, este código marca las notificaciones con
un icono que difiere del icono de la aplicación. Agregue el archivo IC_STAT_STAT_. png a Resources /drawable e
inclúyalo en el proyecto FCMClient .
El SendNotification método utiliza NotificationCompat.Builder para crear la notificación y
NotificationManagerCompat se utiliza para iniciar la notificación. La notificación contiene un PendingIntent que
permitirá al usuario abrir la aplicación y ver el contenido de la cadena pasada en. messageBody Para obtener más
información NotificationCompat.Builder acerca de, consulte notificaciones locales.
OnMessageReceived Llame al SendNotification método al final del método:

public override void OnMessageReceived(RemoteMessage message)


{
Log.Debug(TAG, "From: " + message.From);

var body = message.GetNotification().Body;


Log.Debug(TAG, "Notification Message Body: " + body);
SendNotification(body, message.Data);
}

Como resultado de estos cambios, SendNotification se ejecutará siempre que se reciba una notificación
mientras la aplicación está en primer plano y la notificación aparecerá en el área de notificación.
Cuando una aplicación está en segundo plano, la carga útil del mensaje determinará cómo se trata el mensaje:
Notificación de los mensajes se enviarán a la bandeja del sistema. – Aparecerá una notificación local.
Cuando el usuario pulsa la notificación, se iniciará la aplicación.
Datos de administrará los mensajes. OnMessageReceived –
Ambos – los mensajes que tienen una notificación y una carga de datos se entregarán a la bandeja del
sistema. Cuando se inicia la aplicación, la carga Extras Intent de datos aparecerá en el del que se usó para
iniciar la aplicación.
En este ejemplo, si la aplicación está en segundo plano, SendNotification se ejecutará si el mensaje tiene una
carga de datos. De lo contrario, se iniciará una notificación en segundo plano (ilustrada anteriormente en este
tutorial).
Enviar el último mensaje
Desinstale la aplicación, vuelva a compilarla, ejecútela de nuevo y, después, siga los pasos siguientes para enviar
el último mensaje:
1. En la consola de Firebase, haga clic en nuevo mensaje.
2. En la página redactar mensaje , escriba el texto del mensaje y seleccione dispositivo único.
3. Copie la cadena de token de la ventana de salida del IDE y péguela en el campo token de registro de
FCM de la consola de Firebase como antes.
4. Asegúrese de que la aplicación se está ejecutando en primer plano y haga clic en Enviar mensaje en la
consola de Firebase:

Esta vez, el mensaje que se registró en la ventana de salida también se empaqueta en una notificación – nueva el
icono de notificación aparece en la bandeja de notificación mientras la aplicación se ejecuta en primer plano:
Al abrir la notificación, debería ver el último mensaje enviado desde la GUI de notificaciones de la consola de
Firebase:
Desconectar de FCM
Para cancelar la suscripción a un tema, llame al método UnsubscribeFromTopic en la clase FirebaseMessaging .
Por ejemplo, para cancelar la suscripción al tema de noticias suscrito anteriormente, se podría agregar un botón
de anulación de suscripción al diseño con el siguiente código de controlador:

var unSubscribeButton = FindViewById<Button>(Resource.Id.unsubscribeButton);


unSubscribeButton.Click += delegate {
FirebaseMessaging.Instance.UnsubscribeFromTopic("news");
Log.Debug(TAG, "Unsubscribed from remote notifications");
};

Para anular por completo el registro del dispositivo de FCM, elimine el identificador de instancia llamando al
método DeleteInstanceId en la clase FirebaseInstanceId . Por ejemplo:

FirebaseInstanceId.Instance.DeleteInstanceId();

Esta llamada al método elimina el identificador de instancia y los datos asociados a él. Como resultado, se
detiene el envío periódico de datos de FCM al dispositivo.

Solución de problemas
A continuación se describen los problemas y las soluciones alternativas que pueden surgir al usar Firebase
Cloud Messaging con Xamarin. Android.
FirebaseApp no se ha inicializado
En algunos casos, puede ver este mensaje de error:

Java.Lang.IllegalStateException: Default FirebaseApp is not initialized in this process


Make sure to call FirebaseApp.initializeApp(Context) first.

Se trata de un problema conocido que puede solucionar limpiando la solución y recompilando el proyecto
(compilación > limpiar solución, compilar > recompilar solución).

Resumen
En este tutorial se detallan los pasos para implementar notificaciones remotas de mensajería en la nube de
Firebase en una aplicación de Xamarin. Android. Se describe cómo instalar los paquetes necesarios para las
comunicaciones de FCM y se explica cómo configurar el manifiesto de Android para el acceso a los servidores
de FCM. Proporciona código de ejemplo que muestra cómo comprobar la presencia de Google Play Services. Se
ha mostrado cómo implementar un servicio de escucha de ID. de instancia que negocia con FCM para un token
de registro y se explicó cómo este código crea notificaciones en segundo plano mientras la aplicación está en el
fondo. Se ha explicado cómo suscribirse a los mensajes de tema y se ha proporcionado un ejemplo de
implementación de un servicio de escucha de mensajes que se usa para recibir y Mostrar notificaciones remotas
mientras la aplicación se ejecuta en primer plano.

Vínculos relacionados
FCMNotifications (ejemplo)
Mensajería en la nube de Firebase
Acerca de los mensajes de FCM
Google Cloud Messaging
11/07/2019 • 19 minutes to read • Edit Online

WARNING
Google está en desuso GCM desde el 10 de abril de 2018. Ya no se pueden mantener los proyectos de ejemplo y docs
siguientes. Tan pronto como el 29 de mayo de 2019 se quitará del servidor de GCM y la API de cliente de Google. Google
recomienda migrar las aplicaciones GCM para Firebase Cloud Messaging (FCM). Para obtener más información acerca de la
degradación de GCM y migración, consulte mensajería en la nube de Google en desuso.
Para empezar a usar Firebase Cloud Messaging con Xamarin, consulte Firebase Cloud Messaging.

Google Cloud Messaging (GCM ) es un servicio que facilita la mensajería entre aplicaciones móviles y aplicaciones
de servidor. Este artículo proporciona información general del funcionamiento de GCM y se explica cómo
configurar los servicios de Google para que la aplicación pueda usar GCM.

Este tema proporciona una descripción general de cómo Google Cloud Messaging enruta los mensajes entre la
aplicación y un servidor de aplicaciones y proporciona un procedimiento paso a paso para la adquisición de
credenciales para que la aplicación puede usar los servicios GCM.

Información general
Google Cloud Messaging (GCM ) es un servicio que controla el envío, enrutamiento y la puesta en cola de
mensajes entre aplicaciones de servidor y las aplicaciones cliente móvil. Un aplicación cliente es una aplicación
habilitada para GCM que se ejecuta en un dispositivo. El del servidor de aplicaciones (proporcionado por usted o
su compañía) es el servidor de GCM con que la aplicación cliente se comunica a través de GCM:

Los servidores de aplicaciones mediante GCM, pueden enviar mensajes a un único dispositivo, un grupo de
dispositivos o un número de dispositivos que se suscriben a un tema. La aplicación cliente puede usar GCM para
suscribirse a mensajes de nivel inferiores de un servidor de aplicaciones (por ejemplo, para recibir notificaciones
remotas). Además, GCM hace posible que las aplicaciones cliente enviar mensajes de nivel superior al servidor de
aplicación.
Para obtener información acerca de cómo implementar un servidor de aplicaciones para GCM, consulte acerca del
servidor de GCM conexión.

Google Cloud Messaging en acción


Cuando se envían mensajes de nivel inferiores desde un servidor de aplicaciones para una aplicación cliente, el
servidor de la aplicación envía el mensaje a un del servidor de GCM conexión; el servidor de conexión GCM, a su
vez, reenvía el mensaje a un dispositivo que se está ejecutando la aplicación cliente. Los mensajes pueden enviarse
a través de HTTP o XMPP (Protocolo de presencia y mensajería Extensible). Dado que las aplicaciones cliente no
están siempre conectadas o están ejecutando, los GCM conexión server pone en cola y los almacenes de
mensajes, enviarlos a las aplicaciones cliente, ya que volver a conectarse y estén disponibles. De forma similar,
GCM enqueue ascendentes mensajes will desde la aplicación cliente al servidor de aplicaciones si el servidor de
aplicaciones no está disponible.
GCM utiliza las credenciales siguientes para identificar el servidor de aplicaciones y la aplicación cliente y utiliza
estas credenciales para autorizar a las transacciones de mensajes a través de GCM:
Clave de API – el clave de API permite el acceso al servidor de aplicaciones a los servicios de Google;
GCM usa esta clave para autenticar el servidor de aplicaciones. Para poder usar el servicio GCM, primero
debe obtener una clave de API desde el Google Developer Console mediante la creación de un proyecto. La
clave de API debe mantenerse segura; Para obtener más información sobre cómo proteger la clave de API,
consulte procedimientos recomendados para el uso de forma segura las claves de API.
Id. de remitente – el Id. de remitente autoriza el servidor de aplicaciones a la aplicación cliente – es un
número único que identifica el servidor de aplicación que tiene permiso para enviar mensajes a la
aplicación cliente. El Id. de remitente también es el número de proyecto obtener el Id. de remitente de la
consola de desarrolladores de Google al registrar el proyecto.
Token de registro – el registro Token es la identidad GCM de la aplicación cliente en un dispositivo
determinado. El token de registro se genera en tiempo de ejecución – la aplicación recibe un token de
registro cuando registra por primera vez GCM mientras se ejecuta en un dispositivo. El token de registro,
autoriza a una instancia de la aplicación de cliente (que se ejecutan en ese dispositivo concreto) para recibir
mensajes de GCM.
Id. de aplicación – la identidad de la aplicación de cliente que se registra para recibir mensajes de GCM
(independientemente de cualquier dispositivo determinado). En Android, el identificador de aplicación es el
nombre del paquete registrado en AndroidManifest.xml, tales como com.xamarin.gcmexample .
Configuración de seguridad de Google Cloud Messaging (más adelante en esta guía) proporciona instrucciones
detalladas para crear un proyecto y generar estas credenciales.
Las siguientes secciones explican cómo se utilizan estas credenciales cuando las aplicaciones cliente se comunican
con los servidores de aplicaciones a través de GCM.
Registro con GCM
Una aplicación de cliente instalada en un dispositivo debe registrarse con GCM antes de mensajería puede tener
lugar. La aplicación cliente debe completar los pasos de registro que se muestra en el diagrama siguiente:
1. La aplicación cliente contacta con GCM para obtener un token de registro, pasando el identificador del
remitente a GCM.
2. GCM devuelve un token de registro a la aplicación cliente.
3. La aplicación cliente envía el token de registro al servidor de aplicaciones.
El servidor de la aplicación almacena en caché el token de registro para las siguientes comunicaciones con la
aplicación cliente. Si lo desea, el servidor de aplicaciones puede enviar una confirmación de vuelta a la aplicación
cliente para indicar que se ha recibido el token de registro. Después de producirse este protocolo de enlace, la
aplicación cliente puede recibir mensajes de (o enviar mensajes a) el servidor de aplicaciones.
Cuando la aplicación cliente ya no desea recibir mensajes desde el servidor de aplicaciones, puede enviar una
solicitud al servidor de aplicaciones para eliminar el token de registro. Si la aplicación cliente recibe mensajes de
tema (se explica más adelante en este artículo), puede cancelar la suscripción del tema. Si se desinstala la
aplicación cliente desde un dispositivo, GCM lo detecta y notifica automáticamente al servidor de aplicaciones
para eliminar el token de registro.
Google registrar aplicaciones de cliente explica el proceso de registro con más detalle; se explican la anulación del
registro y cancelación de suscripción y describe el proceso de anulación del registro cuando se desinstala una
aplicación cliente.
Mensajería de nivel inferior
Cuando el servidor de la aplicación envía un mensaje de nivel inferior a la aplicación cliente, sigue los pasos que
se muestran en el diagrama siguiente:
1. El servidor de la aplicación envía el mensaje a GCM.
2. Si el dispositivo cliente no está disponible, el servidor GCM almacena el mensaje en una cola para su
posterior transmisión.
3. Cuando el dispositivo de cliente está disponible, GCM envía el mensaje a la aplicación cliente en ese
dispositivo.
4. La aplicación cliente recibe el mensaje de GCM y administra en consecuencia. Por ejemplo, si el mensaje es
una notificación remota, se presenta al usuario.
En este escenario de mensajería (donde el servidor de la aplicación envía un mensaje a una aplicación de cliente
único), los mensajes pueden hasta 4kB de longitud.
Para obtener información detallada (incluidos ejemplos de código) sobre cómo recibir mensajes de bajada GCM
en Android, consulte notificaciones remotas.
Tema de mensajería
Mensajería de tema es un tipo de mensajería de nivel inferior que el servidor de la aplicación envía un mensaje
único a varios dispositivos de la aplicación de cliente que se suscriben a un tema (por ejemplo, un pronóstico
meteorológico). Los mensajes del tema pueden ser hasta 2KB de longitud y mensajería de tema es compatible con
hasta un millón de suscripciones por aplicación. Si se usa solo para el tema de mensajería GCM, la aplicación
cliente no es necesario para enviar un token de registro al servidor de aplicaciones. Google implementar
mensajería tema se explica cómo enviar mensajes desde un servidor de aplicaciones para varios dispositivos que
se suscriben a un tema determinado.
Grupo de mensajería
Grupo mensajería es un tipo de mensajería de nivel inferior que el servidor de la aplicación envía un mensaje
único a varios dispositivos de la aplicación de cliente que pertenecen a un grupo (por ejemplo, un grupo de
dispositivos que pertenecen a un único usuario). Agrupar los mensajes pueden ser hasta 2KB de longitud para
dispositivos iOS y hasta 4KB de longitud para dispositivos Android. Un grupo se limita a un máximo de 20
miembros. Google Device Messaging grupo explica cómo los servidores de aplicaciones pueden enviar un
mensaje único a varias instancias de la aplicación cliente que se ejecutan en dispositivos que pertenecen a un
grupo.
Mensajería ascendente
Si la aplicación cliente se conecta a un servidor que admita XMPP, puede enviar mensajes al servidor de
aplicación como se muestra en el diagrama siguiente:
1. La aplicación cliente envía un mensaje en el servidor de conexión de GCM XMPP.
2. Si se desconecta el servidor de aplicaciones, el servidor GCM almacena el mensaje en una cola de
transmisión más adelante.
3. Cuando está conectado de nuevo el servidor de aplicaciones, GCM reenvía el mensaje al servidor de
aplicaciones.
4. El servidor de la aplicación analiza el mensaje para comprobar la identidad de la aplicación cliente, a
continuación, envía una confirmación"" a GCM para confirmar la recepción del mensaje.
5. El servidor de la aplicación procesa el mensaje.
Google mensajes ascendente explica cómo estructurar los mensajes codificados en JSON y enviarlos a los
servidores de aplicaciones que ejecutan el servidor de conexión de nube basada en XMPP de Google.

Configuración de Google Cloud Messaging


Para poder usar los servicios GCM en la aplicación, debe adquirir primero las credenciales para tener acceso a los
servidores de GCM de Google. Las secciones siguientes describen los pasos necesarios para completar este
proceso:
Habilitar servicios de Google para la aplicación
1. Inicie sesión en el Google Developers Console con su Google, cuenta (es decir, su dirección de gmail) y cree
un nuevo proyecto. Si tiene un proyecto existente, elija el proyecto que desee convertir en GCM habilitado.
En el ejemplo siguiente, llama a un nuevo proyecto XamarinGCM se crea:
2. A continuación, escriba el nombre del paquete de la aplicación (en este ejemplo, es el nombre del paquete
com.xamarin.gcmexample) y haga clic en continuar para elegir y configurar servicios:

Tenga en cuenta que este nombre del paquete también es el identificador de aplicación para la aplicación.
3. El elegir y configurar servicios sección enumeran los servicios de Google que se pueden agregar a la
aplicación. Haga clic en mensajería en la nube:
4. A continuación, haga clic en habilitar GOOGLE CLOUD MESSAGING:

5. Un clave de API de servidor y un Id. de remitente se generan para la aplicación. Estos valores de
registro y haga clic en cerrar:
Proteger la clave de API – no sirve para uso público. Si se pone en peligro la clave de API, los servidores no
autorizados podrían publicar mensajes en las aplicaciones cliente. Procedimientos recomendados para el
uso de forma segura las claves de API proporciona unas directrices prácticas para proteger la clave de API.
Ver la configuración del proyecto
Puede ver la configuración del proyecto en cualquier momento, inicie sesión en el consola de Google Cloud y
seleccionando el proyecto. Por ejemplo, puede ver el Id. de remitente seleccionando el proyecto en el menú
desplegable en la parte superior de la página (en este ejemplo, el proyecto se denomina XamarinGCM ). El
identificador del remitente es el número de proyecto, como se muestra en esta captura de pantalla (es el Id. de
remitente 9349932736):

Para ver el clave de API, haga clic en Manager API y, a continuación, haga clic en credenciales:
Más información
Google registrar aplicaciones de cliente describe el proceso de registro de cliente con más detalle, y se
proporciona información sobre cómo configurar el reintento automático y mantener sincronizados el
estado de registro.
RFC 6120 y 6121 RFC explicar y defina el Extensible de mensajería y el protocolo de presencia (XMPP ).

Resumen
En este artículo se proporciona información general de Google Cloud Messaging (GCM ). Explican las credenciales
distintos que se usan para identificar y autorizar a la mensajería entre los servidores de aplicaciones y las
aplicaciones cliente. Ilustran los escenarios de mensajería más comunes, y detallan los pasos para registrar la
aplicación con GCM para usar los servicios de GCM.

Vínculos relacionados
Mensajería en la nube
Notificaciones remotas con Google Cloud Messaging
16/08/2019 • 39 minutes to read • Edit Online

WARNING
Google dejó de usar GCM a partir del 10 de abril de 2018. Es posible que los siguientes documentos y proyectos de ejemplo
ya no se mantengan. El servidor y las API de cliente de GCM de Google se quitarán en cuanto 29 de mayo de 2019. Google
recomienda migrar aplicaciones de GCM a Firebase Cloud Messaging (FCM). Para obtener más información sobre el desuso
y la migración de GCM, vea Google Cloud Messaging-deprecated.
Para empezar a trabajar con las notificaciones remotas con la mensajería en la nube Firebase con Xamarin, consulte
notificaciones remotas con FCM.

En este tutorial se proporciona una explicación paso a paso de cómo usar Google Cloud Messaging para
implementar notificaciones remotas (también denominadas notificaciones de envío ) en una aplicación de
Xamarin. Android. Se describen las distintas clases que debe implementar para comunicarse con Google Cloud
Messaging (GCM ), se explica cómo establecer permisos en el manifiesto de Android para el acceso a GCM y se
muestra la mensajería de un extremo a otro con un programa de prueba de ejemplo.

Información general sobre las notificaciones de GCM


En este tutorial, vamos a crear una aplicación de Xamarin. Android que usa Google Cloud Messaging (GCM ) para
implementar notificaciones remotas (también conocidas como notificaciones de envío). Implementaremos los
diversos servicios de intención y escucha que usan GCM para la mensajería remota y probaremos nuestra
implementación con un programa de línea de comandos que simula un servidor de aplicaciones.
Para poder continuar con este tutorial, debe adquirir las credenciales necesarias para usar los servidores GCM de
Google. Este proceso se explica en Google Cloud Messaging. En concreto, necesitará una clave de API y un
identificador de remitente para insertarlos en el código de ejemplo que se muestra en este tutorial.
Usaremos los pasos siguientes para crear una aplicación cliente de Xamarin. Android habilitada para GCM:
1. Instale paquetes adicionales necesarios para las comunicaciones con servidores GCM.
2. Configure los permisos de la aplicación para el acceso a los servidores GCM.
3. Implemente el código para comprobar la presencia de Google Play Services.
4. Implemente un servicio de intención de registro que negocie con GCM para un token de registro.
5. Implemente un servicio de escucha de ID. de instancia que escuche las actualizaciones de token de registro de
GCM.
6. Implemente un servicio de escucha de GCM que reciba mensajes remotos del servidor de aplicaciones a través
de GCM.
Esta aplicación usará una nueva característica de GCM conocida como mensajería de temas. En mensajería de
tema, el servidor de aplicaciones envía un mensaje a un tema, en lugar de a una lista de dispositivos individuales.
Los dispositivos que se suscriben a ese tema pueden recibir mensajes de tema como notificaciones de envío. Para
obtener más información sobre la mensajería de temas de GCM, vea el tema sobre la implementación de
mensajería de temasde Google.
Cuando la aplicación cliente esté lista, implementaremos una aplicación de línea C# de comandos que envíe una
notificación de inserción a nuestra aplicación cliente a través de GCM.
Tutorial
Para empezar, vamos a crear una nueva solución vacía denominada RemoteNotifications. A continuación,
vamos a agregar un nuevo proyecto de Android a esta solución que se basa en la plantilla de aplicación de
Android . Vamos a llamar a este proyecto ClientApp. (Si no está familiarizado con la creación de proyectos de
Xamarin. Android, consulte Hello, Android). El proyecto ClientApp contendrá el código para la aplicación cliente
de Xamarin. Android que recibe notificaciones remotas a través de GCM.
Agregar paquetes necesarios
Antes de poder implementar el código de la aplicación cliente, debemos instalar varios paquetes que usaremos
para la comunicación con GCM. Además, debemos agregar la aplicación Google Play Store a nuestro dispositivo
si aún no está instalado.
Agregar el paquete de Xamarin Google Play Services GCM
Para recibir mensajes de Google Cloud Messaging, el marco de Google Play Services debe estar presente en el
dispositivo. Sin este marco de trabajo, una aplicación Android no puede recibir mensajes de servidores GCM.
Google Play Services se ejecuta en segundo plano mientras el dispositivo Android está encendido y escucha los
mensajes de GCM de forma silenciosa. Cuando llegan estos mensajes, Google Play Services los convierte en
intentos y, a continuación, difunde estos intentos a las aplicaciones que se han registrado para ellos.
En Visual Studio, haga clic con el botón derecho en referencias > administrar paquetes NuGet... ; en Visual
Studio para Mac, haga clic con el botón derecho en paquetes > agregar paquetes. ... Busque Xamarin Google
Play Services-GCM e instale este paquete en el proyecto ClientApp :

Al instalar xamarin Google Play Services-GCM, Xamarin Google Play Services-base se instala
automáticamente. Si recibe un error, cambie la configuración mínima de Android a destino del proyecto a un valor
distinto de compilar con la versión del SDK y vuelva a intentar la instalación de NuGet.
A continuación, edite MainActivity.CS y agregue using las siguientes instrucciones:

using Android.Gms.Common;
using Android.Util;

Esto hace que los tipos del paquete Google Play Services GMS estén disponibles para nuestro código y agrega la
funcionalidad de registro que se usará para realizar el seguimiento de las transacciones con GMS.
Google Play Store
Para recibir mensajes de GCM, la aplicación Google Play Store debe estar instalada en el dispositivo. (Siempre
que se instala una aplicación Google Play en un dispositivo, Google Play Store también se instala, por lo que es
probable que ya esté instalado en el dispositivo de prueba). Sin Google Play, una aplicación Android no puede
recibir mensajes de GCM. Si todavía no tiene la aplicación Google Play Store instalada en el dispositivo, visite el
sitio web de Google Play para descargar e instalar Google Play.
Como alternativa, puede usar un emulador de Android que ejecute Android 2,2 o posterior en lugar de un
dispositivo de prueba (no es necesario instalar Google Play Store en un emulador de Android). Sin embargo, si
usa un emulador, debe usar Wi-Fi para conectarse a GCM y debe abrir varios puertos en el Firewall de Wi-Fi,
como se explica más adelante en este tutorial.
Establecer el nombre del paquete
En Google Cloud Messaging, se especificó un nombre de paquete para nuestra aplicación habilitada para GCM
(este nombre de paquete también sirve como el identificador de la aplicación que está asociado a nuestra clave de
API y al identificador del remitente). Vamos a abrir las propiedades del proyecto ClientApp y establecer el
nombre del paquete en esta cadena. En este ejemplo, se establece el nombre del paquete com.xamarin.gcmexample
en:

Tenga en cuenta que la aplicación cliente no podrá recibir un token de registro de GCM si el nombre del paquete
no coincide exactamente con el nombre del paquete que hemos escrito en la consola para desarrolladores de
Google.
Agregar permisos al manifiesto de Android
Una aplicación Android debe tener configurados los permisos siguientes para poder recibir notificaciones de
Google Cloud Messaging:
com.google.android.c2dm.permission.RECEIVE – Concede permiso a la aplicación para registrar y recibir
mensajes de Google Cloud Messaging. (¿Qué c2dm significa? Esto significa la mensajería de la nube al
dispositivo, que es la predecesora ahora desusada para GCM. GCM todavía usa c2dm en muchas de sus
cadenas de permiso).
android.permission.WAKE_LOCK – (Opcional) impide que la CPU del dispositivo pase a suspensión mientras
escucha un mensaje.
android.permission.INTERNET – Concede acceso a Internet para que la aplicación cliente pueda comunicarse
con GCM.
nombre_paquete registra la aplicación .permission.C2D_MESSAGE con Android y solicita permiso para recibir
exclusivamente todos los mensajes C2D (de la nube al dispositivo). – El prefijo nombredepaquete es el
mismo que el identificador de la aplicación.
Estableceremos estos permisos en el manifiesto de Android. Vamos a editar archivo AndroidManifest. XML y
reemplazar el contenido por el siguiente código XML:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="YOUR_PACKAGE_NAME"
android:versionCode="1"
android:versionName="1.0"
android:installLocation="auto">
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="YOUR_PACKAGE_NAME.permission.C2D_MESSAGE" />
<permission android:name="YOUR_PACKAGE_NAME.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<application android:label="ClientApp" android:icon="@drawable/Icon">
</application>
</manifest>

En el XML anterior, cambie YOUR_PACKAGE_NAME por el nombre del paquete para su proyecto de aplicación
cliente. Por ejemplo, com.xamarin.gcmexample .
Comprobar Google Play Services
En este tutorial, vamos a crear una aplicación sin sistema operativo con un único TextView en la interfaz de
usuario. Esta aplicación no indica directamente la interacción con GCM. En su lugar, veremos la ventana de salida
para ver cómo se realiza el enlace de la aplicación con GCM y buscaremos en la bandeja de notificación las nuevas
notificaciones a medida que lleguen.
En primer lugar, vamos a crear un diseño para el área de mensajes. Edite Resources . layout. Main. axml y
reemplace el contenido por el siguiente código XML:

<?xml version="1.0" encoding="utf-8"?>


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp">
<TextView
android:text=" "
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/msgText"
android:textAppearance="?android:attr/textAppearanceMedium"
android:padding="10dp" />
</LinearLayout>

Guarde Main. axml y ciérrelo.


Cuando se inicia la aplicación cliente, queremos comprobar que Google Play Services está disponible antes de
intentar ponerse en contacto con GCM. Edite MainActivity.CS y reemplace count la declaración de la variable
de instancia por la siguiente declaración de variable de instancia:

TextView msgText;

A continuación, agregue el método siguiente a la clase MainActivity :


public bool IsPlayServicesAvailable ()
{
int resultCode = GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable (this);
if (resultCode != ConnectionResult.Success)
{
if (GoogleApiAvailability.Instance.IsUserResolvableError (resultCode))
msgText.Text = GoogleApiAvailability.Instance.GetErrorString (resultCode);
else
{
msgText.Text = "Sorry, this device is not supported";
Finish ();
}
return false;
}
else
{
msgText.Text = "Google Play Services is available.";
return true;
}
}

Este código comprueba el dispositivo para ver si está instalado el Google Play Services APK. Si no está instalado,
se muestra un mensaje en el área de mensajes que indica al usuario que descargue un APK del Google Play Store
(o habilítelo en la configuración del sistema del dispositivo). Dado que deseamos ejecutar esta comprobación
cuando se inicia la aplicación cliente, agregaremos una llamada a este método al final de OnCreate .
A continuación, reemplace OnCreate el método por el código siguiente:

protected override void OnCreate (Bundle bundle)


{
base.OnCreate (bundle);

SetContentView (Resource.Layout.Main);
msgText = FindViewById<TextView> (Resource.Id.msgText);

IsPlayServicesAvailable ();
}

Este código comprueba la presencia del Google Play Services APK y escribe el resultado en el área de mensajes.
Vamos a volver a compilar y ejecutar la aplicación por completo. Debería ver una pantalla similar a la siguiente
captura de pantalla:
Si no obtiene este resultado, compruebe que el Google Play Services APK está instalado en el dispositivo y que el
paquete Xamarin Google Play Services-GCM se agrega al proyecto ClientApp como se explicó anteriormente.
Si obtiene un error de compilación, intente limpiar la solución y compilar el proyecto de nuevo.
A continuación, escribiremos código para ponerse en contacto con GCM y obtener un token de registro.
Registro con GCM
Antes de que la aplicación pueda recibir notificaciones remotas del servidor de aplicaciones, debe registrarse en
GCM y obtener un token de registro. El trabajo de registro de la aplicación con GCM se controla mediante
IntentService el que se crea. Nuestro IntentService realiza los pasos siguientes:

1. Usa la API InstanceID para generar tokens de seguridad que autorizan a la aplicación cliente a acceder al
servidor de aplicaciones. A cambio, recibimos un token de registro de GCM.
2. Reenvía el token de registro al servidor de aplicaciones (si el servidor de aplicaciones lo requiere).
3. Se suscribe a uno o varios canales de temas de notificación.
Después de implementarlo IntentService , lo probaremos para ver si obtenemos un token de registro de GCM.
Agregue un nuevo archivo denominado RegistrationIntentService.CS y reemplace el código de plantilla por lo
siguiente:
using System;
using Android.App;
using Android.Content;
using Android.Util;
using Android.Gms.Gcm;
using Android.Gms.Gcm.Iid;

namespace ClientApp
{
[Service(Exported = false)]
class RegistrationIntentService : IntentService
{
static object locker = new object();

public RegistrationIntentService() : base("RegistrationIntentService") { }

protected override void OnHandleIntent (Intent intent)


{
try
{
Log.Info ("RegistrationIntentService", "Calling InstanceID.GetToken");
lock (locker)
{
var instanceID = InstanceID.GetInstance (this);
var token = instanceID.GetToken (
"YOUR_SENDER_ID", GoogleCloudMessaging.InstanceIdScope, null);

Log.Info ("RegistrationIntentService", "GCM Registration Token: " + token);


SendRegistrationToAppServer (token);
Subscribe (token);
}
}
catch (Exception e)
{
Log.Debug("RegistrationIntentService", "Failed to get a registration token");
return;
}
}

void SendRegistrationToAppServer (string token)


{
// Add custom implementation here as needed.
}

void Subscribe (string token)


{
var pubSub = GcmPubSub.GetInstance(this);
pubSub.Subscribe(token, "/topics/global", null);
}
}
}

En el código de ejemplo anterior, cambie YOUR_SENDER_ID por el número de identificación del remitente del
proyecto de la aplicación cliente. Para obtener el identificador del remitente del proyecto:
1. Inicie sesión en la consola de Google Cloud y seleccione el nombre del proyecto en el menú desplegable.
En el panel de información del proyecto que se muestra para el proyecto, haga clic en ir a
configuración del proyecto:
2. En la página configuración , busque el número – de proyecto que es el identificador del remitente del
proyecto:

Queremos iniciar nuestro RegistrationIntentService cuando la aplicación comience a ejecutarse. Edite


MainActivity.CS y modifique OnCreate el RegistrationIntentService método para que se inicie después de
comprobar la presencia de Google Play Services:

protected override void OnCreate (Bundle bundle)


{
base.OnCreate (bundle);

SetContentView(Resource.Layout.Main);
msgText = FindViewById<TextView> (Resource.Id.msgText);

if (IsPlayServicesAvailable ())
{
var intent = new Intent (this, typeof (RegistrationIntentService));
StartService (intent);
}
}

Ahora, echemos un vistazo a cada sección de RegistrationIntentService para entender cómo funciona.
En primer lugar, anotamos RegistrationIntentService nuestro con el siguiente atributo para indicar que el sistema
no debe crear instancias del servicio:

[Service (Exported = false)]

El RegistrationIntentService constructor nombra el subproceso de trabajo RegistrationIntentService para facilitar


la depuración.
public RegistrationIntentService() : base ("RegistrationIntentService") { }

La funcionalidad básica de RegistrationIntentService reside en el OnHandleIntent método. Vamos a examinar


este código para ver cómo registra nuestra aplicación con GCM.
So l i c i t a r u n t o k e n d e r e g i st r o

OnHandleIntent primero llama al método InstanceID. GetToken de Google para solicitar un token de registro de
GCM. Encapsulamos este código en un lock para protegerse frente a la posibilidad de que se produzcan varios –
intentos lock de registro al mismo tiempo, lo que garantiza que estas intenciones se procesan de forma
secuencial. Si no se puede obtener un token de registro, se produce una excepción y se registra un error. Si el
registro se realiza correctamente token , se establece en el token de registro que obtuvimos de GCM:

static object locker = new object ();


...
try
{
lock (locker)
{
var instanceID = InstanceID.GetInstance (this);
var token = instanceID.GetToken (
"YOUR_SENDER_ID", GoogleCloudMessaging.InstanceIdScope, null);
...
}
}
catch (Exception e)
{
Log.Debug ...

R e e n v i a r e l t o k e n d e r e g i st r o a l se r v i d o r d e a p l i c a c i o n e s

Si obtenemos un token de registro (es decir, no se produjo ninguna excepción), SendRegistrationToAppServer


llamamos a para asociar el token de registro del usuario con la cuenta del lado servidor (si existe) que mantiene
nuestra aplicación. Dado que esta implementación depende del diseño del servidor de aplicaciones, se
proporciona un método vacío aquí:

void SendRegistrationToAppServer (string token)


{
// Add custom implementation here as needed.
}

En algunos casos, el servidor de aplicaciones no necesita el token de registro del usuario. en ese caso, se puede
omitir este método. Cuando se envía un token de registro al servidor de aplicaciones SendRegistrationToAppServer
, debe mantener un valor booleano para indicar si el token se ha enviado al servidor. Si este valor booleano es
false SendRegistrationToAppServer , envía el token al servidor – de aplicaciones; de lo contrario, el token ya se
envió al servidor de aplicaciones en una llamada anterior.
Su sc r i b i r se a l t e m a d e n o t i fi c a c i ó n

A continuación, llamamos a Subscribe nuestro método para indicar a GCM que queremos suscribirte a un tema
de notificación. En Subscribe , llamamos a la API GcmPubSub. subscribe para suscribir la aplicación cliente a
todos los /topics/global mensajes en:

void Subscribe (string token)


{
var pubSub = GcmPubSub.GetInstance(this);
pubSub.Subscribe(token, "/topics/global", null);
}
El servidor de aplicaciones debe enviar mensajes de /topics/global notificación a si se van a recibir. Tenga en
cuenta que el nombre /topics del tema en puede ser cualquier cosa que desee, siempre que el servidor de
aplicaciones y la aplicación cliente acuerden estos nombres. (Aquí, elegimos el nombre global para indicar que
queremos recibir mensajes en todos los temas admitidos por el servidor de aplicaciones).
Para obtener información sobre la mensajería de temas de GCM en el lado del servidor, vea el tema sobre Cómo
enviar mensajes de Google a temas.
Implementar un servicio de escucha de ID. de instancia
Los tokens de registro son únicos y seguros. sin embargo, es posible que la aplicación cliente (o GCM ) necesite
actualizar el token de registro en caso de que se vuelva a instalar la aplicación o un problema de seguridad. Por
esta razón, debemos implementar una InstanceIdListenerService que responda a las solicitudes de actualización
de tokens desde GCM.
Agregue un nuevo archivo denominado InstanceIdListenerService.CS y reemplace el código de plantilla por lo
siguiente:

using Android.App;
using Android.Content;
using Android.Gms.Gcm.Iid;

namespace ClientApp
{
[Service(Exported = false), IntentFilter(new[] { "com.google.android.gms.iid.InstanceID" })]
class MyInstanceIDListenerService : InstanceIDListenerService
{
public override void OnTokenRefresh()
{
var intent = new Intent (this, typeof (RegistrationIntentService));
StartService (intent);
}
}
}

Anote con el siguiente atributo para indicar que el sistema no debe crear una instancia del servicio y que puede
recibir solicitudes de actualización del token de registro de GCM (también denominado identificador de instancia):
InstanceIdListenerService

[Service(Exported = false), IntentFilter(new[] { "com.google.android.gms.iid.InstanceID" })]

El OnTokenRefresh método en nuestro servicio inicia el RegistrationIntentService para que pueda interceptar el
nuevo token de registro.
Registro de prueba con GCM
Vamos a volver a compilar y ejecutar la aplicación por completo. Si recibe correctamente un token de registro de
GCM, el token de registro debe mostrarse en la ventana de salida. Por ejemplo:

D/Mono ( 1934): Assembly Ref addref ClientApp[0xb4ac2400] -> Xamarin.GooglePlayServices.Gcm[0xb4ac2640]: 2


I/RegistrationIntentService( 1934): Calling InstanceID.GetToken
I/RegistrationIntentService( 1934): GCM Registration Token: f8LdveCvXig:APA91bFIsjUAbP-
V8TPQdLR89qQbEJh1SYG38AcCbBUf34z5gSdUc5OsXrgs93YFiGcRSRafPfzkz23lf3-LvYV1CwrFheMjHgwPeFSh12MywnRIhz

Controlar mensajes de nivel inferior


El código que hemos implementado hasta ahora es solo el código "configurado". comprueba si está instalado
Google Play Services y negocia con GCM y el servidor de aplicaciones para preparar la aplicación cliente para
recibir notificaciones remotas. Sin embargo, todavía hemos implementado código que realmente recibe y procesa
los mensajes de notificación de nivel inferior. Para ello, debemos implementar un servicio de escucha de GCM.
Este servicio recibe mensajes de tema del servidor de aplicaciones y los difunde localmente como notificaciones.
Después de implementar este servicio, vamos a crear un programa de prueba para enviar mensajes a GCM, de
modo que podamos ver si nuestra implementación funciona correctamente.
Icono Agregar un aviso
En primer lugar, vamos a agregar un icono pequeño que aparecerá en el área de notificación cuando se inicie la
notificación. Puede copiar este icono en el proyecto o crear su propio icono personalizado. Asignaremos el
nombre ic_stat_button_click. png al archivo de icono y lo copiaremos en la carpeta Resources /drawable . No
olvide usar agregar > elemento existente... para incluir este archivo de icono en el proyecto.
Implementar un servicio de escucha de GCM
Agregue un nuevo archivo denominado GcmListenerService.CS y reemplace el código de plantilla por lo
siguiente:

using Android.App;
using Android.Content;
using Android.OS;
using Android.Gms.Gcm;
using Android.Util;

namespace ClientApp
{
[Service (Exported = false), IntentFilter (new [] { "com.google.android.c2dm.intent.RECEIVE" })]
public class MyGcmListenerService : GcmListenerService
{
public override void OnMessageReceived (string from, Bundle data)
{
var message = data.GetString ("message");
Log.Debug ("MyGcmListenerService", "From: " + from);
Log.Debug ("MyGcmListenerService", "Message: " + message);
SendNotification (message);
}

void SendNotification (string message)


{
var intent = new Intent (this, typeof(MainActivity));
intent.AddFlags (ActivityFlags.ClearTop);
var pendingIntent = PendingIntent.GetActivity (this, 0, intent, PendingIntentFlags.OneShot);

var notificationBuilder = new Notification.Builder(this)


.SetSmallIcon (Resource.Drawable.ic_stat_ic_notification)
.SetContentTitle ("GCM Message")
.SetContentText (message)
.SetAutoCancel (true)
.SetContentIntent (pendingIntent);

var notificationManager = (NotificationManager)GetSystemService(Context.NotificationService);


notificationManager.Notify (0, notificationBuilder.Build());
}
}
}

Echemos un vistazo a cada sección de nuestro GcmListenerService para entender cómo funciona.
En primer lugar, se GcmListenerService anota con un atributo para indicar que el sistema no debe crear instancias
de este servicio, y se incluye un filtro de intención para indicar que recibe mensajes GCM:

[Service (Exported = false), IntentFilter (new [] { "com.google.android.c2dm.intent.RECEIVE" })]

Cuando GcmListenerService recibe un mensaje de GCM, se OnMessageReceived invoca el método. Este método
extrae el contenido del mensaje del pasado Bundle , registra el contenido del mensaje (para que podamos verlo en
la ventana de salida) y llama SendNotification a para iniciar una notificación local con el contenido del mensaje
recibido:

var message = data.GetString ("message");


Log.Debug ("MyGcmListenerService", "From: " + from);
Log.Debug ("MyGcmListenerService", "Message: " + message);
SendNotification (message);

El SendNotification método utiliza Notification.Builder para crear la notificación NotificationManager y, a


continuación, utiliza para iniciar la notificación. De hecho, esto convierte el mensaje de notificación remota en una
notificación local que se va a presentar al usuario. Para obtener más información sobre Notification.Builder el
NotificationManager uso de y, consulte notificaciones locales.

Declarar el receptor en el manifiesto


Antes de poder recibir mensajes de GCM, debemos declarar el agente de escucha de GCM en el manifiesto de
Android. Vamos a editar archivo AndroidManifest. XML y reemplazar la <application> sección por el siguiente
código XML:

<application android:label="RemoteNotifications" android:icon="@drawable/Icon">


<receiver android:name="com.google.android.gms.gcm.GcmReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="YOUR_PACKAGE_NAME" />
</intent-filter>
</receiver>
</application>

En el XML anterior, cambie YOUR_PACKAGE_NAME por el nombre del paquete para su proyecto de aplicación
cliente. En el ejemplo del tutorial, el nombre del com.xamarin.gcmexample paquete es.
Echemos un vistazo a cada una de las opciones de este XML:

PARÁMETRO DESCRIPCIÓN

com.google.android.gms.gcm.GcmReceiver Declara que nuestra aplicación implementa un receptor de


GCM que captura y procesa los mensajes entrantes de
notificaciones de entrada.

com.google.android.c2dm.permission.SEND Declara que solo los servidores GCM pueden enviar mensajes
directamente a la aplicación.

com.google.android.c2dm.intent.RECEIVE El filtro de intención anuncia que nuestra aplicación controla


los mensajes de difusión desde GCM.

com.google.android.c2dm.intent.REGISTRATION El filtro de intención anuncia que nuestra aplicación controla


nuevos intentos de registro (es decir, que hemos
implementado un servicio de escucha de ID. de instancia).

Como alternativa, puede decorar GcmListenerService con estos atributos en lugar de especificarlos en XML; aquí
se especifican en archivo AndroidManifest. XML para que los ejemplos de código sean más fáciles de seguir.
Creación de un remitente de mensaje para probar la aplicación
Vamos a agregar un C# proyecto de aplicación de consola de escritorio a la solución y llamarlo MessageSender.
Usaremos esta aplicación de consola para simular un servidor – de aplicaciones que enviará mensajes de
notificación a ClientApp a través de GCM.
Agregar el paquete Json.NET
En esta aplicación de consola, vamos a crear una carga de JSON que contiene el mensaje de notificación que
queremos enviar a la aplicación cliente. Usaremos el paquete JSON.net en MessageSender para que sea más
fácil crear el objeto JSON que GCM necesita. En Visual Studio, haga clic con el botón derecho en referencias >
administrar paquetes NuGet... ; en Visual Studio para Mac, haga clic con el botón derecho en paquetes >
agregar paquetes. ...
Vamos a buscar el paquete JSON.net e instalarlo en el proyecto:

Agregar una referencia a System .net. http


También tendremos que agregar una referencia a System.Net.Http para que podamos crear una instancia
HttpClient de para enviar el mensaje de prueba a GCM. En el proyecto MessageSender , haga clic con el botón
secundario en referencias > Agregar referencia y desplácese hacia abajo hasta que vea System .net. http.
Coloque una marca de verificación junto a System .net. http y haga clic en Aceptar.
Implementar código que envía un mensaje de prueba
En MessageSender, edite Program.CS y reemplace el contenido por el código siguiente:
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;

namespace MessageSender
{
class MessageSender
{
public const string API_KEY = "YOUR_API_KEY";
public const string MESSAGE = "Hello, Xamarin!";

static void Main (string[] args)


{
var jGcmData = new JObject();
var jData = new JObject();

jData.Add ("message", MESSAGE);


jGcmData.Add ("to", "/topics/global");
jGcmData.Add ("data", jData);

var url = new Uri ("https://gcm-http.googleapis.com/gcm/send");


try
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));

client.DefaultRequestHeaders.TryAddWithoutValidation (
"Authorization", "key=" + API_KEY);

Task.WaitAll(client.PostAsync (url,
new StringContent(jGcmData.ToString(), Encoding.Default, "application/json"))
.ContinueWith(response =>
{
Console.WriteLine(response);
Console.WriteLine("Message sent: check the client device notification tray.");
}));
}
}
catch (Exception e)
{
Console.WriteLine("Unable to send GCM message:");
Console.Error.WriteLine(e.StackTrace);
}
}
}
}

En el código anterior, cambie YOUR_API_KEY a la clave de API del proyecto de la aplicación cliente.
Este servidor de aplicaciones de prueba envía el siguiente mensaje con formato JSON a GCM:

{
"to": "/topics/global",
"data": {
"message": "Hello, Xamarin!"
}
}

GCM, a su vez, reenvía este mensaje a la aplicación cliente. Vamos a compilar MessageSender y abrir una
ventana de consola en la que se puede ejecutar desde la línea de comandos.
¡Inténtelo!
Ahora estamos listos para probar la aplicación cliente. Si utiliza un emulador o si el dispositivo se comunica con
GCM a través de Wi-Fi, debe abrir los siguientes puertos TCP en el firewall para que los mensajes de GCM
lleguen: 5228, 5229 y 5230.
Inicie la aplicación cliente y vea la ventana de salida. Después de RegistrationIntentService que el reciba
correctamente un token de registro de GCM, la ventana de salida debería mostrar el token con una salida de
registro similar a la siguiente:

I/RegistrationIntentService(16103): GCM Registration Token: eX9ggabZV1Q:APA91bHjBnQXMUeBOT6JDiLpRt8m2YWtY ...

En este momento, la aplicación cliente está lista para recibir un mensaje de notificación remota. Desde la línea de
comandos, ejecute el programa MessageSender. exe para enviar un mensaje de notificación "Hello, Xamarin" a
la aplicación cliente. Si aún no ha compilado el proyecto MessageSender , hágalo ahora.
Para ejecutar MessageSender. exe en Visual Studio, abra un símbolo del sistema, cambie al directorio
MessageSender/bin/Debug y ejecute el comando directamente:

MessageSender.exe

Para ejecutar MessageSender. exe en Visual Studio para Mac, abra una sesión de terminal, cambie a
MessageSender/bin/depure el directorio y use mono para ejecutar MessageSender. exe.

mono MessageSender.exe

El mensaje puede tardar hasta un minuto en propagarse a través de GCM y volver a la aplicación cliente. Si el
mensaje se recibe correctamente, debería ver un resultado similar al siguiente en la ventana de salida:

D/MyGcmListenerService(16103): From: /topics/global


D/MyGcmListenerService(16103): Message: Hello, Xamarin!

Además, debe observar que aparece un nuevo icono de notificación en la bandeja de notificación:
Al abrir la bandeja de notificación para ver las notificaciones, debería ver nuestra notificación remota:

Enhorabuena, la aplicación ha recibido su primera notificación remota.


Tenga en cuenta que ya no se recibirán mensajes de GCM si la aplicación se detiene forzosamente. Para reanudar
las notificaciones después de una detención forzada, la aplicación debe reiniciarse manualmente. Para más
información sobre esta directiva de Android, consulte Inicio de controles en aplicaciones detenidas y este envío de
desbordamiento de pila.

Resumen
En este tutorial se detallan los pasos para implementar notificaciones remotas en una aplicación de Xamarin.
Android. Se describe cómo instalar los paquetes adicionales necesarios para las comunicaciones de GCM y se
explica cómo configurar los permisos de aplicación para el acceso a los servidores GCM. Proporciona código de
ejemplo que muestra cómo comprobar la presencia de Google Play Services, cómo implementar un servicio de
control de la intención de registro y un servicio de escucha de ID. de instancia que negocia con GCM para un
token de registro y cómo implementar un agente de escucha de GCM servicio que recibe y procesa los mensajes
de notificación remotos. Por último, hemos implementado un programa de prueba de línea de comandos para
enviar notificaciones de prueba a nuestra aplicación cliente a través de GCM.

Vínculos relacionados
RemoteNotifications de GCM (ejemplo)
Google Cloud Messaging
Introducción a los servicios web
16/08/2019 • 30 minutes to read • Edit Online

En esta guía se muestra cómo consumir diferentes tecnologías de servicios Web. Entre los temas tratados se
incluyen la comunicación con servicios REST, servicios SOAP y servicios de Windows Communication Foundation.
Para que funcione correctamente, muchas aplicaciones móviles dependen de la nube y, por tanto, la integración de
servicios web en aplicaciones móviles es un escenario común. La plataforma Xamarin admite el consumo de
distintas tecnologías de servicios web e incluye compatibilidad integrada y de terceros para consumir servicios
RESTful, ASMX y Windows Communication Foundation (WCF ).
En el caso de los clientes que usan Xamarin. Forms, hay ejemplos completos que usan cada una de estas
tecnologías en la documentación de servicios Web de Xamarin. Forms .

IMPORTANT
En iOS 9, la seguridad de transporte de aplicaciones (ATS) exige conexiones seguras entre los recursos de Internet (como el
servidor back-end de la aplicación) y la aplicación, lo que evita la divulgación accidental de información confidencial. Puesto
que ATS está habilitada de forma predeterminada en las aplicaciones compiladas para iOS 9, todas las conexiones estará
sujeto a los requisitos de seguridad ATS. Si las conexiones no cumplen estos requisitos, se producirá un error con una
excepción.

Puede optar por ATS si no es posible usar el protocolo y proteger la HTTPS comunicación de los recursos de
Internet. Esto puede lograrse mediante la actualización de la aplicación Info.plist archivo. Para obtener más
información, consulte App Transport Security.

REST
Representational State Transfer (REST) es un estilo de arquitectura para la creación de servicios web. Solicitudes
REST se realizan a través de HTTP utilizando los mismos verbos HTTP que los exploradores web que se usan para
recuperar las páginas web y para enviar datos a los servidores. Los verbos son:
OBTENER : esta operación se usa para recuperar datos desde el servicio web.
POST : esta operación se usa para crear un nuevo elemento de datos en el servicio web.
COLOCAR : esta operación se usa para actualizar un elemento de datos en el servicio web.
REVISIÓN : esta operación se usa para actualizar un elemento de datos en el servicio web con la descripción
de un conjunto de instrucciones sobre cómo se debe modificar el elemento. No se utiliza este verbo en la
aplicación de ejemplo.
ELIMINAR : esta operación se usa para eliminar un elemento de datos en el servicio web.
Se llama a las API de RESTful API que se adhieren a REST del servicio Web y se definen mediante:
Un URI base.
Métodos HTTP, como GET, POST, PUT, PATCH o DELETE.
Tipo de medio de los datos, como JavaScript Object Notation (JSON ).
La simplicidad de REST ha ayudado a hacer el método principal para tener acceso a servicios web en aplicaciones
móviles.

Consumo de servicios REST


Hay una serie de bibliotecas y clases que se pueden usar para consumir servicios REST, y en las subsecciones
siguientes se describen. Para obtener más información sobre cómo consumir un servicio REST, consulte consumo
de un servicio web RESTful.
HttpClient
Las bibliotecas de cliente http de Microsoft HttpClient proporcionan la clase, que se utiliza para enviar y recibir
solicitudes a través de http. Proporciona funcionalidad para enviar solicitudes HTTP y recibir respuestas HTTP de
un recurso identificado por URI. Cada solicitud se envía como una operación asincrónica. Para obtener más
información acerca de las operaciones asincrónicas, vea información general de soporte técnico de Async.
La HttpResponseMessage clase representa un mensaje de respuesta HTTP recibido del servicio web después de
realizar una solicitud HTTP. Contiene información sobre la respuesta, incluido el código de estado, los encabezados
y el cuerpo. El HttpContent clase representa el cuerpo HTTP y encabezados de contenido, como Content-Type y
Content-Encoding . El contenido se puede leer utilizando cualquiera de los ReadAs métodos, como
ReadAsStringAsync y ReadAsByteArrayAsync , dependiendo del formato de los datos.

Para obtener más información sobre HttpClient la clase, vea crear el objeto HTTPClient.
HTTPWebRequest
La llamada a servicios HTTPWebRequest web con implica:
Crear la instancia de solicitud para un URI determinado.
Establecer varias propiedades HTTP en la instancia de la solicitud.
Recuperar un HttpWebResponse de la solicitud.
Lectura de datos de la respuesta.
Por ejemplo, el código siguiente recupera datos de la Servicio Web de la Biblioteca Nacional de medicina:

var rxcui = "198440";


var request = HttpWebRequest.Create(string.Format(@"http://rxnav.nlm.nih.gov/REST/RxTerms/rxcui/{0}/allinfo",
rxcui));
request.ContentType = "application/json";
request.Method = "GET";

using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)


{
if (response.StatusCode != HttpStatusCode.OK)
Console.Out.WriteLine("Error fetching data. Server returned status code: {0}", response.StatusCode);
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
var content = reader.ReadToEnd();
if(string.IsNullOrWhiteSpace(content)) {
Console.Out.WriteLine("Response contained empty body...");
}
else {
Console.Out.WriteLine("Response Body: \r\n {0}", content);
}

Assert.NotNull(content);
}
}

En el ejemplo anterior se HttpWebRequest crea un que devolverá datos con formato JSON. Los datos se devuelven
HttpWebResponse en un, desde StreamReader el que se puede obtener para leer los datos.

RestSharp
Otro enfoque para consumir servicios REST es usar la biblioteca RestSharp . RestSharp encapsula las solicitudes
HTTP, incluida la compatibilidad para recuperar los resultados como contenido de cadena sin formato o como un
C# objeto deserializado. Por ejemplo, el código siguiente realiza una solicitud a la Servicio Web de la Biblioteca
Nacional de medicina y recupera los resultados como una cadena con formato JSON:

var request = new RestRequest(string.Format("{0}/allinfo", rxcui));


request.RequestFormat = DataFormat.Json;
var response = Client.Execute(request);
if(string.IsNullOrWhiteSpace(response.Content) || response.StatusCode != System.Net.HttpStatusCode.OK) {
return null;
}
rxTerm = DeserializeRxTerm(response.Content);

DeserializeRxTerm es un método que tomará la cadena JSON sin formato de RestSharp.RestResponse.Content la


propiedad y la convertirá C# en un objeto. La deserialización de los datos devueltos de los servicios web se
describe más adelante en este artículo.
NSUrlConnection
Además de las clases disponibles en la biblioteca de clases base (BCL ) mono, HttpWebRequest como y las C#
bibliotecas de terceros, como RestSharp, las clases específicas de la plataforma también están disponibles para
consumir servicios Web. Por ejemplo, en iOS, se NSUrlConnection pueden NSMutableUrlRequest usar las clases y.
En el ejemplo de código siguiente se muestra cómo llamar a la Servicio Web de la Biblioteca Nacional de medicina
mediante clases de iOS:

var rxcui = "198440";


var request = new NSMutableUrlRequest(new
NSUrl(string.Format("http://rxnav.nlm.nih.gov/REST/RxTerms/rxcui/{0}/allinfo", rxcui)),
NSUrlRequestCachePolicy.ReloadRevalidatingCacheData, 20);
request["Accept"] = "application/json";

var connectionDelegate = new RxTermNSURLConnectionDelegate();


var connection = new NSUrlConnection(request, connectionDelegate);
connection.Start();

public class RxTermNSURLConnectionDelegate : NSUrlConnectionDelegate


{
StringBuilder _ResponseBuilder;
public bool IsFinishedLoading { get; set; }
public string ResponseContent { get; set; }

public RxTermNSURLConnectionDelegate()
: base()
{
_ResponseBuilder = new StringBuilder();
}

public override void ReceivedData(NSUrlConnection connection, NSData data)


{
if(data != null) {
_ResponseBuilder.Append(data.ToString());
}
}
public override void FinishedLoading(NSUrlConnection connection)
{
IsFinishedLoading = true;
ResponseContent = _ResponseBuilder.ToString();
}
}

Por lo general, las clases específicas de la plataforma para consumir servicios web se deben limitar a escenarios en
los que se va C#a migrar código nativo. Siempre que sea posible, el código de acceso al servicio Web debe ser
portable para que se pueda compartir entre plataformas.
ServiceStack
Otra opción para llamar a los servicios web es la biblioteca de pila de servicios . Por ejemplo, el código siguiente
muestra cómo usar el método de la IServiceClient.GetAsync pila de servicio para emitir una solicitud de servicio:

client.GetAsync<CustomersResponse>("",
(response) => {
foreach(var c in response.Customers) {
Console.WriteLine(c.CompanyName);
}
},
(response, ex) => {
Console.WriteLine(ex.Message);
});

IMPORTANT
Aunque herramientas como ServiceStack y RestSharp facilitan la llamada y el consumo de servicios de REST, a veces no es
trivial usar XML o JSON que no se ajuste a las convenciones de serialización de DataContract estándar. Si es necesario,
invoque la solicitud y controle la serialización adecuada explícitamente mediante la biblioteca ServiceStack. Text que se
describe a continuación.

Consumir datos de RESTful


Servicios web rESTful normalmente utilizan mensajes JSON para devolver datos al cliente. JSON es un formato de
intercambio de datos basado en texto que genera cargas compactos, lo que reduce los requisitos de ancho de
banda cuando se envían datos. En esta sección, se examinarán los mecanismos para consumir respuestas RESTful
en JSON y el código XML (POX).
System.JSON
La plataforma Xamarin incluye compatibilidad con JSON fuera de la caja. Mediante el uso JsonObject de, los
resultados se pueden recuperar como se muestra en el ejemplo de código siguiente:

var obj = JsonObject.Parse(json);


var properties = obj["rxtermsProperties"];
term.BrandName = properties["brandName"];
term.DisplayName = properties["displayName"];
term.Synonym = properties["synonym"];
term.FullName = properties["fullName"];
term.FullGenericName = properties["fullGenericName"];
term.Strength = properties["strength"];

Sin embargo, es importante tener en cuenta que las System.Json herramientas de cargan la totalidad de los datos
en la memoria.
JSON.NET
La biblioteca de NewtonSoft JSON.net es una biblioteca ampliamente usada para serializar y deserializar mensajes
JSON. En el ejemplo de código siguiente se muestra cómo usar JSON.NET para deserializar un mensaje JSON C#
en un objeto:
var term = new RxTerm();
var properties = JObject.Parse(json)["rxtermsProperties"];
term.BrandName = properties["brandName"].Value<string>();
term.DisplayName = properties["displayName"].Value<string>();
term.Synonym = properties["synonym"].Value<string>();;
term.FullName = properties["fullName"].Value<string>();;
term.FullGenericName = properties["fullGenericName"].Value<string>();;
term.Strength = properties["strength"].Value<string>();
term.RxCUI = properties["rxcui"].Value<string>();

ServiceStack.Text
ServiceStack. Text es una biblioteca de serialización de JSON diseñada para trabajar con la biblioteca de
ServiceStack. En el ejemplo de código siguiente se muestra cómo analizar JSON ServiceStack.Text.JsonObject
mediante un:

var result = JsonObject.Parse(json).Object("rxtermsProperties")


.ConvertTo(x => new RxTerm {
BrandName = x.Get("brandName"),
DisplayName = x.Get("displayName"),
Synonym = x.Get("synonym"),
FullName = x.Get("fullName"),
FullGenericName = x.Get("fullGenericName"),
Strength = x.Get("strength"),
RxTermDoseForm = x.Get("rxtermsDoseForm"),
Route = x.Get("route"),
RxCUI = x.Get("rxcui"),
RxNormDoseForm = x.Get("rxnormDoseForm"),
});

System.Xml.Linq
En el caso de consumir un servicio Web REST basado en XML, LINQ to XML se puede utilizar para analizar el
XML y rellenar C# un objeto insertado, tal y como se muestra en el ejemplo de código siguiente:

var doc = XDocument.Parse(xml);


var result = doc.Root.Descendants("rxtermsProperties")
.Select(x=> new RxTerm()
{
BrandName = x.Element("brandName").Value,
DisplayName = x.Element("displayName").Value,
Synonym = x.Element("synonym").Value,
FullName = x.Element("fullName").Value,
FullGenericName = x.Element("fullGenericName").Value,
//bind more here...
RxCUI = x.Element("rxcui").Value,
});

Servicio Web ASP.NET (ASMX)


ASMX proporciona la capacidad de compilar servicios web que envían mensajes mediante el Protocolo simple de
acceso a objetos (SOAP ). SOAP es un protocolo independiente de la plataforma y lenguaje para crear y obtener
acceso a servicios web. Los consumidores de un servicio de ASMX no es necesario saber nada acerca de la
plataforma, el modelo de objetos o el lenguaje de programación usado para implementar el servicio. Sólo
necesitan entender cómo enviar y recibir mensajes SOAP.
Un mensaje SOAP es un documento XML que contiene los siguientes elementos:
Un elemento raíz denominado sobres que identifica el documento XML como un mensaje SOAP.
Opcional encabezado elemento que contiene información específica de la aplicación, como datos de
autenticación. Si el encabezado elemento está presente debe ser el primer elemento secundario de la sobres
elemento.
Obligatoria cuerpo elemento que contiene el mensaje SOAP, diseñado para el destinatario.
Opcional error elemento que se usa para indicar los mensajes de error. Si el error elemento está presente, debe
ser un elemento secundario de la cuerpo elemento.
SOAP puede operar en muchos protocolos de transporte, incluidos HTTP, SMTP, TCP y UDP. Sin embargo, un
servicio de ASMX solo puede funcionar a través de HTTP. La plataforma Xamarin es compatible con las
implementaciones estándar de SOAP 1.1 a través de HTTP, y esto incluye compatibilidad con muchas de las
configuraciones estándar de servicio ASMX.
Generación de un proxy
Se debe generar un proxy para consumir un servicio asmx, lo que permite que la aplicación se conecte al servicio.
El proxy se construye por consumir los metadatos del servicio que define los métodos y la configuración del
servicio asociado. Estos metadatos se exponen como un documento de lenguaje de descripción de servicios web
(WSDL ) generado por el servicio Web. El proxy se compila con Visual Studio para Mac o Visual Studio para
agregar una referencia Web para el servicio Web a los proyectos específicos de la plataforma.
La dirección URL del servicio web puede ser un recurso de origen remoto hospedado o del sistema de file:///
archivos local accesible a través del prefijo de la ruta de acceso, por ejemplo:

file:///Users/myUserName/projects/MyProjectName/service.wsdl

Esto genera el proxy en la carpeta de referencias de servicio o web del proyecto. Dado que un proxy se genera
código, no debe modificarse.
Agregar manualmente un proxy a un proyecto
Si tiene un proxy existente que se ha generado mediante herramientas compatibles, esta salida se puede consumir
cuando se incluye como parte del proyecto. En Visual Studio para Mac, use la . . opción de menú para agregar el
proxy. Además, esto requiere que se haga referencia a System. Web. Services. dll explícitamente mediante la
adición de referencias. . diálogo.
Consumir el proxy
Las clases de proxy generadas proporcionan métodos para consumir el servicio web que usan el patrón de diseño
del modelo de programación asincrónica (APM ). En este patrón de una operación asincrónica se implementa como
dos métodos denominados BeginOperationName y EndOperationName, que comienzan y terminan la operación
asincrónica.
El BeginOperationName método comienza la operación asincrónica y devuelve un objeto que implementa el
IAsyncResult interfaz. Después de llamar a BeginOperationName, una aplicación puede seguir ejecutando
instrucciones en el subproceso de llamada mientras lleva a la operación asincrónica en un subproceso ThreadPool.
Para cada llamada a BeginOperationName, también debe llamar la aplicación EndOperationName para obtener
los resultados de la operación. El valor devuelto de EndOperationName es el mismo tipo devuelto por el método
de servicio web sincrónico. El ejemplo de código siguiente muestra un ejemplo:

public async Task<List<TodoItem>> RefreshDataAsync ()


{
...
var todoItems = await Task.Factory.FromAsync<ASMXService.TodoItem[]> (
todoService.BeginGetTodoItems,
todoService.EndGetTodoItems,
null,
TaskCreationOptions.None);
...
}

Task Parallel Library (TPL ) puede simplificar el proceso de consumo de un par de métodos begin/end APM al
encapsular las operaciones asincrónicas en la misma Task objeto. Esta encapsulación proporciona varias
sobrecargas de los Task.Factory.FromAsync método. Este método crea un Task que ejecuta el
TodoService.EndGetTodoItems método una vez que TodoService.BeginGetTodoItems se completa el método, con
null el parámetro que indica que no se pasa BeginGetTodoItems ningún dato al delegado. Por último, el valor de la
TaskCreationOptions enumeración especifica que debe usarse el comportamiento predeterminado para la creación
y ejecución de tareas.
Para obtener más información acerca de APM, vea modelo de programación asincrónica y TPL y la programación
asincrónica .NET Framework tradicional en MSDN.
Para obtener más información sobre cómo consumir un servicio ASMX, consulte consumo de un servicio Web
ASP.net (asmx).

Windows Communication Foundation (WCF)


WCF es el marco unificado de Microsoft para la creación de aplicaciones orientadas a servicios. Permite a los
desarrolladores crear aplicaciones distribuidas seguras, confiables, transacciones e interoperables.
WCF describe un servicio con una variedad de contratos diferentes que se incluyen los siguientes:
Los contratos de datos : definir las estructuras de datos que forman la base para el contenido dentro de un
mensaje.
Contratos de mensaje – redactar mensajes de los contratos de datos existente.
Contratos de error : permitir que los errores de SOAP personalizados que se especifique.
Contratos de servicio : especificar las operaciones que admiten servicios y los mensajes necesarios para
interactuar con cada operación. También especifique ningún comportamiento de error personalizado que se
puede asociar con las operaciones en cada servicio.
Existen diferencias entre los servicios Web de ASP.NET (ASMX) y WCF, pero es importante comprender que WCF
admite las mismas funcionalidades que proporciona ASMX: los mensajes SOAP a través de HTTP.
IMPORTANT
La compatibilidad con la plataforma de Xamarin para WCF se limita a los mensajes SOAP con codificación de texto a través de
BasicHttpBinding http/https mediante la clase. Además, compatibilidad con WCF requiere el uso de herramientas solo está
disponibles en un entorno de Windows para generar al proxy.

Generación de un proxy
Un proxy debe generarse para consumir un servicio WCF, que permite que la aplicación para conectarse al
servicio. El proxy se construye por consumir los metadatos del servicio que definen los métodos y la configuración
del servicio asociado. Estos metadatos se muestran en forma de un documento de lenguaje de descripción de
servicios Web (WSDL ) que se genera el servicio web. El proxy se puede compilar mediante el Microsoft WCF Web
Service Reference Provider en Visual Studio 2017 para agregar una referencia de servicio para el servicio Web a
una biblioteca de .NET Standard.
Una alternativa para crear al proxy con el Microsoft WCF Web Service Reference Provider en Visual Studio 2017
consiste en utilizar ServiceModel Metadata Utility Tool (svcutil.exe). Para obtener más información, consulte
ServiceModel Metadata Utility Tool (Svcutil.exe).
Configuración del proxy
La configuración del proxy generado suele tomar dos argumentos de configuración (según SOAP 1.1/asmx o
WCF ) durante la inicialización: EndpointAddress el y/o la información de enlace asociada, como se muestra en el
ejemplo siguiente:

var binding = new BasicHttpBinding () {


Name= "basicHttpBinding",
MaxReceivedMessageSize = 67108864,
};

binding.ReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas() {


MaxArrayLength = 2147483646,
MaxStringContentLength = 5242880,
};

var timeout = new TimeSpan(0,1,0);


binding.SendTimeout= timeout;
binding.OpenTimeout = timeout;
binding.ReceiveTimeout = timeout;

client = new Service1Client (binding, new EndpointAddress ("http://192.168.1.100/Service1.svc"));

Un enlace se utiliza para especificar el transporte, codificación y detalles protocolares requeridos para que las
aplicaciones y servicios para comunicarse entre sí. El BasicHttpBinding especifica que se enviarán los mensajes
codificados en texto SOAP a través del protocolo de transporte HTTP. Especificación de una dirección de punto de
conexión permite a la aplicación para conectarse a distintas instancias del servicio WCF, siempre que hay varias
instancias publicadas.
Consumir el proxy
Las clases de proxy generadas proporcionan métodos para consumir los servicios web que usan el patrón de
diseño del modelo de programación asincrónica (APM ). En este patrón, una operación asincrónica se implementa
como dos métodos denominados BeginOperationName y EndOperationName, que comienzan y terminan la
operación asincrónica.
El BeginOperationName método comienza la operación asincrónica y devuelve un objeto que implementa el
IAsyncResult interfaz. Después de llamar a BeginOperationName, una aplicación puede seguir ejecutando
instrucciones en el subproceso de llamada mientras lleva a la operación asincrónica en un subproceso ThreadPool.
Para cada llamada a BeginOperationName, también debe llamar la aplicación EndOperationName para obtener
los resultados de la operación. El valor devuelto de EndOperationName es el mismo tipo devuelto por el método
de servicio web sincrónico. El ejemplo de código siguiente muestra un ejemplo:

public async Task<List<TodoItem>> RefreshDataAsync ()


{
...
var todoItems = await Task.Factory.FromAsync <ObservableCollection<TodoWCFService.TodoItem>> (
todoService.BeginGetTodoItems,
todoService.EndGetTodoItems,
null,
TaskCreationOptions.None);
...
}

Task Parallel Library (TPL ) puede simplificar el proceso de consumo de un par de métodos begin/end APM al
encapsular las operaciones asincrónicas en la misma Task objeto. Esta encapsulación proporciona varias
sobrecargas de los Task.Factory.FromAsync método. Este método crea un Task que ejecuta el
TodoServiceClient.EndGetTodoItems método una vez que TodoServiceClient.BeginGetTodoItems se completa el
método, con null el parámetro que indica que no se pasa BeginGetTodoItems ningún dato al delegado. Por último,
el valor de la TaskCreationOptions enumeración especifica que debe usarse el comportamiento predeterminado
para la creación y ejecución de tareas.
Para obtener más información acerca de APM, vea modelo de programación asincrónica y TPL y la programación
asincrónica .NET Framework tradicional en MSDN.
Para obtener más información acerca de cómo consumir un servicio WCF, consulte consumo de un servicio Web
de Windows Communication Foundation (WCF ).
Usar la seguridad de transporte
Los servicios WCF pueden emplear la seguridad de nivel de transporte para protegerse frente a la interceptación
de mensajes. La plataforma Xamarin admite enlaces que emplean la seguridad de nivel de transporte mediante
SSL. Sin embargo, puede haber casos en los que la pila tenga que validar el certificado, lo que provoca un
comportamiento imprevisto. La validación se puede invalidar registrando un ServerCertificateValidationCallback
delegado antes de invocar el servicio, como se muestra en el ejemplo de código siguiente:

System.Net.ServicePointManager.ServerCertificateValidationCallback +=
(se, cert, chain, sslerror) => { return true; };

Esto mantiene el cifrado de transporte y omite la validación de certificados del servidor. Sin embargo, este enfoque
no tiene en cuenta los problemas de confianza asociados con el certificado y puede no ser adecuado. Para obtener
más información, consulte uso de raíces de confianza de forma respetuosa en Mono-Project.com.
Uso de la seguridad de credenciales de cliente
Los servicios WCF también pueden requerir que los clientes del servicio se autentiquen con las credenciales. La
plataforma Xamarin no admite el protocolo WS -Security, que permite a los clientes enviar credenciales dentro del
sobre del mensaje SOAP. Sin embargo, la plataforma de Xamarin admite la posibilidad de enviar credenciales de
autenticación HTTP Basic al servidor especificando lo ClientCredentialType adecuado:

basicHttpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;

A continuación, se pueden especificar las credenciales de autenticación básica:


client.ClientCredentials.UserName.UserName = @"foo";
client.ClientCredentials.UserName.Password = @"mrsnuggles";

En el ejemplo anterior, si recibe el mensaje "se ha quedado sin trampolines de tipo 0", puede aumentar el número
de tipo 0 trampolines agregando el –aot “trampolines={number of trampolines}” argumento a la compilación. Para
más información, consulte Solución de problemas.
Para obtener más información acerca de la autenticación HTTP Basic, aunque en el contexto de un servicio Web
REST, consulte autenticación de un servicio web RESTful.

Vínculos relacionados
Servicios web en Xamarin. Forms
Herramienta de utilidad de metadatos de ServiceModel (SvcUtil. exe)
BasicHttpBinding
Implementación y prueba
18/07/2019 • 4 minutes to read • Edit Online

En esta sección se incluyen guías en las que se explica cómo probar una aplicación, optimizar su rendimiento,
prepararla para el lanzamiento, firmarla con un certificado y publicarla en una tienda de aplicaciones.

Tamaños de paquete de aplicación


En este artículo se examinan los elementos que componen un paquete de aplicación Xamarin.Android y las
estrategias asociadas que se pueden utilizar para la implementación eficaz del paquete durante las etapas de
depuración y lanzamiento del desarrollo.

Compilar aplicaciones
En esta sección se describe cómo funciona el proceso de compilación y se explica cómo compilar paquetes de
aplicaciones Android (APK) específicos de ABI.

Emulador de la línea de comandos


En este artículo se trata brevemente el inicio del emulador mediante la línea de comandos.

Depuración
Las guías de la sección ayudan a depurar la aplicación mediante emuladores de Android, dispositivos Android
reales y el registro de depuración.

Establecer el atributo Debuggable


En este artículo se explica cómo establecer el atributo debuggable para que herramientas como adb puedan
comunicarse con la JVM.

Entorno
En este artículo se describe el entorno de ejecución de Xamarin.Android y las propiedades del sistema Android que
influyen en la ejecución del programa.

GDB
En este artículo se explica cómo usar gdb para depurar una aplicación Xamarin.Android.

Instalar una aplicación del sistema


En esta guía se explica cómo instalar una aplicación Xamarin.Android como una aplicación del sistema en un
dispositivo Android o como parte de una ROM personalizada.

Vincular en Android
En este artículo se describe el proceso de vinculación que se usa en Xamarin.Android para reducir el tamaño final
de una aplicación. Se describen los diferentes niveles de vinculación que se pueden ejecutar y se proporcionan
algunas orientaciones y consejos de solución de problemas para mitigar los errores que podrían deberse al uso del
vinculador.

Rendimiento de Xamarin.Android
Existen muchas técnicas para aumentar el rendimiento de las aplicaciones compiladas con Xamarin.Android. En
conjunto, estas técnicas pueden reducir considerablemente la cantidad de trabajo que realiza una CPU y la cantidad
de memoria consumida por una aplicación.

Generar perfiles de aplicaciones Android


En esta guía se explica cómo usar las herramientas del generador de perfiles para examinar el rendimiento y el uso
de memoria de una aplicación Android.

Preparar una aplicación para su lanzamiento


Después de haber codificado y probado una aplicación, es necesario preparar un paquete para la distribución. La
primera tarea en la preparación de este paquete es compilar la aplicación para el lanzamiento, lo que implica
principalmente establecer algunos atributos de la aplicación.

Firmar el paquete de aplicación de Android


Obtenga información sobre cómo crear una identidad de firma de Android, crear un certificado de firma para
aplicaciones de Android y firmar la aplicación con el certificado de firma. Además, en este tema se explica cómo
exportar la aplicación a un disco para la distribución ad hoc. Se puede realizar una instalación de prueba del APK
resultante en dispositivos Android sin pasar por una tienda de aplicaciones.

Publicar una aplicación


En esta serie de artículos se explican los pasos para la distribución pública de una aplicación creada con
Xamarin.Android. La distribución puede realizarse a través de diversos canales, como el correo electrónico, un
servidor web privado, Google Play o Amazon Appstore para Android.
Tamaños de paquete de aplicación
11/07/2019 • 8 minutes to read • Edit Online

En este artículo se examinan los elementos que componen un paquete de aplicación Xamarin.Android y las
estrategias asociadas que se pueden utilizar para la implementación eficaz del paquete durante las etapas de
depuración y lanzamiento de la versión.

Información general
Xamarin.Android usa diversos mecanismos para minimizar el tamaño de paquete y mantener un proceso eficiente
de depuración e implementación de versiones. En este artículo, se examina el flujo de trabajo de implementación
de depuración y lanzamiento de Xamarin.Android y cómo la plataforma Xamarin.Android garantiza que se
compilan y lanzan pequeños paquetes de aplicación.

Paquetes de versión
Para distribuir una aplicación totalmente contenida, el paquete debe incluir la aplicación, las bibliotecas asociadas,
el contenido, el entorno de ejecución Mono y los ensamblados de biblioteca de clases base (BCL ) necesarios. Por
ejemplo, si tomamos la plantilla predeterminada "Hola, mundo", el contenido de una compilación de paquete
completa sería similar al siguiente:

15,8 MB es un tamaño de descarga que nos gustaría. El problema son las bibliotecas BCL, dado que incluyen
mscorlib, System y Mono.Android, que proporcionan muchos de los componentes necesarios para ejecutar la
aplicación. Sin embargo, también proporcionan una funcionalidad que puede que no use en la aplicación, por lo
que puede ser preferible excluir estos componentes.
Cuando se compila una aplicación para su distribución, se ejecuta un proceso, conocido como vinculación, que
examina la aplicación y quita cualquier código que no se use directamente. Este proceso es similar a la
funcionalidad que proporciona la recolección de elementos no utilizados para la memoria asignada por el montón.
Pero, en lugar de trabajar sobre objetos, la vinculación trabaja sobre el código. Por ejemplo, hay un espacio de
nombres completo en System.dll para enviar y recibir correo electrónico, pero si la aplicación no hace uso de esta
funcionalidad, lo que hace simplemente se código es desperdiciar espacio. Después de ejecutar el enlazador en la
aplicación Hola, mundo, nuestro paquete se parece ahora a este:

Como se puede observar, se quita una cantidad considerable de la BCL que no se usaba. Tenga en cuenta que el
tamaño final de la BCL depende de lo que la aplicación use realmente. Por ejemplo, si echamos un vistazo a una
aplicación de ejemplo más significativa llamada ApiDemo, podemos ver que el componente BCL ha aumentado de
tamaño porque ApiDemo usa más cantidad de la BCL que Hola, mundo:
Como se ilustra aquí, el tamaño del paquete de aplicación suele ser 2,9 MB más grande que la aplicación y sus
dependencias.

Depuración de paquetes
En las compilaciones de depuración, las cosas se tratan de forma ligeramente diferente. Cuando se realizan las
mismas implementaciones una y otra vez en un dispositivo, una aplicación tiene que ser lo más rápida posible, de
modo que se optimizan los paquetes de depuración en favor de la velocidad de implementación en lugar del
tamaño.
Android es relativamente lento en copiar e instalar un paquete, así que queremos que el tamaño del paquete sea lo
más pequeño posible. Como se explicó anteriormente, una de las formas posibles de minimizar el tamaño de
paquete es mediante el enlazador. Sin embargo, la vinculación es lenta y lo habitual es que queramos implementar
solo partes de la aplicación que hayan cambiado desde la última implementación. Para lograr esto, separamos
nuestra aplicación de los componentes principales del Xamarin.Android.
La primera vez que realizamos la depuración en el dispositivo, copiamos dos paquetes grandes llamados Tiempo
de ejecución compartido y Plataforma compartida. El tiempo de ejecución compartido contiene el entorno de
ejecución de Mono y BCL, mientras que la plataforma compartida contiene ensamblados específicos de nivel de
API de Android:

La copia de estos componentes principales solo se hace una vez, ya que tarda bastante tiempo, pero permite que
las sucesivas aplicaciones que se ejecutan en modo de depuración los utilicen. Por último, copiamos la aplicación
real, que es pequeña y rápida:

Implementación rápida de ensamblados


La opción de compilación Implementación rápida de ensamblados se puede usar para reducir aún más el tamaño
del paquete de instalación de depuración al no incluir los ensamblados en el paquete de la aplicación, instalarlos
directamente en el dispositivo una sola vez y copiarlos únicamente sobre los archivos que se han modificado desde
la última implementación.
Para habilitar Implementación rápida de ensamblados, siga estos pasos:
1. Haga clic con el botón derecho en el proyecto de Android en el Explorador de soluciones y seleccione
Opciones.
2. En el cuadro de diálogo Opciones del proyecto, seleccione Compilación de Android:
3. Active las casillas Usar el entorno de ejecución Mono compartido e Implementación rápida de
ensamblados:

4. Haga clic en el botón Aceptar para guardar los cambios y cerrar el cuadro de diálogo Opciones del
proyecto.
La próxima vez que la aplicación se compile para la depuración, los ensamblados se instalarán directamente en el
dispositivo (si aún no lo están) y un paquete de aplicación más pequeño (que no incluye los ensamblados) también
se instalará en el dispositivo. Con ello se acorta el tiempo necesario para conseguir que los cambios en la
aplicación se pongan en funcionamiento para la realización de pruebas.
Al soportar la primera implementación larga del entorno de tiempo de ejecución compartido y de la plataforma
compartida, cada vez que realizamos cambios en la aplicación, podemos implementar la nueva versión
rápidamente y sin problemas, de modo que conseguimos un ciclo de cambio, implementación y ejecución rápido.

Resumen
En este artículo, examinamos las facetas del empaquetado de perfiles de depuración y lanzamiento de
Xamarin.Android. Además, analizamos las estrategias que usa la plataforma Mono para Android para facilitar la
implementación eficiente de paquetes durante las fases de desarrollo de depuración y lanzamiento.
Compilar aplicaciones
18/07/2019 • 2 minutes to read • Edit Online

En esta sección se describe cómo funciona el proceso de compilación y se explica cómo compilar paquetes de
aplicaciones Android (APK) específicos de ABI.

Proceso de compilación
En este tema se explican los pasos y los procesos que intervienen en el código fuente, los recursos y los activos de
una aplicación Xamarin.Android y se genera un APK que se puede instalar en dispositivos Android.

Compilar APK específicos de ABI


En esta guía se describe cómo crear APK de Android que admiten una arquitectura de una única CPU y ABI.
Proceso de compilación
19/08/2019 • 63 minutes to read • Edit Online

Información general
El proceso de compilación de Xamarin.Android es responsable de pegarlo todo junto y generar
Resource.designer.cs , admitir AndroidAsset , AndroidResource y otras acciones de compilación, generar
contenedores Android invocables y generar un archivo .apk para su ejecución en dispositivos Android.

Paquetes de aplicación
En términos generales, hay dos tipos de paquetes de aplicación de Android (archivos .apk ) que puede generar
el sistema de compilación de Xamarin.Android:
Compilaciones de versión, que son totalmente autocontenidas y no requieren la ejecución de paquetes
adicionales. Estos son los paquetes que se proporcionarían a una tienda de aplicaciones.
Compilaciones de depuración, los que no.
No es por casualidad que estos correspondan al elemento de MSBuild Configuration que genera el paquete.
Entorno de tiempo de ejecución compartido
El entorno de tiempo de ejecución compartido es un par de paquetes de Android adicionales que proporcionan
la biblioteca de clases base ( mscorlib.dll , etc.) y la biblioteca de enlaces de Android ( Mono.Android.dll , etc.).
Las compilaciones de depuración dependen del entorno de tiempo de ejecución compartido en lugar de incluir
los ensamblados de enlace y de biblioteca de clases base en el paquete de aplicaciones Android, lo que permite
que el paquete de depuración sea más pequeño.
El entorno de tiempo de ejecución compartido se puede deshabilitar en las compilaciones de depuración si se
establece la propiedad $(AndroidUseSharedRuntime) en False .
Implementación rápida
La implementación rápida funciona junto con el entorno de tiempo de ejecución compartido para reducir
incluso más el tamaño del paquete de aplicaciones Android. Para lograr esto, los ensamblados de la aplicación
no se incluyen dentro del paquete. En su lugar, se copian en el destino mediante adb push . Este proceso acelera
el ciclo de compilación, implementación y depuración dado que solo cambian los ensamblados; el paquete no se
vuelve a instalar. Solo los ensamblados actualizados se vuelven a sincronizar con el dispositivo de destino.
Se sabe que la implementación rápida genera errores en los dispositivos que impiden que adb se sincronicen
con el directorio /data/data/@PACKAGE_NAME@/files/.__override__ .
La implementación rápida está habilitada de forma predeterminada y puede deshabilitarse en las compilaciones
de depuración si se establece la propiedad $(EmbedAssembliesIntoApk) en True .

Proyectos de MSBuild
El proceso de compilación de Xamarin.Android se basa en MSBuild, que también es el formato de archivo de
proyecto usado por Visual Studio para Mac y Visual Studio. Normalmente, no es necesario que los usuarios
editen manualmente los archivos de MSBuild, dado que el IDE crea proyectos totalmente funcionales, los
actualiza con los cambios realizados e invoca destinos de compilación según sea necesario.
Puede que los usuarios avanzados quieran realizar operaciones que no se admiten en la interfaz gráfica de
usuario del IDE, así que el proceso de compilación se puede personalizar mediante la edición directa del archivo
de proyecto. En esta página solo se documentan las características y personalizaciones específicas de
Xamarin.Android; se pueden realizar muchas más cosas con los elementos, las propiedades y los destinos
normales de MSBuild.

Compilar destinos
Los siguientes destinos de compilación se definen para proyectos de Xamarin.Android:
Build: compila el paquete.
Clean: elimina todos los archivos generados por el proceso de compilación.
Install: instala el paquete en el dispositivo predeterminado o el dispositivo virtual.
Uninstall: desinstala el paquete del dispositivo predeterminado o el dispositivo virtual.
SignAndroidPackage: crea y firma el paquete ( .apk ). Úselo con /p:Configuration=Release para
generar paquetes de comerciales.
UpdateAndroidResources: actualiza el archivo Resource.designer.cs . El IDE llama normalmente a este
destino cuando se agregan nuevos recursos al proyecto.

Puntos de extensión de compilación


El sistema de compilación de Xamarin.Android expone algunos puntos de extensión públicos para los usuarios
que quieran usar nuestro proceso de compilación. Para usar uno de estos puntos de extensión, deberá agregar
su destino personalizado a la propiedad de MSBuild correspondiente en un PropertyGroup . Por ejemplo:

<PropertyGroup>
<AfterGenerateAndroidManifest>
$(AfterGenerateAndroidManifest);
YourTarget;
</AfterGenerateAndroidManifest>
</PropertyGroup>

Tenga en cuenta esta recomendación sobre la extensión del proceso de compilación: Si no se escriben
correctamente, las extensiones de compilación pueden afectar al rendimiento de la compilación, especialmente si
se ejecutan en cada compilación. Es muy recomendable que lea la documentación de MSBuild antes de
implementar estas extensiones.
AfterGenerateAndroidManifest: los destinos enumerados en esta propiedad se ejecutarán
directamente después del destino de _GenerateJavaStubs interno. Aquí es donde se genera el archivo
AndroidManifest.xml en el $(IntermediateOutputPath) . Por lo tanto, si quiere realizar modificaciones en el
archivo AndroidManifest.xml generado, puede hacerlo mediante este punto de extensión.
Se ha agregado en Xamarin.Android 9.4.
BeforeGenerateAndroidManifest: los destinos enumerados en esta propiedad se ejecutarán
directamente antes de _GenerateJavaStubs .
Se ha agregado en Xamarin.Android 9.4.

Propiedades de compilación
Las propiedades de MSBuild controlan el comportamiento de los destinos. Se especifican en el archivo de
proyecto, por ejemplo, MyApp.csproj, dentro de un elemento MSBuild PropertyGroup.
Configuration: especifica la configuración de compilación que se usará, como "Debug" o "Release". La
propiedad Configuration se usa para determinar los valores predeterminados de otras propiedades que
determinan el comportamiento de destino. Se pueden crear configuraciones adicionales dentro del IDE.
De forma predeterminada, la configuración Debug dará lugar a los destinos Install y
SignAndroidPackage que crean un paquete de Android más pequeño que, para funcionar, requiere la
presencia de otros archivos y paquetes.
La configuración Release predeterminada dará lugar a los destinos Install y SignAndroidPackage que
crean un paquete de Android que es independiente, y se puede usar sin instalar ningún otro paquete o
archivo.
DebugSymbols: un valor booleano que determina si el paquete de Android es depurable (tiene el
atributo debuggable), en combinación con la propiedad $(DebugType) . Un paquete depurable contiene
símbolos de depuración, establece el atributo //application/@android:debuggable en true y agrega
automáticamente el permiso INTERNET para que el depurador pueda asociarlo al proceso. Una aplicación
es depurable si DebugSymbols es True y DebugType es la cadena vacía o Full .
DebugType: especifica el tipo de símbolos de depuración para generar como parte de la compilación,
que también afecta a si la aplicación es depurable. Entre los posibles valores se incluyen:
Full: se generan símbolos completos. Si la propiedad de MSBuild DebugSymbols es también True ,
entonces el paquete de aplicación es depurable.
PdbOnly: se generan símbolos "PDB". El paquete de aplicación no será depurable.
Si DebugType no está establecido o es la cadena vacía, la propiedad DebugSymbols controla si la aplicación
es o no depurable.
AndroidGenerateLayoutBindings: permite la generación de diseño de código subyacente si se
establece en true o lo deshabilita por completo si se establece en false . El valor predeterminado es
false .

Propiedades de instalación
Las propiedades de instalación controlan el comportamiento de los destinos Install y Uninstall .
AdbTarget: especifica el dispositivo de destino de Android en el que se puede instalar o del que se puede
quitar el paquete Android. El valor de esta propiedad es el mismo que el de la opción del dispositivo de
destino adb :

# Install package onto emulator via -e


# Use `/Library/Frameworks/Mono.framework/Commands/msbuild` on OS X
MSBuild /t:Install ProjectName.csproj /p:AdbTarget=-e

Propiedades de empaquetado
Las propiedades de empaquetado controlan la creación del paquete de Android y se usan con los destinos
Install y SignAndroidPackage . Las propiedades de firma también son importantes al empaquetar aplicaciones
de versión.
AndroidApkDigestAlgorithm: un valor de cadena que especifica el algoritmo de síntesis del mensaje
que se usará con jarsigner -digestalg .
El valor predeterminado es SHA1 para los APK y SHA-256 para los paquetes de aplicaciones.
Se ha agregado en Xamarin.Android 9.4.
AndroidApkSignerAdditionalArguments – Una propiedad de cadena que permite al desarrollador
proporcionar argumentos adicionales a la herramienta apksigner .
Agregado en Xamarin.Android 8.2.
AndroidApkSigningAlgorithm – Un valor de cadena que especifica el algoritmo de firma para
utilizarlo con jarsigner -sigalg .
El valor predeterminado es md5withRSA para los APK y SHA256withRSA para los paquetes de aplicaciones.
Agregado en Xamarin.Android 8.2.
AndroidApplication: un valor booleano que indica si el proyecto es para una aplicación Android ( True )
o para un proyecto de la biblioteca de Android ( False o no existe).
Solo puede existir un proyecto con <AndroidApplication>True</AndroidApplication> en un paquete de
Android. (Por desgracia, esto no se ha comprobado aún, lo que puede dar lugar a errores sutiles y
extraños respecto a los recursos de Android).
AndroidApplicationJavaClass – el nombre completo de clase de Java para usar en lugar de
android.app.Application cuando una clase hereda de Android.App.Application.

Esta propiedad se establece generalmente mediante otras propiedades, como la propiedad de MSBuild
$(AndroidEnableMultiDex) .

Agregado en Xamarin.Android 6.1.


AndroidBuildApplicationPackage: un valor booleano que indica si crear y firmar el paquete (.apk).
Establecer este valor en True es equivalente a usar el destino de compilación SignAndroidPackage.
Después de Xamarin.Android 7.1, se agregó compatibilidad con esta propiedad.
De forma predeterminada, esta propiedad es False .
AndroidDexTool: propiedad de estilo de la enumeración con los valores válidos de dx o d8 . Indica el
compilador de dex que se usa durante el proceso de compilación de Xamarin.Android. Actualmente tiene
como valor predeterminado dx . Para obtener más información, vea la documentación sobre D8 y R8.
AndroidEnableDesugar: propiedad booleana que determina si desugar está habilitado. Android no
admite actualmente todas las características de Java 8 y la cadena de herramientas predeterminada
implementa las nuevas características de lenguaje ejecutando transformaciones de código de bytes,
llamadas desugar , en la salida del compilador javac . El valor predeterminado es False si se usa
AndroidDexTool=dx y True si se usa AndroidDexTool=d8 .

AndroidEnableGooglePlayStoreChecks: una propiedad booleana que permite a los desarrolladores


deshabilitar las siguientes comprobaciones de Google Play Store: XA1004, XA1005 y XA1006. Esto
resulta útil para los desarrolladores que no tienen como destino Google Play Store y que no quieren
ejecutar las comprobaciones mencionadas.
Se ha agregado en Xamarin.Android 9.4.
AndroidEnableMultiDex: una propiedad booleana que determina si se usará la compatibilidad con
Multi-Dex en el archivo .apk final.
En Xamarin.Android 5.1, se agregó compatibilidad con esta propiedad.
De forma predeterminada, esta propiedad es False .
AndroidEnablePreloadAssemblies – Una propiedad booleana que controla si todos los ensamblados
administrados que se incluyen en el paquete de aplicación se cargan o no durante el inicio del proceso.
Cuando se establece en True , todos los ensamblados que se incluyen en el paquete de aplicación se
cargan durante el inicio del proceso, antes de que se invoque cualquier código de aplicación. Esta acción
es coherente con lo que hacía Xamarin.Android en las versiones anteriores a Xamarin.Android 9.2.
Cuando se establece en False , los ensamblados solo se cargan cuando es necesario. De esta forna, las
aplicaciones se inician más rápido y también hay una mayor coherencia con la semántica de .NET de
escritorio. Para ver los ahorros de tiempo, establezca la propiedad del sistema debug.mono.log en timing
y busque el mensaje Finished loading assemblies: preloaded en adb logcat .
Puede que las aplicaciones o bibliotecas que usan inserción de dependencias necesiten que esta
propiedad se establezca en True si estas requieren a su vez que
AppDomain.CurrentDomain.GetAssemblies() devuelva todos los ensamblados del conjunto de aplicación,
incluso si el ensamblado no hubiera sido necesario.
De forma predeterminada, este valor se establecerá en True .
Se ha agregado en Xamarin.Android 9.2.
AndroidEnableProfiledAot: una propiedad booleana que determina si los perfiles de AOT se usarán
durante la compilación Ahead-of-Time.
Los perfiles se muestran en el grupo de elementos AndroidAotProfile . Este ItemGroup contiene perfiles
predeterminados. Se puede reemplazar quitando los perfiles de AOT existentes y agregando los suyos.
La compatibilidad con esta propiedad se ha agregado en Xamarin.Android 9.4.
De forma predeterminada, esta propiedad es False .
AndroidEnableSGenConcurrent: una propiedad booleana que determina si se usará el recolector de
elementos no utilizados simultáneo.
Se agregó compatibilidad con esta propiedad en Xamarin.Android 7.2.
De forma predeterminada, esta propiedad es False .
AndroidErrorOnCustomJavaObject – Una propiedad booleana que determina si los tipos pueden
implementar Android.Runtime.IJavaObject sin heredando también de Java.Lang.Object o
Java.Lang.Throwable :

class BadType : IJavaObject {


public IntPtr Handle {
get {return IntPtr.Zero;}
}

public void Dispose()


{
}
}

Cuando es True, estos tipos generarán un error de XA4212, en caso contrario, una advertencia XA4212.
En Xamarin.Android 8.1, se agregó compatibilidad con esta propiedad.
De forma predeterminada, esta propiedad es True .
AndroidFastDeploymentType: lista de valores separada por : (dos puntos) para controlar qué tipos
se pueden implementar en el directorio de implementación rápida del dispositivo de destino cuando la
propiedad de MSBuild $(EmbedAssembliesIntoApk) es False . Si un recurso se implementa rápido, no se
inserta en el archivo .apk generado, lo que puede acelerar los tiempos de desarrollo. (Cuanto más
rápido se implementa, con menos frecuencia es necesario recompilar el archivo .apk , y el proceso de
instalación puede ser más rápido). Los valores válidos son:
Assemblies : implementa los ensamblados de aplicación.
: implementa archivos .dex , recursos de Android y activos de Android. Este valor solo se
Dexes
puede usar en dispositivos que ejecutan Android 4.4 o posterior (API -19).
El valor predeterminado es Assemblies .
Experimental. Agregado en Xamarin.Android 6.1.
AndroidGenerateJniMarshalMethods: se trata de una propiedad bool que permite la generación de
métodos de serialización JNI como parte del proceso de compilación. Reduce en gran medida el uso de
System.Reflection en el código de aplicación auxiliar de enlace.
De forma predeterminada, se establecerá en False. Si los desarrolladores quieren usar la nueva
característica de métodos de serialización JNI, pueden establecer

<AndroidGenerateJniMarshalMethods>True</AndroidGenerateJniMarshalMethods>

en su csproj. Especifique también la propiedad en la línea de comandos mediante

/p:AndroidGenerateJniMarshalMethods=True

Experimental. Se ha agregado en Xamarin.Android 9.2. El valor predeterminado es False.


AndroidGenerateJniMarshalMethodsAdditionalArguments: propiedad de cadena que se puede
usar para agregar parámetros adicionales a la invocación de jnimarshalmethod-gen.exe . Resulta útil para la
depuración, por lo que se pueden usar opciones tales como -v , -d o --keeptemp .
El valor predeterminado es una cadena vacía. Se puede establecer en el archivo csproj o en la línea de
comandos. Por ejemplo:

<AndroidGenerateJniMarshalMethodsAdditionalArguments>-v -d --
keeptemp</AndroidGenerateJniMarshalMethodsAdditionalArguments>

O bien

/p:AndroidGenerateJniMarshalMethodsAdditionalArguments="-v -d --keeptemp"

Se ha agregado en Xamarin.Android 9.2.


AndroidHttpClientHandlerType – Controla la implementación de System.Net.Http.HttpMessageHandler
predeterminada que se va a utilizar mediante el constructor predeterminado System.Net.Http.HttpClient .
El valor es un nombre calificado con el ensamblado de una subclase HttpMessageHandler , adecuada para
usarse con System.Type.GetType(string) . Los valores más comunes para esta propiedad son los
siguientes:
Xamarin.Android.Net.AndroidClientHandler : Use las API de Java de Android para realizar solicitudes
de red. Esto permite tener acceso a las direcciones URL TLS 1.2, cuando la versión de Android
subyacente admita dicho protocolo. Solo Android 5.0 y versiones posteriores proporcionan
compatibilidad confiable con TLS 1.2 a través de Java.
Esto corresponde a la opción Android de las páginas de propiedades de Visual Studio y la opción
AndroidClientHandler de las páginas de propiedades de Visual Studio para Mac.
El asistente para la creación de proyectos selecciona esta opción para los nuevos proyectos cuando
la versión de Android mínima está configurada en Android 5.0 (Lollipop) o versiones
posteriores en Visual Studio, o bien cuando Target Platforms está establecido en Latest and
Greatest en Visual Studio para Mac.
Anular la cadena vacía: Esto equivale a System.Net.Http.HttpClientHandler, System.Net.Http .
Esto corresponde a la opción Default de las páginas de propiedades de Visual Studio.
El asistente para la creación de proyectos selecciona esta opción para los nuevos proyectos cuando
la versión de Android mínima está configurada en Android 4.4.87 o versiones anteriores en
Visual Studio, o bien cuando Target Platforms está establecido en Modern Development o
Maximum Compatibility en Visual Studio para Mac.
System.Net.Http.HttpClientHandler, System.Net.Http : Use el HttpMessageHandler administrado.
Esto corresponde a la opción Managed de las páginas de propiedades de Visual Studio.
Nota: Si la compatibilidad con TLS 1.2 es necesaria en las versiones de Android anteriores a la 5.0, o si se
requiere con System.Net.WebClient y las API relacionadas, se debe usar $(AndroidTlsProvider) .
Nota: La compatibilidad con esta propiedad funciona estableciendo la variable de entorno
XA_HTTP_CLIENT_HANDLER_TYPE . Tendrá prioridad un valor $XA_HTTP_CLIENT_HANDLER_TYPE en un archivo con
una acción de compilación de @(AndroidEnvironment) .
Agregado en Xamarin.Android 6.1.
AndroidLinkMode: especifica qué tipo de vinculación debe realizarse en los ensamblados contenidos
dentro del paquete de Android. Solo se usa en proyectos de aplicación de Android. El valor
predeterminado es SdkOnly. Los valores válidos son:
None: no se intenta la vinculación.
SdkOnly: la vinculación se realizará solo en las bibliotecas de clase base, no en los ensamblados
del usuario.
Full: la vinculación se realizará en las bibliotecas de clase base y en los ensamblados del usuario.

NOTE
El uso de un valor para AndroidLinkMode de Full da lugar con frecuencia a aplicaciones interrumpidas, en
especial cuando se usa la reflexión. Evítelo a menos que sepa realmente lo que está haciendo.

<AndroidLinkMode>SdkOnly</AndroidLinkMode>

AndroidLinkSkip: especifica una lista delimitada por punto y coma ( ; ) de nombres de ensamblado, sin
extensiones de archivos, que no se deben vincular. Solo se usa dentro de proyectos de aplicaciones
Android.

<AndroidLinkSkip>Assembly1;Assembly2</AndroidLinkSkip>

AndroidLinkTool: propiedad de estilo de la enumeración con los valores válidos de proguard o r8 .


Indica el reductor de código que se usa con el código Java. Actualmente el valor predeterminado es una
cadena vacía o proguard si $(AndroidEnableProguard) es True . Para obtener más información, vea la
documentación sobre D8 y R8.
AndroidLintEnabled: propiedad booleana que permite que el desarrollador ejecute la herramienta
lint de Android como parte del proceso de empaquetado.

AndroidLintEnabledIssues: lista separada por comas de problemas de Lint que se va a habilitar.


AndroidLintEnabledIssues: lista separada por comas de problemas de Lint que se va a
deshabilitar.
AndroidLintCheckIssues: lista separada por comas de problemas de Lint que hay que
comprobar. Nota: Solo se comprobarán estos problemas.
AndroidLintConfig: se trata de una acción de compilación para un archivo de configuración de
tipo lint. Puede usarse para habilitar o deshabilitar la comprobación de problemas. Varios archivos
pueden usar esta acción de compilación ya que su contenido se va a combinar.
Consulte la Ayuda de Lint para más información sobre las herramientas lint de Android.
AndroidManagedSymbols: una propiedad booleana que controla si se generan puntos de secuencia
para que la información de nombre de archivo y número de línea se pueda extraer de los seguimientos de
pila de Release .
Agregado en Xamarin.Android 6.1.
AndroidManifest: especifica un nombre de archivo para usar como plantilla para el archivo
AndroidManifest.xml de la aplicación . Durante la compilación, cualquier otro valor necesario se combina
para producir el archivo AndroidManifest.xml real. $(AndroidManifest) debe contener el nombre de
paquete en el atributo /manifest/@package .
AndroidMultiDexClassListExtraArgs: propiedad de cadena que permite a los desarrolladores pasar
argumentos adicionales a com.android.multidex.MainDexListBuilder al generar el archivo multidex.keep .
Un caso específico es si se obtiene el siguiente error durante la compilación de dx .

com.android.dex.DexException: Too many classes in --main-dex-list, main dex capacity exceeded

Si recibe este error, puede agregar lo siguiente al elemento .csproj.

<DxExtraArguments>--force-jumbo </DxExtraArguments>
<AndroidMultiDexClassListExtraArgs>--disable-annotation-resolution-
workaround</AndroidMultiDexClassListExtraArgs>

Esto debe permitir que el paso dx se realice correctamente.


Se ha agregado en Xamarin.Android 8.3.
AndroidPackageFormat: una propiedad de estilo de la enumeración con los valores válidos de apk o
aab . Esto indica si quiere empaquetar la aplicación Android como un archivo APK o un paquete de
aplicaciones Android. Los grupos de aplicaciones son un nuevo formato para las compilaciones de
Release que se quieran enviar a Google Play. Actualmente, este valor es apk de forma predeterminada.

Cuando $(AndroidPackageFormat) se establece en aab , se establecen otras propiedades de MSBuild


necesarias para los paquetes de aplicaciones de Android:
$(AndroidUseAapt2) es True .
$(AndroidUseApkSigner) es False .
$(AndroidCreatePackagePerAbi) es False .

AndroidD8JarPath: ruta de acceso a r8.jar para su uso con el compilador y reductor de dex de d8. El
valor predeterminado es una ruta de acceso en la instalación de Xamarin.Android. Para obtener más
información, vea la documentación sobre D8 y R8.
AndroidSdkBuildToolsVersion: el paquete de compilación de herramientas de Android SDK
proporciona, entre otras, las herramientas aapt y zipalign. Se pueden instalar varias versiones diferentes
del paquete de herramientas de compilación al mismo tiempo. Para realizar el paquete de herramientas
de compilación elegido para empaquetar, se comprueba y usa una versión de herramientas de
compilación "preferida", si existe; en caso contrario, se usa el paquete de herramientas de compilación
instalado con la versión más alta.
La propiedad de MSBuild $(AndroidSdkBuildToolsVersion) contiene la versión de herramientas de
compilación preferida. El sistema de compilación de Xamarin.Android proporciona un valor
predeterminado en Xamarin.Android.Common.targets , y el valor predeterminado se puede reemplazar
dentro del archivo de proyecto para elegir una versión alternativa de las herramientas de compilación si,
por ejemplo, la herramienta aapt más reciente se bloquea mientras se sabe que una versión anterior de
aapt funciona.
AndroidSupportedAbis: una propiedad de cadena que contiene una lista delimitada por punto y coma (
; ) de ABI que se deberían incluir en el archivo .apk .

Los valores admitidos son:


armeabi-v7a
x86
arm64-v8a : requiere Xamarin.Android 5.1 y versiones posteriores.
x86_64 : requiere Xamarin.Android 5.1 y versiones posteriores.
AndroidTlsProvider: un valor de cadena que especifica qué proveedor de TLS se debe usar en una
aplicación. Los valores posibles son:
Anular la cadena vacía: En Xamarin.Android 7.3 y versiones posteriores, esto equivale a btls .
En Xamarin.Android 7.1, esto equivale a legacy .
Esto corresponde a la configuración Default de las páginas de propiedades de Visual Studio.
btls : usa Boring SSL para la comunicación TLS con HttpWebRequest.
Esto permite el uso de TLS 1.2 en todas las versiones de Android.
Esto corresponde a la configuración Native TLS 1.2+ de las páginas de propiedades de Visual
Studio.
legacy: usa la implementación de SSL administrada histórica para la interacción de red. Aquí no
se admite TLS 1.2.
Esto corresponde a la configuración Managed TLS 1.0 de las páginas de propiedades de Visual
Studio.
default: Es poco probable que este valor se use en proyectos de Xamarin.Android. El valor
recomendado que se usará en su lugar es la cadena vacía, que corresponde a la configuración
Default de las páginas de propiedades de Visual Studio.
El valor default no se ofrece en las páginas de propiedades de Visual Studio.
Actualmente, esto equivale a legacy .
Agregado en Xamarin.Android 7.1.
AndroidUseApkSigner – Una propiedad booleana que permite que el desarrollador use la herramienta
apksigner en lugar de jarsigner .

Agregado en Xamarin.Android 8.2.


AndroidUseLegacyVersionCode: una propiedad booleana permite al desarrollador revertir el cálculo
de versionCode al comportamiento anterior Xamarin.Android 8.2. SOLO debe usarse para los
desarrolladores con aplicaciones en Google Play Store. Se recomienda utilizar la nueva propiedad
$(AndroidVersionCodePattern) .

Agregado en Xamarin.Android 8.2.


AndroidUseManagedDesignTimeResourceGenerator – Una propiedad booleana que cambiará las
compilaciones en tiempo de diseño para usar el analizador de recurso administrado en lugar de aapt .
Agregado en Xamarin.Android 8.1.
AndroidUseSharedRuntime: una propiedad booleana que determina si se requieren los paquetes de
entorno de tiempo de ejecución compartido para ejecutar la aplicación en el dispositivo de destino.
Confiar en los paquetes de entorno de tiempo de ejecución compartido permite que el paquete de
aplicación sea más pequeño y acelera el proceso de creación y desarrollo del paquete, lo que da lugar a
un ciclo de respuesta de compilación, implementación y depuración más rápido.
Esta propiedad debe ser True para las compilaciones de depuración y False para los proyectos de
versión.
AndroidVersionCodePattern: una propiedad de cadena que permite al desarrollador personalizar el
elemento versionCode en el manifiesto. Consulte Crear el código de la versión para el APK para más
información sobre cómo decidir el valor de versionCode .
Algunos ejemplos: si abi es armeabi y versionCode en el manifiesto es 123 , {abi}{versionCode}
producirá un código de versión de 1123 cuando $(AndroidCreatePackagePerAbi) sea True; de lo contrario,
producirá un valor de 123. Si abi es x86_64 y versionCode en el manifiesto es 44 , se generará 544
cuando $(AndroidCreatePackagePerAbi) sea True; de lo contrario, se producirá un valor de 44 .
Si se incluye una cadena con formato de relleno a la izquierda, {abi}{versionCode:0000} , produciría
50044 porque estamos rellenando a la izquierda versionCode con 0 . Como alternativa, puede usar el
relleno decimal, como {abi}{versionCode:D4} , que hace lo mismo que el ejemplo anterior.
Solo se admiten cadenas con formato de relleno "0" y "Dx", dado que el valor DEBE ser un entero.
Elementos de clave predefinidos
abi: inserta la ABI de destino para la aplicación.
2 – armeabi-v7a
3 – x86
4 – arm64-v8a
5 – x86_64
minSDK: inserta el valor de SDK mínimo admitido del archivo AndroidManifest.xml o 11 si no se
define ninguno.
versionCode: usa el código de versión directamente de Properties\AndroidManifest.xml .
Puede definir elementos personalizados con la propiedad $(AndroidVersionCodeProperties) , que se define
a continuación.
De forma predeterminada, el valor se establece en {abi}{versionCode:D6} . Si un programador quiere
mantener el comportamiento anterior, se puede reemplazar el valor predeterminado mediante el
establecimiento de la propiedad $(AndroidUseLegacyVersionCode) en true .
Agregado en Xamarin.Android 7.2.
AndroidVersionCodeProperties: propiedad de cadena que permite al desarrollador definir elementos
personalizados para usar con AndroidVersionCodePattern . Tienen el formato de un par key=value . Todos
los elementos de value deben ser valores enteros. Por ejemplo: screen=23;target=$(_AndroidApiLevel) .
Como puede ver, pueden hacer uso de propiedades de MSBuild existentes o personalizadas en la cadena.
Agregado en Xamarin.Android 7.2.
AotAssemblies: una propiedad booleana que determina si se los ensamblados se compilarán en modo
Ahead-of-Time en código nativo y se incluirán en el archivo .apk .
En Xamarin.Android 5.1, se agregó compatibilidad con esta propiedad.
De forma predeterminada, esta propiedad es False .
EmbedAssembliesIntoApk: una propiedad booleana que determina si los ensamblados de la aplicación
se deben insertar o no en el paquete de aplicación.
Esta propiedad debe ser True para compilaciones de versión y False para compilaciones de depuración.
Puede que deba ser True en las compilaciones de depuración si la implementación rápida no admite el
dispositivo de destino.
Cuando esta propiedad es False , la propiedad de MSBuild $(AndroidFastDeploymentType) también
controla lo que se insertará en el archivo .apk , lo que puede afectar a los tiempos de desarrollo y
recompilación.
EnableLLVM: propiedad booleana que determina si se usará o no LLVM al realizar la compilación Ahead
Of Time de los ensamblados en código nativo.
En Xamarin.Android 5.1, se agregó compatibilidad con esta propiedad.
De forma predeterminada, esta propiedad es False .
Esta propiedad se omite a menos que la propiedad de MSBuild $(AotAssemblies) sea True .
EnableProguard: una propiedad booleana que determina si se ejecuta o no proguard como parte del
proceso de empaquetado para vincular código Java.
En Xamarin.Android 5.1, se agregó compatibilidad con esta propiedad.
De forma predeterminada, esta propiedad es False .
Si es True , los archivos de ProguardConfiguration se usarán para controlar la ejecución de proguard .
JavaMaximumHeapSize: especifica el valor del parámetro java -Xmx que se usará al compilar el
archivo .dex como parte del proceso de empaquetado. Si no se especifica, la opción -Xmx suministra
java con un valor de 1G . Se ha detectado que esto suele ser necesario en Windows en comparación con
otras plataformas.
Es necesario especificar esta propiedad si el destino _CompileDex produce un error
java.lang.OutOfMemoryError .

Personalice el valor cambiando lo siguiente:


<JavaMaximumHeapSize>1G</JavaMaximumHeapSize>

JavaOptions: especifica opciones de línea de comando adicionales que se pasarán a java al compilar el
archivo .dex .
LinkerDumpDependencies: propiedad bool que permite la generación del archivo de dependencias del
enlazador. Este archivo se puede usar como entrada para la herramienta illinkanalyzer.
El valor predeterminado es False.
MandroidI18n: especifica la compatibilidad con la internacionalización que se incluye con la aplicación,
como tablas de intercalación y ordenación. El valor es una lista separada por comas o punto y coma de
uno o varios de los siguientes valores sin distinción entre mayúsculas y minúsculas:
None: no incluye codificaciones adicionales.
All: incluye todas las codificaciones disponibles.
CJK: incluye las codificaciones china, japonesa y coreana, como Japonés (EUC ) [enc-jp, CP51932],
Japonés (Shift-JIS ) [iso-2022-jp, shift_jis, CP932], Japonés (JIS ) [CP50220], Chino simplificado
(GB2312 ) [gb2312, CP936], Coreano (UHC ) [ks_c_5601-1987, CP949], Coreano (EUC ) [euc-kr,
CP51949], Chino tradicional (Big5 ) [big5, CP950] y Chino simplificado (GB18030 ) [GB18030,
CP54936].
MidEast: incluye las codificaciones de Oriente Medio, como Turco (Windows) [iso-8859-9,
CP1254], Hebreo (Windows) [windows-1255, CP1255], Árabe (Windows) [windows-1256,
CP1256], Árabe (ISO ) [iso-8859-6, CP28596], Hebreo (ISO ) [iso-8859-8, CP28598], Latín 5 (ISO )
[iso-8859-9, CP28599] y Hebreo (alternativa a Iso ) [iso-8859-8, CP38598].
Other: incluye otras codificaciones, como Cirílico (Windows) [CP1251], Báltico (Windows) [iso-
8859-4, CP1257], Vietnamita (Windows) [CP1258], Cirílico (KOI8 -R ) [koi8-r, CP1251], Ucraniano
(KOI8 -U ) [koi8-u, CP1251], Báltico (ISO ) [iso-8859-4, CP1257], Cirílico (ISO ) [iso-8859-5,
CP1251], ISCII Davenagari[x-iscii-de, CP57002], ISCII Bengalí[x-iscii-be, CP57003], ISCII Tamil[x-
iscii-ta, CP57004], ISCII Telugu[x-iscii-te, CP57005], ISCII Asamés[x-iscii-as, CP57006], ISCII
Oriya[x-iscii-or, CP57007], ISCII Canarés[x-iscii-ka, CP57008], ISCII Malayalam[x-iscii-ma,
CP57009], ISCII Gujarati[x-iscii-gu, CP57010], ISCII Punjabi[x-iscii-pa, CP57011] y Thai
(Windows) [CP874].
Rare: incluye las codificaciones raras, como IBM EBCDIC (Turco ) [CP1026], IBM EBCDIC (Latín 1,
sistemas abiertos) [CP1047], IBM EBCDIC (EE. UU. y Canadá con Euro ) [CP1140], IBM EBCDIC
(Alemania con Euro ) [CP1141], IBM EBCDIC (Dinamarca/Noruega con Euro ) [CP1142], IBM
EBCDIC (Finlandia/Suecia con Euro ) [CP1143], IBM EBCDIC (Italia con Euro ) [CP1144], IBM
EBCDIC (Latinoamérica/España con Euro ) [CP1145], IBM EBCDIC (Reino Unido con Euro )
[CP1146], IBM EBCDIC (Francia con Euro ) [CP1147], IBM EBCDIC (Internacional con Euro )
[CP1148], IBM EBCDIC (Islandés con Euro ) [CP1149], IBM EBCDIC (Alemania ) [CP20273], IBM
EBCDIC (Dinamarca/Noruega ) [CP20277], IBM EBCDIC (Finlandia/Suecia ) [CP20278], IBM
EBCDIC (Italia ) [CP20280], IBM EBCDIC (Latinoamérica/España ) [CP20284], IBM EBCDIC (Reino
Unido ) [CP20285], IBM EBCDIC (Katakana japonés extendido ) [CP20290], IBM EBCDIC (Francia )
[CP20297], IBM EBCDIC (Árabe) [CP20420], IBM EBCDIC (Hebreo ) [CP20424], IBM EBCDIC
(Islandés) [CP20871], IBM EBCDIC (Cirílico: serbio, búlgaro ) [CP21025], IBM EBCDIC (EE. UU. y
Canadá ) [CP37], IBM EBCDIC (Internacional) [CP500], Árabe (ASMO 708 ) [CP708],
Centroeuropeo (DOS ) [CP852] , Cirílico (DOS ) [CP855], Turco (DOS ) [CP857], Europeo
Occidental (DOS con Euro ) [CP858], Hebreo (DOS ) [CP862], Árabe (DOS ) [CP864], Ruso (DOS )
[CP866], Griego (DOS ) [CP869], IBM EBCDIC (Latín 2 ) [CP870] y IBM EBCDIC (Griego ) [CP875].
West: incluye las codificaciones occidentales, como Europeo Occidental (Mac) [macintosh,
CP10000], Islandés (Mac) [x-mac-icelandic, CP10079], Centroeuropeo (Windows) [iso-8859-2,
CP1250], Europeo Occidental (Windows) [iso-8859-1, CP1252], Griego (Windows) [iso-8859-7,
CP1253], Centroeuropeo (ISO ) [iso-8859-2, CP28592], Latín 3 (ISO ) [iso-8859-3, CP28593],
Griego (ISO ) [iso-8859-7, CP28597], Latín 9 (ISO ) [iso-8859-15, CP28605], Estados Unidos OEM
[CP437], Europeo Occidental (DOS ) [CP850], Portugués (DOS ) [CP860], Islandés (DOS ) [CP861],
Francés canadiense (DOS ) [CP863] y Nórdico (DOS ) [CP865].

<MandroidI18n>West</MandroidI18n>

MonoSymbolArchive: una propiedad booleana que controla si los artefactos de .mSYM para usarlos
más adelante con mono-symbolicate , a fin de extraer información “real” de nombre de archivo y número
de línea de los seguimientos de pila de versión.
Este valor es true de forma predeterminada para aplicaciones de “versión” que tienen habilitados
símbolos de depuración: $(EmbedAssembliesIntoApk) es true, $(DebugSymbols) es true y $(Optimize) es
true.
Agregado en Xamarin.Android 7.1.
Propiedades de compilación de proyectos de enlace
Las siguientes propiedades de MSBuild se usan con proyectos de enlace:
AndroidClassParser: una propiedad de cadena que controla cómo se analizan los archivos .jar . Entre
los posibles valores se incluyen:
class-parse: usa class-parse.exe para analizar el código de bytes de Java directamente, sin ayuda
de una JVM. Este valor es experimental.
jar2xml: usa jar2xml.jar para utilizar la reflexión de Java y extraer tipos y miembros de un
archivo .jar .
Las ventajas de class-parse sobre jar2xml son las siguientes:
class-parse puede extraer nombres de parámetro del código de bytes de Java que contiene
símbolos de depuración (por ejemplo, código de bytes compilado con javac -g ).
class-parse no "omite" las clases que se heredan de miembros de tipos que no se pueden
resolver o que los contienen.
Experimental. Agregado en Xamarin.Android 6.0.
El valor predeterminado es jar2xml .
El valor predeterminado cambiará en futuras versiones.
AndroidCodegenTarget: una propiedad de cadena que controla la ABI de destino de generación de
código. Entre los posibles valores se incluyen:
XamarinAndroid: usa la API de enlace de JNI presente desde Mono para Android 1.0. Los
ensamblados de enlace compilados con Xamarin.Android 5.0 o posterior solo se pueden ejecutar
en Xamarin.Android 5.0 o posterior (adiciones de API/ABI), pero el origen es compatible con
versiones de producto anteriores.
XAJavaInterop1: usa Java.Interop de uso para las invocaciones de JNI. Los ensamblados de
enlace que usan XAJavaInterop1 solo se pueden compilar y ejecutar con Xamarin.Android 6.1 o
posterior. Xamarin.Android 6.1 y versiones posteriores enlazan Mono.Android.dll con este valor.
Las ventajas de XAJavaInterop1 son las siguientes:
Ensamblados más pequeños.
Almacenamiento en caché de jmethodID para invocaciones de método base , mientras que
todos los demás enlaces de la jerarquía de herencia se compilan con XAJavaInterop1 o
versiones posteriores.
Almacenamiento en caché de jmethodID de los constructores de JCW (Java Callable
Wrapper) para subclases administradas.
El valor predeterminado es XAJavaInterop1 .
Propiedades del recurso
Las propiedades del recurso controlan la generación del archivo Resource.designer.cs , que proporciona acceso
a recursos de Android.
AndroidAapt2CompileExtraArgs: especifica opciones adicionales de la línea de comandos que se
pasan al comando aapt2 compile al procesar recursos de Android.
Se ha agregado en Xamarin.Android 9.1.
AndroidAapt2LinkExtraArgs: especifica opciones adicionales de la línea de comandos que se pasan al
comando aapt2 link al procesar recursos de Android.
Se ha agregado en Xamarin.Android 9.1.
AndroidExplicitCrunch: si va a compilar una aplicación con un gran número de recursos Drawable
locales, una compilación inicial (o recompilación) puede tardar minutos en completarse. Para acelerar el
proceso de compilación, intente incluir esta propiedad y establecerla en True . Cuando se establece esta
propiedad, el proceso de compilación analiza previamente los archivos .png.
Nota: Esta opción no es compatible con la opción $(AndroidUseAapt2) . Si $(AndroidUseAapt2) está
habilitada, se deshabilitará esta funcionalidad. Si quiere seguir usando esta característica, establezca
$(AndroidUseAapt2) en False .

Experimental. Agregado en Xamarin.Android 7.0.


AndroidResgenExtraArgs: especifica opciones adicionales de la línea de comandos para pasar al
comando aapt al procesar activos y recursos de Android.
AndroidResgenFile: especifica el nombre del archivo de recursos que se generará. La plantilla
predeterminada establece esta propiedad en Resource.designer.cs .
AndroidUseAapt2: propiedad bool que permite al desarrollador controlar el uso de la herramienta
aapt2 para el empaquetado. De forma predeterminada, este valor se establecerá en False y usaremos
aapt . Si el desarrollador quiere usar la nueva funcionalidad de aapt2 puede establecerlo

<AndroidUseAapt2>True</AndroidUseAapt2>

en su csproj. Especifique también la propiedad en la línea de comandos mediante

/p:AndroidUseAapt2=True

Se ha agregado en Xamarin.Android 8.3.


MonoAndroidResourcePrefix: especifica un prefijo de ruta de acceso que se quita del principio de los
nombres de archivo con una acción de compilación de AndroidResource . Esto permite cambiar la
ubicación de los recursos.
El valor predeterminado es Resources . Cambie este valor a res con estructuras de proyectos de Java.
Propiedades de firma
Las propiedades de firma controlan cómo se firma el paquete de aplicación para que se pueda instalar en un
dispositivo Android. Para permitir una iteración de compilación más rápida, las tareas de Xamarin.Android no
firman paquetes durante el proceso de compilación, porque es un proceso bastante lento. En su lugar, se firman
(si es necesario) antes de la instalación o durante la exportación, por medio del IDE o del destino de compilación
Install. Al invocar el destino SignAndroidPackage se produce un paquete con el sufijo -Signed.apk en el
directorio de salida.
De forma predeterminada, el destino de firma genera una nueva clave de firma de depuración, si es necesario. Si
desea usar una clave específica, por ejemplo, en un servidor de compilación, se pueden usar las siguientes
propiedades de MSBuild:
AndroidDebugKeyAlgorithm – Especifica el algoritmo predeterminado que se usará para
debug.keystore . El valor predeterminado es RSA .

AndroidDebugKeyValidity – Especifica la validez predeterminada para usarla con debug.keystore . El


valor predeterminado es 10950 , 30 * 365 o 30 years .
AndroidKeyStore: un valor booleano que indica si se debe usar información de firma personalizada. El
valor predeterminado es False , lo que significa que se usará la clave de firma de depuración
predeterminada para firmar paquetes.
AndroidSigningKeyAlias: especifica el alias de la clave en el almacén de claves. Es el valor de keytool -
alias usado al crear el almacén de claves.
AndroidSigningKeyPass: especifica la contraseña de la clave en el archivo de almacén de claves. Este es
el valor especificado cuando keytool pide que se escriba la contraseña de clave para
$(AndroidSigningKeyAlias) .
AndroidSigningKeyStore: especifica el nombre de archivo del archivo de almacén de claves creado por
keytool . Corresponde al valor proporcionado a la opción keytool - keystore.

AndroidSigningStorePass: especifica la contraseña de $(AndroidSigningKeyStore) . Es el valor


proporcionado a keytool al crear el archivo de almacén de claves y cuando se pide que se escriba la
contraseña del almacén de claves.
Por ejemplo, considere la siguiente invocación de keytool :

$ keytool -genkey -v -keystore filename.keystore -alias keystore.alias -keyalg RSA -keysize 2048 -validity
10000
Enter keystore password: keystore.filename password
Re-enter new password: keystore.filename password
...
Is CN=... correct?
[no]: yes

Generating 2,048 bit RSA key pair and self-signed certificate (SHA1withRSA) with a validity of 10,000 days
for: ...
Enter key password for keystore.alias
(RETURN if same as keystore password): keystore.alias password
[Storing filename.keystore]

Para usar el almacén de claves generado anteriormente, use el grupo de propiedades:


<PropertyGroup>
<AndroidKeyStore>True</AndroidKeyStore>
<AndroidSigningKeyStore>filename.keystore</AndroidSigningKeyStore>
<AndroidSigningStorePass>keystore.filename password</AndroidSigningStorePass>
<AndroidSigningKeyAlias>keystore.alias</AndroidSigningKeyAlias>
<AndroidSigningKeyPass>keystore.alias password</AndroidSigningKeyPass>
</PropertyGroup>

Acciones de compilación
Las acciones de compilación se aplican a archivos dentro del proyecto y controlan cómo se procesa el archivo.
AndroidAarLibrary
La acción de compilación de AndroidAarLibrary se debe utilizar para hacer referencia directamente a los
archivos .aar. Esta acción de compilación la utilizan normalmente componentes de Xamarin. Es decir, para incluir
referencias a archivos .aar que son necesarios para que funcionen Google Play y otros servicios.
Los archivos con esta acción de compilación se tratarán de un modo bastante similar a los recursos incrustados
en proyectos de biblioteca. El archivo .aar se extrae en el directorio intermedio. Después, los recursos y los
archivos .jar se incluirán en los grupos de elementos pertinentes.
AndroidBoundLayout
Indica que el archivo de diseño debe tener código subyacente generado en caso de que la propiedad
AndroidGenerateLayoutBindings se establezca en false . En todos los demás aspectos es idéntica a
AndroidResource , descrito anteriormente. Esta acción solo se puede usar con archivos de diseño:

<AndroidBoundLayout Include="Resources\layout\Main.axml" />

AndroidEnvironment
Los archivos con una acción de compilación de AndroidEnvironment se usan para inicializar variables de entorno
y propiedades del sistema durante el inicio del proceso. La acción de compilación AndroidEnvironment se puede
aplicar a varios archivos, y estos se evalúan sin ningún orden determinado (así que no especifique la misma
variable de entorno o propiedad de sistema en varios archivos).
AndroidFragmentType
Especifica el tipo completo predeterminado que se usará para todos los elementos de diseño de <fragment> al
generar el código de los enlaces de diseño. El valor predeterminado de la propiedad es el tipo estándar
Android.App.Fragment de Android.

AndroidJavaLibrary
Los archivos con una acción de compilación de AndroidJavaLibrary son archivos de Java (archivos .jar ) que se
incluirán en el paquete final de Android.
AndroidJavaSource
Los archivos con una acción de compilación de AndroidJavaSource son el código fuente de Java que se incluirá
en el paquete final de Android.
AndroidLintConfig
La acción de compilación "AndroidLintConfig" se debe usar con la propiedad de compilación
AndroidLintEnabled . Los archivos con esta acción de compilación se combinan y se pasan a las herramientas
lint de Android. Deben ser archivos XML que contengan información sobre qué pruebas se habilitan o
deshabilitan.
Vea la documentación de lint para obtener más información.
AndroidNativeLibrary
Las bibliotecas nativas se agregan a la compilación mediante el establecimiento de su acción de compilación en
AndroidNativeLibrary .

Tenga en cuenta que puesto que Android admite varias interfaces binarias de aplicación (ABI), el sistema de
compilación debe saber para qué ABI está compilada la biblioteca nativa. Hay dos maneras de hacerlo:
1. Examinando la ruta de acceso.
2. Mediante el atributo de elemento Abi .
Con el examen de la ruta de acceso, el nombre del directorio principal de la biblioteca nativa se utiliza para
especificar la ABI a la que se dirige la biblioteca. Por lo tanto, si agrega lib/armeabi-v7a/libfoo.so a la
compilación, la ABI se examina como armeabi-v7a .
Nombre del atributo de elemento
Abi: especifica la ABI de la biblioteca nativa.

<ItemGroup>
<AndroidNativeLibrary Include="path/to/libfoo.so">
<Abi>armeabi-v7a</Abi>
</AndroidNativeLibrary>
</ItemGroup>

AndroidResource
Todos los archivos con una acción de compilación de AndroidResource se compilan en recursos de Android
durante el proceso de compilación y se vuelven accesibles mediante $(AndroidResgenFile) .

<ItemGroup>
<AndroidResource Include="Resources\values\strings.xml" />
</ItemGroup>

Quizás los usuarios más avanzados deseen que recursos diferentes se usen en distintas configuraciones, pero
con la misma ruta de acceso efectiva. Para lograr esto, se pueden tener varios directorios de recursos y tener
archivos con las mismas rutas de acceso relativas dentro de estos diferentes directorios, y usar condiciones de
MSBuild para incluir condicionalmente diferentes archivos en diferentes configuraciones. Por ejemplo:

<ItemGroup Condition="'$(Configuration)'!='Debug'">
<AndroidResource Include="Resources\values\strings.xml" />
</ItemGroup>
<ItemGroup Condition="'$(Configuration)'=='Debug'">
<AndroidResource Include="Resources-Debug\values\strings.xml"/>
</ItemGroup>
<PropertyGroup>
<MonoAndroidResourcePrefix>Resources;Resources-Debug<MonoAndroidResourcePrefix>
</PropertyGroup>

LogicalName: especifica la ruta de acceso a los recursos de manera explícita. Permite la creación de “alias” de
archivos para que estén disponibles con varios nombres de recursos distintos.
<ItemGroup Condition="'$(Configuration)'!='Debug'">
<AndroidResource Include="Resources/values/strings.xml"/>
</ItemGroup>
<ItemGroup Condition="'$(Configuration)'=='Debug'">
<AndroidResource Include="Resources-Debug/values/strings.xml">
<LogicalName>values/strings.xml</LogicalName>
</AndroidResource>
</ItemGroup>

Contenido
La acción de compilación Content no se admite (dado que no hemos descubierto cómo admitirla sin un paso
seguramente costoso de primera ejecución).
A partir de Xamarin.Android 5.1, si se intenta usar la acción de compilación @(Content) se producirá una
advertencia XA0101 .
LinkDescription
Los archivos con una acción de compilación LinkDescription se usan para controlan el comportamiento del
enlazador.
ProguardConfiguration
Los archivos con una acción de compilación ProguardConfiguration contienen opciones que se usan para
controlar el comportamiento de proguard . Para más información sobre esta acción de compilación, consulte
ProGuard.
Estos archivos se omiten a menos que la propiedad de MSBuild $(EnableProguard) sea True .

Definiciones de destino
Las partes del proceso de compilación específicas de Xamarin.Android se definen en
$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets , pero también se requieren los
destinos normales específicos del lenguaje, como Microsoft.CSharp.targets, para compilar el ensamblado.
Las siguientes propiedades de compilación deben establecerse antes de importar los destinos de lenguaje:

<PropertyGroup>
<TargetFrameworkIdentifier>MonoDroid</TargetFrameworkIdentifier>
<MonoDroidVersion>v1.0</MonoDroidVersion>
<TargetFrameworkVersion>v2.2</TargetFrameworkVersion>
</PropertyGroup>

Todos estos destinos y propiedades se pueden incluir para C# mediante la importación de


Xamarin.Android.CSharp.targets:

<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />

Este archivo se puede adaptar fácilmente para otros lenguajes.


Compilar APK específicos de ABI
01/08/2019 • 15 minutes to read • Edit Online

En este documento se describe cómo compilar un APK que será el destino de una única ABI mediante
Xamarin.Android.

Información general
En algunas situaciones, puede ser conveniente que una aplicación tenga varios APK; cada APK está firmado con el
mismo almacén de claves y comparte el mismo nombre de paquete pero se compila para un dispositivo o una
configuración de Android específicos. Este no es el enfoque recomendado: es mucho más sencillo tener un APK
que pueda admitir varios dispositivos y configuraciones. Existen algunas situaciones en las que puede resultar útil
crear varios APK, como por ejemplo:
Reducir el tamaño del APK: Google Play impone un límite de tamaño de 100 MB en archivos APK. La
creación de APK específicos del dispositivo puede reducir el tamaño del APK, dado que solo es necesario
suministrar un subconjunto de activos y recursos para la aplicación.
Admitir diferentes arquitecturas de CPU: si la aplicación ha compartido bibliotecas para CPU
concretas, puede distribuir únicamente las bibliotecas compartidas para esa CPU.
Varios APK pueden complicar la distribución, un problema que soluciona Google Play. Google Play garantiza que
se entrega el APK correcto a un dispositivo en función del código de versión de la aplicación y otros metadatos
contenidos con AndroidManifest.XML. Para conocer de forma específica los detalles y las restricciones respecto
a cómo Google Play admite varios APK para una aplicación, consulte la documentación de Google sobre la
compatibilidad con varios APK.
En esta guía se describe cómo crear un script para la compilación de varios APK para una aplicación
Xamarin.Android, teniendo como destino cada APK una ABI específica. Se abarcan los siguientes temas:
1. Crear un código de versión único para el APK.
2. Crear una versión temporal de AndroidManifest.XML que se usará con este APK.
3. Compilar la aplicación mediante AndroidManifest.XML del paso anterior.
4. Preparar el APK para el lanzamiento mediante su firma y el uso de Zipalign.
Al final de esta guía encontrará un tutorial en el que se demuestra cómo crear scripts para estos pasos mediante
Rake.
Crear el código de la versión para el APK
Google recomienda un algoritmo determinado para el código de versión que usa un código de versión de siete
dígitos; consulte la sección Using a version code scheme (Usar un esquema de código de versión) en el
documento sobre la compatibilidad con varios APK. Al expandir este esquema de código de versión a ocho
dígitos, es posible incluir alguna información de ABI en el código de versión que garantiza que Google Play
distribuirá el APK correcto a un dispositivo. En la lista siguiente se explica este formato de código de versión de
ocho dígitos (que se indexan de izquierda a derecha):
Índice 0 (rojo en el diagrama siguiente): un entero de la ABI:
1– armeabi
2– armeabi-v7a
6– x86
Índice 1-2 (naranja en el diagrama siguiente): el nivel de API mínimo admitido por la aplicación.
Índice 3-4 (azul en el diagrama siguiente): los tamaños de pantalla admitidos:
1: pequeño
2: normal
3: grande
4: extra grande
Índice 5-7 (verde en el diagrama siguiente): un número único para el código de versión. Lo establece el
desarrollador. Debería aumentar para cada versión pública de la aplicación.
En el siguiente diagrama se ilustra la posición de cada código descrito en la lista anterior:

Google Play garantiza que se entrega el APK correcto al dispositivo en función del valor de versionCode y la
configuración de APK. El APK con el código de versión más alto se entrega al dispositivo. Por ejemplo, una
aplicación podría tener tres APK con los siguientes códigos de versión:
11413456: la ABI es armeabi ; tiene como destino el nivel de API 14; pantallas de pequeña a grande; con un
número de versión de 456.
21423456: la ABI es armeabi-v7a ; tiene como destino el nivel de API 14; pantallas de normal a grande; con un
número de versión de 456.
61423456: la ABI es x86 ; tiene como destino el nivel de API 14; pantallas de normal a grande; con un número
de versión de 456.
Para continuar con este ejemplo, imagine que se corrigió un error que era específico de armeabi-v7a . La versión
de la aplicación aumenta a 457 y se crea un nuevo APK con android:versionCode establecido en 21423457. Los
códigos de versión para armeabi y las versiones x86 permanecen igual.
Imagine ahora que la versión x86 recibe algunas actualizaciones o correcciones de errores que tienen como
destino una API más reciente (nivel de API 19), de modo que se convierte en la versión 500 de la aplicación. El
nuevo valor de versionCode cambiaría a 61923500 mientras que armeabi/armeabi-v7a permanecen sin cambios.
En este momento, los códigos de versión serían:
11413456: la ABI es armeabi ; tiene como destino el nivel de API 14; pantallas de pequeña a grande; con un
número de versión de 456.
21423457: la ABI es armeabi-v7a ; tiene como destino el nivel de API 14; pantallas de normal a grande; con un
número de versión de 456.
61923500: la ABI es x86 ; tiene como destino el nivel de API 19; pantallas de normal a grande; con un número
de versión de 500.
Mantener estos códigos de versión de forma manual puede ser una carga considerable para el desarrollador. El
proceso de calcular el valor correcto de android:versionCode y luego generar el APK debería automatizarse. En el
tutorial al final de este documento, se incluye un ejemplo de cómo hacerlo.
Crear un archivo AndroidManifest.XML temporal
Aunque no es estrictamente necesario, crear un archivo AndroidManifest.XML temporal para cada ABI puede
ayudar a evitar problemas que podrían surgir debido a la pérdida de información de una APK a la otra. Por
ejemplo, es fundamental que el atributo android:versionCode sea único para cada APK.
El modo en que se realice esto depende del sistema de scripts implicado, pero normalmente supone tomar una
copia del manifiesto de Android usado durante el desarrollo, modificarlo y, luego, usar ese manifiesto modificado
durante el proceso de compilación.
Compilar el APK
La mejor manera de compilar el APK por ABI es usar xbuild o msbuild , como se muestra en la siguiente línea
de comando de ejemplo:

/Library/Frameworks/Mono.framework/Commands/xbuild /t:Package /p:AndroidSupportedAbis=<TARGET_ABI>


/p:IntermediateOutputPath=obj.<TARGET_ABI>/ /p:AndroidManifest=<PATH_TO_ANDROIDMANIFEST.XML>
/p:OutputPath=bin.<TARGET_ABI> /p:Configuration=Release <CSPROJ FILE>

En la lista siguiente se explica cada parámetro de línea de comandos:


/t:Package : crea un APK de Android que se firma con el almacén de claves de depuración.
/p:AndroidSupportedAbis=<TARGET_ABI> : es la ABI para el destino. Debe ser armeabi , armeabi-v7a o x86 .
/p:IntermediateOutputPath=obj.<TARGET_ABI>/ : es el directorio que contendrá los archivos intermedios que
se crean como parte de la compilación. Si es necesario, Xamarin.Android creará un directorio con nombre
después de la ABI, como obj.armeabi-v7a . Se recomienda usar una carpeta para cada ABI, ya que, de esta
manera, se evitan problemas que pueden dar lugar a la pérdida de archivos entre una compilación y otra.
Tenga en cuenta que este valor se termina con un separador de directorio (una / en el caso de OS X).
/p:AndroidManifest: esta propiedad especifica la ruta de acceso al archivo AndroidManifest.XML que se
usará durante la compilación.
/p:OutputPath=bin.<TARGET_ABI> : es el directorio que albergará el APK final. Xamarin.Android creará un
directorio con nombre después de la ABI, por ejemplo bin.armeabi-v7a .
: realiza una compilación de versión del APK. Las compilaciones de depuración
/p:Configuration=Release
no se pueden cargar en Google Play.
<CS_PROJ FILE> : es la ruta de acceso al archivo .csproj del proyecto de Xamarin.Android.
Iniciar sesión y usar Zipalign con el APK
Es necesario firmar el APK antes de que se puede distribuir a través de Google Play. Para ello, se puede usar la
aplicación jarsigner que forma parte del Kit para desarrolladores de Java. La siguiente línea de comandos
demuestra cómo usar jarsigner en la línea de comandos:

jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore <PATH/TO/KEYSTORE> -storepass <PASSWORD> -
signedjar <PATH/FOR/SIGNED_JAR> <PATH/FOR/JAR/TO/SIGN> <NAME_OF_KEY_IN_KEYSTORE>

Se debe haber usado Zipaling en todas las aplicaciones de Xamarin.Android antes de que se puedan ejecutar en
un dispositivo. Este es el formato de la línea de comandos que se usará:

zipalign -f -v 4 <SIGNED_APK_TO_ZIPALIGN> <PATH/TO/ZIP_ALIGNED.APK>

Automatizar la creación de APK con Rake


El proyecto de ejemplo OneABIPerAPK es un sencillo proyecto de Android que demuestra cómo calcular un
número de versión específico de la ABI y compilar tres APK diferentes para cada una de las siguientes ABI:
armeabi
armeabi-v7a
x86
El archivo rakefile en el proyecto de ejemplo realiza cada uno de los pasos que se describieron en las secciones
anteriores:
1. Crea un elemento android:versionCode para el APK.
2. Escribe el elemento android:versionCode en un archivo AndroidManifest.XML personalizado para ese
APK.
3. Compila una compilación de versión del proyecto de Xamarin.Android que tendrá como destino
particularmente la ABI y con el archivo AndroidManifest.XML que se creó en el paso anterior.
4. Firma el APK con un almacén de claves de producción.
5. Usa Zipalign con el APK.
Para compilar todos los APK de la aplicación, ejecute la tarea build de Rake desde la línea de comandos:

$ rake build
==> Building an APK for ABI armeabi with ./Properties/AndroidManifest.xml.armeabi, android:versionCode =
10814120.
==> Building an APK for ABI x86 with ./Properties/AndroidManifest.xml.x86, android:versionCode = 60814120.
==> Building an APK for ABI armeabi-v7a with ./Properties/AndroidManifest.xml.armeabi-v7a,
android:versionCode = 20814120.

Una vez finalizada la tarea de Rake, habrá tres carpetas bin con el archivo xamarin.helloworld.apk . En la captura
de pantalla siguiente se muestra cada una de estas carpetas con su contenido:
NOTE
El proceso de compilación que se describe en esta guía se puede implementar en uno de muchos sistemas de compilación
diferentes. Aunque no tenemos un ejemplo ya escrito, también debería ser posible con Powershell / psake o Fake.

Resumen
En esta guía se proporcionan algunas sugerencias con la creación del APK de Android que tienen como destino
una ABI específica. También se examina un posible esquema para la creación de android:versionCodes que
identificará la arquitectura de CPU destinada al APK. En el tutorial se incluye un proyecto de ejemplo que se ha
compilado con scripts de Rake.

Vínculos relacionados
OneABIPerAPK (ejemplo)
Publicar una aplicación
Multiple APK Support for Google Play (Compatibilidad con varios APK en Google Play)
Emulador de la línea de comandos
11/07/2019 • 2 minutes to read • Edit Online

Ejecución de Android Emulator desde la línea de comandos


Para habilitar la ejecución de Android Emulator desde la línea de comandos, puede usar la herramienta "emulador"
que se proporciona en Android SDK. Esta herramienta se puede usar para ejecutar el emulador desde Terminal en
OS X o desde el símbolo del sistema en una máquina Windows.
Para iniciar un emulador de Android específico, ejecute el siguiente comando desde el directorio de herramientas
en la ubicación de Android SDK (por ejemplo, C:\android-sdk-windows\tools):
En Windows

emulator.exe -avd NameOfYourEmulator -partition-size 512

En macOS

./emulator -avd NameOfYourEmulator -partition-size 512

El motivo de necesitar el tamaño de partición es permitir que el emulador disponga de mucho espacio para
instalarse en él la plataforma de Xamarin.Android dado que, de forma predeterminada, el tamaño del emulador es
pequeño.
Puede encontrar más información sobre parámetros adicionales en este sitio de Android:
https://developer.android.com/studio/run/emulator-commandline
Depuración
11/07/2019 • 2 minutes to read • Edit Online

En esta sección se describe cómo depurar una aplicación de Xamarin.Android en dispositivos o emuladores.

Información general sobre depuración


Para desarrollar una aplicación Android es necesario ejecutarla, ya sea en un hardware físico o mediante un
emulador. El uso de hardware es el mejor enfoque, pero no siempre es el más práctico. En muchos casos, puede
resultar más sencillo y rentable simular o emular el hardware de Android mediante uno de los emuladores que se
describen a continuación.
Depuración en Android Emulator
En este artículo se describe cómo iniciar Android Emulator desde Visual Studio y ejecutar la aplicación en un
dispositivo virtual.
Depuración en un dispositivo
En este artículo se muestra cómo configurar un dispositivo Android físico para que la aplicación de
Xamarin.Android se pueda implementar directamente desde Visual Studio o Visual Studio para Mac.
Registro de depuración de Android
Un truco muy común que emplean los desarrolladores para depurar sus aplicaciones es usar Console.WriteLine .
Pero en una plataforma móvil como Android no hay consola. Los dispositivos Android proporcionan un registro
que es probable que necesite usar al escribir aplicaciones. Este registro se conoce a veces como logcat por el
comando escrito para recuperarlo. En este artículo se describe cómo usar logcat.

WARNING
Tenga en cuenta que Xamarin Android Player está en desuso. Para obtener más información, consulte el anuncio de esta
entrada de blog. Además, el Emulador de Microsoft Visual Studio para Android ha quedado obsoleto desde Visual
Studio 2017.
Depuración en Android Emulator
11/07/2019 • 9 minutes to read • Edit Online

En esta guía se explica cómo iniciar un dispositivo virtual en Android Emulator para depurar y probar la
aplicación.

Información general
Android Emulator (incluido como parte de la carga de trabajo Desarrollo para dispositivos móviles con
.NET) se puede ejecutar en varias configuraciones para simular otros dispositivos Android. Cada una de estas
configuraciones se crea como un dispositivo virtual. En esta guía, obtendrá información sobre cómo iniciar el
emulador desde Visual Studio y ejecutar la aplicación en un dispositivo virtual. Para obtener información sobre
cómo configurar Android Emulator y crear dispositivos virtuales, vea Configuración de Android Emulator.

Uso de un dispositivo virtual preconfigurado


Visual Studio
Visual Studio para Mac
Visual Studio incluye dispositivos virtuales preconfigurados que aparecen en el menú desplegable del
dispositivo. Por ejemplo, en la siguiente captura de pantalla de Visual Studio 2017, están disponibles varios
dispositivos virtuales preconfigurados:
VisualStudio_android-23_arm_phone
VisualStudio_android-23_arm_tablet
VisualStudio_android-23_x86_phone
VisualStudio_android-23_x86_tablet

Normalmente, se selecciona el dispositivo virtual VisualStudio_android-23_x86_phone para probar y


depurar una aplicación de teléfono. Si uno de estos dispositivos virtuales preconfigurados cumple los
requisitos (es decir, coincide con el nivel de API de destino de la aplicación), vaya a Inicio del emulador para
empezar a ejecutar la aplicación en el emulador. (Si todavía no está familiarizado con los niveles de API de
Android, vea Understanding Android API Levels (Información de los niveles de API de Android)).
Si el proyecto de Xamarin.Android usa un nivel de plataforma de destino que no es compatible con los
dispositivos virtuales disponibles, en el menú desplegable se enumerarán los dispositivos virtuales que no se
pueden usar, en Dispositivos no compatibles. Por ejemplo, el siguiente proyecto tiene una plataforma de
destino establecida en Android 7.1 Nougat (API 25), que es no es compatible con los dispositivos virtuales
Android 6.0 indicados en este ejemplo:
Puede hacer clic en Cambiar destino mínimo de Android para cambiar la versión mínima de Android del
proyecto de modo que coincida con el nivel de API de los dispositivos virtuales disponibles. También puede
usar Android Device Manager para crear dispositivos virtuales compatibles con el nivel de API de destino.
Para poder configurar dispositivos virtuales para un nuevo nivel de API, debe instalar las imágenes del sistema
correspondientes para ese nivel de API (vea Configuración de Android SDK para Xamarin.Android).

Edición de dispositivos virtuales


Para modificar dispositivos virtuales (o crear otros), debe usar Android Device Manager.

Inicio del emulador


Cerca de la parte superior de Visual Studio, hay un menú desplegable que se puede usar para seleccionar el
modo de Depuración o Versión. Al seleccionar Depuración, se asocia el depurador al proceso de la
aplicación que se ejecuta dentro del emulador después de que se inicie la aplicación. Al seleccionar el modo de
Versión, se deshabilita el depurador (pero todavía es posible ejecutar la aplicación y usar instrucciones de
registro para la depuración). Tras elegir un dispositivo virtual en el menú desplegable de dispositivos,
seleccione el modo de Depuración o Versión. Después, haga clic en el botón Reproducir para ejecutar la
aplicación:
Visual Studio
Visual Studio para Mac

Cuando se inicie el emulador, Xamarin.Android implementará la aplicación en el emulador.El emulador ejecuta


la aplicación con la imagen de dispositivo virtual configurada. A continuación, se muestra una captura de
pantalla de ejemplo de Android Emulator. En este ejemplo, el emulador está ejecutando una aplicación en
blanco denominada MyApp:
El emulador puede dejarse en ejecución, de modo que no es necesario cerrarlo y esperar a que se reinicie cada
vez que se inicie la aplicación. La primera vez que se ejecuta una aplicación de Xamarin.Android en el
emulador, se instala el tiempo de ejecución compartido de Xamarin.Android para el nivel de API de destino,
seguido de la aplicación. La instalación del tiempo de ejecución puede tardar unos minutos, así que tendrá que
esperar. La instalación del tiempo de ejecución tiene lugar solamente cuando se implementa en el emulador la
primera aplicación de Xamarin.Android, –de modo que las posteriores implementaciones serán más rápidas
porque solo se copiará la aplicación en el emulador.

Arranque rápido
Las versiones más recientes de Android Emulator incluyen una característica denominada Arranque rápido
que inicia el emulador en unos pocos segundos. Al cerrar el emulador, toma una instantánea del estado del
dispositivo virtual para que se pueda restaurar rápidamente desde ese estado cuando se reinicia. Para obtener
acceso a esta característica, necesita lo siguiente:
Android Emulator versión 27.0.2 o posterior
Android SDK Tools versión 26.1.1 o posterior
Cuando se instalan las versiones indicadas anteriormente del emulador y de las herramientas del SDK, la
característica de Arranque rápido se habilita de forma predeterminada.
El primer arranque en frío del dispositivo virtual tiene lugar sin una mejora de velocidad porque todavía no se
ha creado una instantánea:
Cuando salga del emulador, el Arranque rápido guarda el estado del emulador en una instantánea:

Los inicios posteriores del dispositivo virtual son mucho más rápidos porque el emulador simplemente
restaura el estado con el que se ha cerrado el emulador.
Solución de problemas
Para obtener sugerencias y soluciones alternativas a problemas habituales del emulador, vea Solución de
problemas de Android Emulator.

Resumen
En esta guía se explica el proceso para configurar Android Emulator para ejecutar y probar aplicaciones
Xamarin.Android. Se describen los pasos para iniciar el emulador mediante dispositivos virtuales
preconfigurados y se proporcionan los pasos para implementar una aplicación en el emulador desde Visual
Studio.
Para obtener más información sobre cómo usar Android Emulator, vea los temas siguientes para
desarrolladores de Android:
Navegar en la pantalla
Realizar tareas básicas en el emulador
Trabajar con los controles extendidos, la configuración y la ayuda
Ejecutar el emulador con el Arranque rápido
Depurar en un dispositivo
11/07/2019 • 2 minutes to read • Edit Online

En este artículo se explica cómo depurar una aplicación Xamarin.Android en un dispositivo Android físico.

Información general sobre la depuración en un dispositivo


Es posible depurar una aplicación Xamarin.Android en un dispositivo Android mediante Visual Studio para Mac o
Visual Studio. Antes de que realizar la depuración en un dispositivo, se debe configurar para el desarrollo y
conectarlo a su PC o Mac.

Depuración de una aplicación


Una vez que se conecte un dispositivo al equipo, se realiza la depuración de una aplicación de Xamarin.Android de
la misma manera que cualquier otro producto de Xamarin o aplicación .NET. Asegúrese de que la configuración de
Debug (Depuración) y el dispositivo externo estén seleccionados en el IDE. Esto garantizará que los símbolos de
depuración necesarios estén disponibles y que el IDE se pueda conectar a la aplicación en ejecución:
Visual Studio
Visual Studio para Mac

A continuación, se establece un punto de interrupción en el código:

Una vez seleccionado el dispositivo, Xamarin.Android se conecta al dispositivo, implementa la aplicación y, a


continuación, la ejecuta. Al alcanzar el punto de interrupción, el depurador detiene la aplicación, lo que permite que
la aplicación se depure de forma similar a cualquier otra aplicación de C#:
Resumen
En este documento se describe cómo depurar una aplicación de Xamarin.Android estableciendo un punto de
interrupción y seleccionando el dispositivo de destino.

Vínculos relacionados
Configurar el dispositivo para el desarrollo
Establecer el atributo Debuggable
Registro de depuración de Android
01/08/2019 • 11 minutes to read • Edit Online

Un truco muy común que emplean los desarrolladores para depurar sus aplicaciones es realizar llamadas a
Console.WriteLine . Pero en una plataforma móvil como Android no hay consola. Los dispositivos Android
proporcionan un registro que puede usar al escribir aplicaciones. Este registro se conoce a veces como logcat
debido al comando escrito para recuperarlo. Use la herramienta Registro de depuración para ver los datos
registrados.

Información general sobre el registro de depuración de Android


La herramienta Registro de depuración proporciona un método para ver la salida del registro mientras se
depura una aplicación a través de Visual Studio. El registro de depuración es compatible con los siguientes
dispositivos:
Teléfonos, tabletas y ponibles Android físicos.
Dispositivo virtual Android en ejecución en Android Emulator.

NOTE
La herramienta Registro de depuración no funciona con Xamarin Live Player.

El Registro de depuración no muestra mensajes de registro que se generan mientras la aplicación se ejecuta de
forma independiente en el dispositivo (es decir, mientras está desconectada de Visual Studio).

Acceso al registro de depuración desde Visual Studio


Visual Studio
Visual Studio para Mac
Para abrir la herramienta Registro de dispositivos, haga clic en el icono Registro de dispositivos (logcat) en
la barra de herramientas:

Como alternativa, inicie la herramienta Registro de dispositivos desde una de las selecciones de menú
siguientes:
Ver > Otras ventanas > Registro de dispositivos
Herramientas -> Android -> Registro de dispositivos
La captura de pantalla siguiente muestra las distintas partes de la ventana Herramienta de depuración:
Selector de dispositivos – Selecciona qué dispositivo físico o un emulador de ejecución se va a
supervisar.
Entradas de registro – Una tabla de mensajes de registro de logcat.
Borrar entradas del registro – Borra todas las entradas de registro actuales de la tabla.
Reproducir/Pausar – Alterna entre la actualización o la pausa de la visualización de las nuevas entradas
de registro.
Detener – Detiene la visualización de las nuevas entradas de registro.
Cuadro de búsqueda – Escriba las cadenas de búsqueda en este cuadro para filtrar un subconjunto de las
entradas de registro.
Cuando se muestre la ventana de la herramienta Registro de depuración, use el menú desplegable de
dispositivos para elegir el dispositivo Android que desea supervisar:

Después de seleccionar el dispositivo, la herramienta Registro de dispositivos agrega las entradas del registro
automáticamente desde una aplicación en ejecución (estas entradas del registro se muestran en la en la tabla de
entradas del registro). El cambio entre dispositivos se detiene y se inicia el registro de dispositivos. Tenga en
cuenta que un proyecto Android debe estar cargado antes de que los dispositivos aparezcan en el selector de
dispositivos. Si el dispositivo no aparece en el selector de dispositivos, compruebe que está disponible en el menú
desplegable de dispositivos de Visual Studio junto al botón Iniciar.

Acceso desde la línea de comandos


Visual Studio
Visual Studio para Mac
Otra opción es ver el registro de depuración a través de la línea de comandos. Abra una ventana de símbolo del
sistema y navegue hasta la carpeta de herramientas de la plataforma de Android SDK (normalmente, la carpeta
de herramientas de la plataforma del SDK se encuentra en C:\Archivos de programa (x86)\Android\android-
sdk\platform -tools).
Si se conecta solo un dispositivo (dispositivo físico o emulador), se puede ver el registro escribiendo el comando
siguiente:

$ adb logcat

Si se conecta más de un dispositivo, el dispositivo se debe identificar explícitamente. Por ejemplo, adb -d logcat
muestra el registro del único dispositivo físico conectado, mientras que adb -e logcat muestra el registro del
único emulador que se ejecuta.
Encontrará más comandos escribiendo adb y leyendo los mensajes de ayuda.

Escribir en el registro de depuración


Los mensajes pueden escribirse en el registro de depuración usando los métodos de la clase Android.Util.Log.
Por ejemplo:

string tag = "myapp";

Log.Info (tag, "this is an info message");


Log.Warn (tag, "this is a warning message");
Log.Error (tag, "this is an error message");

Esto genera una salida similar a la siguiente:

I/myapp (11103): this is an info message


W/myapp (11103): this is a warning message
E/myapp (11103): this is an error message

También es posible utilizar Console.WriteLine para escribir en el Registro de depuración. Estos mensajes
aparecen en logcat con un formato de salida ligeramente diferente (esta técnica es especialmente útil al depurar
aplicaciones de Xamarin.Forms en Android):

System.Console.WriteLine ("DEBUG - Button Clicked!");

Esto genera una salida similar a la siguiente en logcat:

Info (19543) / mono-stdout: DEBUG - Button Clicked!

Mensajes interesantes
Al leer el registro (y especialmente al proporcionar fragmentos de código de registro a otras personas), a menudo
es demasiado incómodo examinar el archivo de registro en su totalidad. Para facilitar la navegación por los
mensajes de registro, empiece buscando una entrada de registro que se parezca a la siguiente:

I/ActivityManager(12944): Starting: Intent { act=android.intent.action.MAIN cat=


[android.intent.category.LAUNCHER] flg=0x10200000 cmp=GcTest.GcTest/gctest.Activity1 } from pid 24175

En concreto, busque una línea que coincida con la expresión regular que también contiene el nombre del paquete
de aplicación:
^I.*ActivityManager.*Starting: Intent

Esta es la línea que corresponde al inicio de una actividad, y la mayoría de los mensajes siguientes (pero no
todos) deberían estar relacionados con la aplicación.
Tenga en cuenta que cada mensaje contiene el identificador de proceso (pid) del proceso que genera el mensaje.
En el mensaje de ActivityManager anterior, el proceso 12944 generó el mensaje. Para determinar qué proceso es
el proceso de la aplicación que se está depurando, busque el mensaje mono.MonoRuntimeProvider:

I/ActivityThread( 602): Pub TouchTest.TouchTest.__mono_init__: mono.MonoRuntimeProvider

Este mensaje procede del proceso que se inició. Todos los mensajes posteriores que contienen este pid proceden
del mismo proceso.
Atributo Debuggable
11/07/2019 • 2 minutes to read • Edit Online

Para que la depuración sea posible, Android admite el protocolo JDWP (Java Debug Wire Protocol). Se trata de
una tecnología que permite que herramientas como ADB se comuniquen con una JVM. Aunque JDWP es
importante durante el desarrollo, se debe deshabilitar antes de la publicación.
JDWP puede ser el valor del atributo android:debuggable en una aplicación Android. Xamarin.Android
proporciona los siguientes métodos para establecer este atributo:
1. Se crea un archivo AndroidManifext.xml y se establece ahí el atributo android:debuggable .
2. Se incluye ApplicationAttribute en un archivo .CS , así: [assembly: Application(Debuggable=false)] .

Si AndroidManifest.xml y ApplicationAttribute existen, el contenido de AndroidManifest.xml tiene prioridad


sobre lo que se especifica mediante ApplicationAttribute .
Si no existen ni ApplicationAttribute , el valor predeterminado del atributo
AndroidManifest.xml
android:debuggable depende de si se generan o no símbolos de depuración. Si existen símbolos de depuración,
Xamarin.Android establece el atributo android:debuggable en true .
Tenga en cuenta que el valor del atributo android:debuggable no depende necesariamente de la configuración de
compilación. Puede que las compilaciones de lanzamiento tengan el atributo android:debuggable establecido en
true.

Vínculos relacionados
Debuggable apps in the Android market (Aplicaciones que se pueden depurar en Android Market)
Entorno de Xamarin.Android
06/08/2019 • 9 minutes to read • Edit Online

Entorno de ejecución
El entorno de ejecución es el conjunto de variables de entorno y las propiedades del sistema de Android que
influyen en la ejecución del programa. Las propiedades del sistema de Android se pueden establecer con el
comando adb shell setprop , mientras que las variables de entorno se pueden establecer mediante la propiedad
del sistema debug.mono.env :

## Enable GREF logging


adb shell setprop debug.mono.log gref

## Set the MONO_LOG_LEVEL and MONO_LOG_MASK environment variables


## so that additional Mono messages will be written to `adb logcat`.
adb shell setprop debug.mono.env "'MONO_LOG_LEVEL=info|MONO_LOG_MASK=asm'"

Las propiedades del sistema de Android se establecen para todos los procesos del dispositivo de destino.
A partir de Xamarin.Android 4.6, las propiedades del sistema y las variables de entorno se pueden establecer o
invalidar por cada aplicación agregando un archivo de entorno al proyecto. Un archivo de entorno es un archivo
de texto sin formato Unix con una acción de compilación de AndroidEnvironment . El archivo de entorno
contiene líneas con el formato clave=valor. Los comentarios son líneas que comienzan por # . Las líneas en
blanco se omiten.
Si la clave comienza con una letra mayúscula, entonces se trata como una variable de entorno y setenv(3) se usa
para establecer la variable de entorno en el valor especificado durante el inicio del proceso.
Si la clave comienza con una letra minúscula, se trata como una propiedad del sistema Android y el valor es el
valor predeterminado: las propiedades del sistema de Android que controlan el comportamiento de ejecución de
Xamarin.Android se buscan primero en el almacén de propiedades del sistema de Android y, si no existe ningún
valor, se usa el valor especificado en el archivo de entorno. El objetivo es permitir que se use adb shell setprop
para invalidar los valores que proceden del archivo de entorno con fines de diagnóstico.

Variables de entorno de Xamarin.Android


Xamarin.Android admite la variable XA_HTTP_CLIENT_HANDLER_TYPE , que se puede establecer mediante
adb shell setprop debug.mono.env o por medio de la acción de compilación $(AndroidEnvironment) .

XA_HTTP_CLIENT_HANDLER_TYPE

El tipo completo de ensamblado que debe heredar de HttpMessageHandler y que se construye a partir de la
construcción predeterminada HttpClient() .
En Xamarin.Android 6.1, esta variable de entorno no se establece de forma predeterminada, y se usa
HttpClientHandler.
Como alternativa, puede especificarse el valor Xamarin.Android.Net.AndroidClientHandler para usar
java.net.URLConnection para el acceso a la red, que puede permitir el uso de TLS 1.2 cuando Android lo admita.

Agregado en Xamarin.Android 6.1.


Propiedades del sistema de Xamarin.Android
Xamarin.Android admite las siguientes propiedades del sistema, que se pueden establecer mediante
adb shell setprop o por medio de la acción de compilación $(AndroidEnvironment) .

debug.mono.debug
debug.mono.env
debug.mono.gc
debug.mono.log
debug.mono.max_grefc
debug.mono.profile
debug.mono.runtime_args
debug.mono.trace
debug.mono.wref
XA_HTTP_CLIENT_HANDLER_TYPE

debug.mono.debug

El valor de la propiedad del sistema debug.mono.debug es un entero. Si 1 , se comporta "como si" el proceso se
hubiera iniciado con mono --debug . Por lo general, se muestra la información de archivo y línea en seguimientos
de pila, etc., sin necesidad de que la aplicación se inicie desde un depurador.
debug.mono.env

Contiene una lista de variables de entorno separada por | .


debug.mono.gc

El valor de la propiedad del sistema debug.mono.debug es un entero. Si 1 , se debe registrar entonces la


información de GC.
Esto equivale a hacer que la propiedad del sistema debug.mono.log contenga gc .
debug.mono.log

Controla qué información adicional registrará Xamarin.Android en adb logcat . Es una cadena separada por
comas ( , ), que contiene uno de los siguientes valores:
all : imprimir todos los mensajes. En raras ocasiones es una buena idea, ya que incluye mensajes lref .
assembly : imprimir .apk y ensamblar los mensajes de análisis.
gc : imprimir los mensajes relacionados con GC.
gref : imprimir los mensajes de referencia global de JNI.
lref : imprimir los mensajes de referencia local de JNI.
Nota: Este valor en realidad enviará correo basura a adb logcat .
En Xamarin.Android 5.1, también creará un archivo .__override__/lrefs.txt , que puede volverse gigantesco.
Evítelo.
timing : imprimir alguna información de tiempo de método. Este valor también creará los archivos
.__override__/methods.txt y .__override__/counters.txt .

debug.mono.max_grefc

El valor de la propiedad del sistema debug.mono.max_grefc es un entero. Su valor invalida el recuento de GREF
máximo detectado para el dispositivo de destino.
Tenga en cuenta lo siguiente: Solo se puede usar con adb shell setprop debug.mono.max_grefc , ya que el valor no
estará disponible a tiempo con un archivo environment.txt.
debug.mono.profile

La propiedad del sistema debug.mono.profile habilita el generador de perfiles. Es equivalente a la opción


mono --profile , y utiliza sus mismos valores. ( Para más información, consulte la página man mono(1 )).

debug.mono.runtime_args

La propiedad del sistema debug.mono.runtime_args contiene opciones adicionales que se deben analizar mediante
mono.
debug.mono.trace

La propiedad del sistema debug.mono.trace permite el seguimiento. Es equivalente a la opción mono --trace ,y
utiliza sus mismos valores. (Para más información, consulte la página man mono(1)).
En general, no la utilice. El uso de seguimiento enviará correo basura a la salida de adb logcat , ralentizará
gravemente el comportamiento del programa y modificará su comportamiento (hasta agregar condiciones de
errores adicionales).
Sin embargo, en ocasiones, permite realizar cierta investigación adicional...
debug.mono.wref

La propiedad del sistema debug.mono.wref permite invalidar el mecanismo de referencia débil de JNI detectado
predeterminado. Hay dos valores admitidos:
jni : se usan referencias débiles de JNI, creadas por JNIEnv::NewWeakGlobalRef() y destruidas por
JNIEnv::DeleteWeakGlobalREf() .
java : se usan referencias globales de JNI con instancias java.lang.WeakReference de referencia.

De forma predeterminada, se usa java , hasta API-7 y en API-19 (Kit Kat) con ART habilitado. (API-8 agregó
referencias de jni y ART interrumpe las referencias de jni ).
Esta propiedad del sistema es útil para pruebas y determinadas formas de investigación. En general, no se debe
cambiar.
XA_HTTP_CLIENT_HANDLER_TYPE
Introducida primero en Xamarin.Android 6.1, esta variable de entorno declara la implementación de
HttpMessageHandler predeterminada que usará HttpClient . Esta variable no se establece de forma
predeterminada, y Xamarin.Android usará HttpClientHandler .

XA_HTTP_CLIENT_HANDLER_TYPE=Xamarin.Android.Net.AndroidClientHandler

NOTE
El dispositivo Android subyacente debe admitir TLS 1.2. Android 5.0 y versiones posteriores admiten TLS 1.2

Ejemplo
## Comments are lines which start with '#'
## Blank lines are ignored.

## Enable GREF messages to `adb logcat`


debug.mono.log=gref

## Clear out a Mono environment variable to decrease logging


MONO_LOG_LEVEL=

Vínculos relacionados
Seguridad de la capa de transporte
GDB
01/08/2019 • 7 minutes to read • Edit Online

Información general
Xamarin.Android 4.10 introdujo la compatibilidad parcial con el uso de gdb gracias al destino de MSBuild _Gdb .

NOTE
Para la compatibilidad con gdb es necesario tener instalado Android NDK.

Existen tres maneras de usar gdb :


1. Compilaciones de depuración con implementación rápida habilitada.
2. Compilaciones de depuración con implementación rápida deshabilitada.
3. Compilaciones de versión
Cuando haya algún problema, consulte la sección Solución de problemas.
Compilaciones de depuración con implementación rápida
Al compilar e implementar una compilación de depuración con implementación rápida habilitada, se puede asociar
gdb mediante el destino de MSBuild _Gdb .

En primer lugar, instale la aplicación. Para ello, puede usar el IDE o la línea de comandos:

$ /Library/Frameworks/Mono.framework/Commands/xbuild /t:Install *.csproj

En segundo lugar, ejecute el destino _Gdb . Al final de la ejecución, se imprime una línea de comandos de gdb :

$ /Library/Frameworks/Mono.framework/Commands/xbuild /t:_Gdb *.csproj


...
Target _Gdb:
"/opt/android/ndk/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/arm-linux-
androideabi-gdb" -x "/Users/jon/Development/Projects/Scratch.HelloXamarin20//gdb-symbols/gdb.env"
...

El destino _Gdb iniciará una actividad de iniciador declarada dentro del archivo AndroidManifest.xml . Para
especificar explícitamente qué actividad ejecutar, use la propiedad de MSBuild RunActivity . En este momento no
se admite el inicio de servicios y otras construcciones de Android.
El destino _Gdb creará un directorio gdb-symbols y copiará ahí el contenido de los directorios /system/lib y
$APPDIR/lib del destino.

NOTE
El contenido del directorio gdb-symbols está vinculado al destino de Android en el que realizó la implementación, y no se
reemplazará automáticamente si cambia el directorio. (Puede considerarlo un error). Si cambia los dispositivos de destino de
Android, deberá eliminar manualmente este directorio.

Por último, copie el comando gdb generado y ejecútelo en el shell:


$ "/opt/android/ndk/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/arm-linux-androideabi-gdb"
-x "/Users/jon/Development/Projects/Scratch.HelloXamarin20//gdb-symbols/gdb.env"
GNU gdb (GDB) 7.3.1-gg2
...
(gdb) bt
#0 0x40082e84 in nanosleep () from /Users/jon/Development/Projects/Scratch.HelloXamarin20/gdb-symbols/libc.so
#1 0x4008ffe6 in sleep () from /Users/jon/Development/Projects/Scratch.HelloXamarin20/gdb-symbols/libc.so
#2 0x74e46240 in ?? ()
#3 0x74e46240 in ?? ()
(gdb) c

Compilaciones de depuración sin implementación rápida


Las compilaciones de depuración con implementación rápida funcionan mediante la copia del programa
gdbserver de Android NDK en el directorio .__override__ de implementación rápida. Si la implementación
rápida está deshabilitada, puede que este directorio no exista.
Hay dos soluciones alternativas:
Establecer la propiedad del sistema debug.mono.log para que se cree el directorio .__override__ .
Incluya gdbserver dentro de .apk .
Establecer la propiedad del sistema debug.mono.log

Para establecer la propiedad del sistema debug.mono.log , use el comando adb :

$ adb shell setprop debug.mono.log gc

Una vez que se ha establecido la propiedad del sistema, ejecute el destino _Gdb y el comando gdb impreso, lo
mismo que hizo con la configuración de compilaciones de depuración con implementación rápida:

$ /Library/Frameworks/Mono.framework/Commands/xbuild /t:_Gdb *.csproj


...
Target _Gdb:
"/opt/android/ndk/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/arm-linux-
androideabi-gdb" -x "/Users/jon/Development/Projects/Scratch.HelloXamarin20//gdb-symbols/gdb.env"
...
$ "/opt/android/ndk/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/arm-linux-androideabi-gdb"
-x "/Users/jon/Development/Projects/Scratch.HelloXamarin20//gdb-symbols/gdb.env"
GNU gdb (GDB) 7.3.1-gg2
...
(gdb) c

Incluir gdbserver en la aplicación


Para incluir gdbserver dentro de la aplicación:
1. Busque gdbserver en su instancia de Android NDK (debe estar en
$ANDROID_NDK_PATH/prebuilt/android-arm/gdbserver/gdbserver) y cópielo en el directorio del
proyecto.
2. Cambie el nombre de gdbserver por libs/armeabi-v7a/libgdbserver.so.
3. Agregue libs/armeabi-v7a/libgdbserver.so al proyecto con una acción de compilación de
AndroidNativeLibrary .

4. Vuelva a compilar y a instalar la aplicación.


Una vez que la aplicación se ha instalado de nuevo, ejecute el destino _Gdb y el comando gdb impreso, lo mismo
que hizo con la configuración de compilaciones de depuración con implementación rápida:

$ /Library/Frameworks/Mono.framework/Commands/xbuild /t:_Gdb *.csproj


...
Target _Gdb:
"/opt/android/ndk/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/arm-linux-
androideabi-gdb" -x "/Users/jon/Development/Projects/Scratch.HelloXamarin20//gdb-symbols/gdb.env"
...
$ "/opt/android/ndk/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/arm-linux-androideabi-gdb"
-x "/Users/jon/Development/Projects/Scratch.HelloXamarin20//gdb-symbols/gdb.env"
GNU gdb (GDB) 7.3.1-gg2
...
(gdb) c

Versiones de lanzamiento
Para la compatibilidad con gdb son necesarias tres cosas:
1. El permiso de INTERNET .
2. Tener habilitada la depuración de aplicaciones.
3. Un elemento gdbserver accesible.

El permiso de INTERNET está habilitado de forma predeterminada en las aplicaciones de depuración. Si no existe
aún en la aplicación, puede agregarlo; para ello, edite Properties/AndroidManifest.xml o las propiedades del
proyecto.
Para habilitar la depuración de aplicaciones, se puede definir la propiedad de atributo personalizada
ApplicationAttribute.Debugging como true , o se puede editar Properties/AndroidManifest.xml y definir el
atributo //application/@android:debuggable como true :

<application android:label="Example.Name.Here" android:debuggable="true">

Para proporcionar un elemento gdbserver accesible, siga la sección Compilaciones de depuración sin
implementación rápida.
Un aspecto a tener en cuenta: el destino de MSBuild _Gdb terminará todas las instancias de aplicación que
estaban en ejecución. Esto no funciona en destinos de Android v4.0.

Solución de problemas
mono_pmip no funciona
La función mono_pmip (útil para obtener marcos de pila administrados) se exporta desde libmonosgen-2.0.so , que
actualmente el destino _Gdb no puede extraer. (Este problema se corregirá en futuras versiones).
Para habilitar las funciones de llamada ubicadas en libmonosgen-2.0.so , cópielas del dispositivo de destino al
directorio gdb-symbols :

$ adb pull /data/data/Mono.Android.DebugRuntime/lib/libmonosgen-2.0.so Project/gdb-symbols

A continuación, reinicie la sesión de depuración.


Error de bus: 10 al ejecutar el comando gdb

Cuando el comando gdb produce el error "Bus error: 10" , reinicie el dispositivo Android.
$ "/path/to/arm-linux-androideabi-gdb" -x "Project/gdb-symbols/gdb.env"
GNU gdb (GDB) 7.3.1-gg2
Copyright (C) 2011 Free Software Foundation, Inc.
...
Bus error: 10
$

Ningún seguimiento de pila después de la asociación

$ "/path/to/arm-linux-androideabi-gdb" -x "Project/gdb-symbols/gdb.env"
GNU gdb (GDB) 7.3.1-gg2
Copyright (C) 2011 Free Software Foundation, Inc.
...
(gdb) bt
No stack.

Este problema suele ser un indicio de que el contenido del directorio gdb-symbols no está sincronizado con el
destino de Android. (¿Cambió su destino de Android?)
Elimine el directorio gdb-symbols e inténtelo de nuevo.
Vincular en Android
01/08/2019 • 9 minutes to read • Edit Online

Las aplicaciones de Xamarin.Android usan un enlazador para reducir el tamaño de la aplicación. El enlazador
emplea análisis estáticos de la aplicación para determinar qué ensamblados, tipos y miembros se usan realmente.
El enlazador se comporta entonces como un recolector de elementos no utilizados, que busca continuamente los
ensamblados, tipos y miembros a los que se hace referencia hasta que se encuentra la clausura completa de los
ensamblados, los tipos y los miembros a los que se hace referencia. Todo el contenido fuera de esta clausura se
descarta.
Por ejemplo, el ejemplo Hello, Android:

CONFIGURACIÓN TAMAÑO 1.2.0 TAMAÑO 4.0.1

Lanzar sin vincular: 14,0 MB 16,0 MB

Lanzar con vinculación: 4,2 MB 2,9 MB

Enlace de resultados de un paquete con un tamaño un 30 % inferior al del paquete original (sin vincular) en 1.2.0
y un 18 % inferior al del paquete sin vincular en 4.0.1.

Control
La vinculación se basa en análisis estáticos. Por lo tanto, todo lo que depende del entorno en tiempo de ejecución
no se detectará:

// To play along at home, Example must be in a different assembly from MyActivity.


public class Example {
// Compiler provides default constructor...
}

[Activity (Label="Linker Example", MainLauncher=true)]


public class MyActivity {
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);

// Will this work?


var o = Activator.CreateInstance (typeof (ExampleLibrary.Example));
}
}

Comportamiento del enlazador


El mecanismo principal para controlar el enlazador es el menú desplegable Comportamiento del enlazador
(Vinculación en Visual Studio) del cuadro de diálogo Opciones del proyecto. Hay tres opciones:
1. No vincular (Ninguno en Visual Studio)
2. Vincular ensamblados de SDK (Solo ensamblados de SDK )
3. Vincular todos los ensamblados (Ensamblados de SDK y usuario)
La opción No vincular desactiva el enlazador; en el ejemplo de tamaño de aplicación anterior "Lanzar sin
vincular" se usó este comportamiento. Es útil para solucionar errores en tiempo de ejecución, para ver si es
responsabilidad del enlazador. Normalmente, no se recomienda esta configuración para las compilaciones de
producción.
La opción Vincular ensamblados de SDK solo vincula los ensamblados que se proporcionan con
Xamarin.Android. Todos los demás ensamblados (como el código) no se vinculan.
La opción Vincular todos los ensamblados vincula todos los ensamblados, lo que significa que el código
también puede eliminarse si no hay referencias estáticas.
El ejemplo anterior funcionará con las opciones No vincular y Vincular ensamblados de SDK y presentará errores
con la opción Vincular todos los ensamblados, en cuyo caso se generará el siguiente error:

E/mono (17755): [0xafd4d440:] EXCEPTION handling: System.MissingMethodException: Default constructor not


found for type ExampleLibrary.Example.
I/MonoDroid(17755): UNHANDLED EXCEPTION: System.MissingMethodException: Default constructor not found for
type ExampleLibrary.Example.
I/MonoDroid(17755): at System.Activator.CreateInstance (System.Type,bool) <0x00180>
I/MonoDroid(17755): at System.Activator.CreateInstance (System.Type) <0x00017>
I/MonoDroid(17755): at LinkerScratch2.Activity1.OnCreate (Android.OS.Bundle) <0x00027>
I/MonoDroid(17755): at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (intptr,intptr,intptr) <0x00057>
I/MonoDroid(17755): at (wrapper dynamic-method) object.95bb4fbe-bef8-4e5b-8e99-ca83a5d7a124
(intptr,intptr,intptr) <0x00033>
E/mono (17755): [0xafd4d440:] EXCEPTION handling: System.MissingMethodException: Default constructor not
found for type ExampleLibrary.Example.
E/mono (17755):
E/mono (17755): Unhandled Exception: System.MissingMethodException: Default constructor not found for type
ExampleLibrary.Example.
E/mono (17755): at System.Activator.CreateInstance (System.Type type, Boolean nonPublic) [0x00000] in
<filename unknown>:0
E/mono (17755): at System.Activator.CreateInstance (System.Type type) [0x00000] in <filename unknown>:0
E/mono (17755): at LinkerScratch2.Activity1.OnCreate (Android.OS.Bundle bundle) [0x00000] in <filename
unknown>:0
E/mono (17755): at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (IntPtr jnienv, IntPtr
native__this, IntPtr native_savedInstanceState) [0x00000] in <filename unknown>:0
E/mono (17755): at (wrapper dynamic-method) object:95bb4fbe-bef8-4e5b-8e99-ca83a5d7a124
(intptr,intptr,intptr)

Conservar el código
A veces, el enlazador eliminará código que desea conservar. Por ejemplo:
Es posible que tenga código al que llamar de forma dinámica mediante
System.Reflection.MemberInfo.Invoke .

Si crea instancias de tipos de forma dinámica, puede que desee conservar el constructor predeterminado
de sus tipos.
Si usa la serialización XML, puede que desee conservar las propiedades de los tipos.
En estos casos, puede usar el atributo Android.Runtime.Preserve. Cada miembro no vinculado de forma estática
por la aplicación es susceptible de ser eliminado, por lo que se puede usar este atributo para marcar los miembros
a los que no se hace referencia de forma estática pero que aún son necesarios para la aplicación. Este atributo se
puede aplicar en cada miembro de un tipo o en el propio tipo.
En el ejemplo siguiente, este atributo se utiliza para conservar el constructor de la clase Example :

public class Example


{
[Android.Runtime.Preserve]
public Example ()
{
}
}
Si desea conservar todo el tipo, puede usar la siguiente sintaxis de atributo:

[Android.Runtime.Preserve (AllMembers = true)]

Por ejemplo, en el siguiente fragmento de código, toda la clase Example se conserva para la serialización XML:

[Android.Runtime.Preserve (AllMembers = true)]


class Example
{
// Compiler provides default constructor...
}

A veces se desean conservar determinados tipos, pero solo si se mantiene el tipo contenedor. En tales casos, use
la siguiente sintaxis de atributo:

[Android.Runtime.Preserve (Conditional = true)]

Si no desea recurrir a una dependencia en las bibliotecas de Xamarin, por ejemplo, como en el supuesto caso de
que compile una biblioteca de clases portátil multiplataforma, también puede usar el atributo
Android.Runtime.Preserve . Para ello, declare una clase PreserveAttribute en el espacio de nombres
Android.Runtime como este:

namespace Android.Runtime
{
public sealed class PreserveAttribute : System.Attribute
{
public bool AllMembers;
public bool Conditional;
}
}

En los ejemplos anteriores, el atributo Preserve se declara en el espacio de nombres Android.Runtime ; sin
embargo, puede usar el atributo Preserve porque el vinculador busca este atributo por nombre de tipo de
atributo en cualquier espacio de nombres.
falseflag
Si no se puede usar el atributo [Preserve], a menudo resulta útil proporcionar un bloque de código para que el
enlazador crea que se usa el tipo, al tiempo que se impide la ejecución del bloque de código en tiempo de
ejecución. Para usar esta técnica, podríamos hacer lo siguiente:

[Activity (Label="Linker Example", MainLauncher=true)]


class MyActivity {

#pragma warning disable 0219, 0649


static bool falseflag = false;
static MyActivity ()
{
if (falseflag) {
var ignore = new Example ();
}
}
#pragma warning restore 0219, 0649

// ...
}
linkskip
Es posible especificar que un conjunto de ensamblados proporcionado por el usuario no debe vincularse en
absoluto, mientras que se permite omitir otros ensamblados de usuario con la opción Vincular ensamblados de
SDK mediante el uso de la propiedad AndroidLinkSkip MSBuild:

<PropertyGroup>
<AndroidLinkSkip>Assembly1;Assembly2</AndroidLinkSkip>
</PropertyGroup>

LinkDescription
La @(LinkDescription) acción de compilación puede usarse en archivos que pueden contener un archivo de
configuración de enlazador personalizado. .edmx. Puede que sea necesario que los archivos de configuración de
enlazador personalizados conserven los miembros internal o private .
Atributos personalizados
Cuando se vincula un ensamblado, se quitarán los siguientes tipos de atributo personalizado de todos los
miembros:
System.ObsoleteAttribute
System.MonoDocumentationNoteAttribute
System.MonoExtensionAttribute
System.MonoInternalNoteAttribute
System.MonoLimitationAttribute
System.MonoNotSupportedAttribute
System.MonoTODOAttribute
System.Xml.MonoFIXAttribute
Cuando se vincula un ensamblado, se quitarán los siguientes tipos de atributo personalizado de todos los
miembros de las compilaciones de versiones:
System.Diagnostics.DebuggableAttribute
System.Diagnostics.DebuggerBrowsableAttribute
System.Diagnostics.DebuggerDisplayAttribute
System.Diagnostics.DebuggerHiddenAttribute
System.Diagnostics.DebuggerNonUserCodeAttribute
System.Diagnostics.DebuggerStepperBoundaryAttribute
System.Diagnostics.DebuggerStepThroughAttribute
System.Diagnostics.DebuggerTypeProxyAttribute
System.Diagnostics.DebuggerVisualizerAttribute

Vínculos relacionados
Configuración personalizada del enlazador
Vincular en iOS
Dispositivos de varios núcleos y Xamarin.Android
22/07/2019 • 19 minutes to read • Edit Online

Android puede ejecutarse en varias arquitecturas de equipo diferentes. En este documento se describen las
distintas arquitecturas de CPU que se pueden emplear con una aplicación Xamarin.Android. También se explica
cómo las aplicaciones Android se empaquetan para admitir distintas arquitecturas de CPU. Se introducirá la
Interfaz binaria de aplicación (ABI ) y se proporcionarán instrucciones respecto a cuáles ABI usar en una
aplicación Xamarin.Android.

Información general
Android permite la creación de "fat binaries" (también conocidos como binarios multiarquitectura), un único
archivo .apk que contiene código máquina que admitirá varias arquitecturas diferentes de CPU. Para ello, cada
trozo de código máquina se asocia con una Interfaz binaria de aplicación. La ABI se usa para controlar qué código
máquina se ejecutará en un dispositivo de hardware determinado. Por ejemplo, para que una aplicación Android
se ejecute en un dispositivo x86, es necesario incluir compatibilidad con la ABI x86 al compilar la aplicación.
En concreto, cada aplicación Android admitirá al menos una interfaz binaria de aplicación insertada (EABI). Las
EABI son convenciones específicas de programas de software insertados. Por lo general, una EABI describe cosas
como:
El conjunto de instrucciones de CPU.
El orden secuencial (endianness) en que la memoria se almacena y carga en tiempo de ejecución.
El formato binario de archivos de objetos y bibliotecas de programa, así como el tipo de contenido que se
permite o admite en estos archivos y bibliotecas.
Las diversas convenciones usadas para pasar datos entre el código de aplicación y el sistema (por ejemplo,
cómo se usan los registros o la pila al llamar a funciones, las restricciones de alineación, etc.)
Restricciones de tamaño y alineación para tipos de enumeración, estructuras, campos y matrices.
La lista de símbolos de función disponibles para el código máquina en tiempo de ejecución, en general
desde un conjunto de bibliotecas muy específico seleccionado.
armeabi y la seguridad para subprocesos
A continuación se examina en detalle la Interfaz binaria de aplicación, pero es importante recordar que el entorno
de tiempo de ejecución de armeabi que se usa en Xamarin.Android no es seguro para subprocesos. Si una
aplicación que tiene compatibilidad con armeabi se implementa en un dispositivo armeabi-v7a , se producirán
muchas excepciones raras e inexplicables.
Debido a un error en Android 4.0.0, 4.0.1, 4.0.2 y 4.0.3, las bibliotecas nativas se seleccionarán del directorio
armeabi aun en el caso de que haya un directorio armeabi-v7a y el dispositivo sea un dispositivo armeabi-v7a .

NOTE
Xamarin.Android garantiza que .so se agrega al APK en el orden correcto. Este error no debería ser un problema para los
usuarios de Xamarin.Android.

Descripciones de ABI
Cada ABI compatible con Android se identifica mediante un nombre único.
armeabi
Este es el nombre de una EABI para CPU basadas en ARM que admiten al menos el conjunto de instrucciones
ARMv5TE. Android sigue la ABI GNU/Linux de ARM little endian. Esta ABI no es compatible con cálculos de
punto flotante asistidos por hardware. Todas las operaciones de FP se realizan mediante funciones del asistente de
software que proceden de la biblioteca estática libgcc.a del compilador. Los dispositivos SMP no admiten
armeabi .

IMPORTANT
El código armeabi de Xamarin.Android no es seguro para subprocesos y no se debe usar en dispositivos armeabi-v7a de
varios núcleos (se describen a continuación). El uso de código armeabi en un dispositivo armeabi-v7a de un único núcleo
es seguro.

armeabi-v7a
Se trata de otro conjunto de instrucciones de CPU basado en ARM que amplía la EABI armeabi descrita
anteriormente. La EABI armeabi-v7a presenta compatibilidad con operaciones de punto flotante de hardware y
varios dispositivos de CPU (SMP ). Las aplicaciones que usan la EABI armeabi-v7a pueden esperar considerables
mejoras en el rendimiento por encima de las aplicaciones que usan armeabi .

NOTE
El código máquina armeabi-v7a no se ejecuta en dispositivos ARMv5.

arm64-v8a
Se trata de un conjunto de instrucciones de 64 bits que se basa en la arquitectura de CPU de ARMv8. Esta
arquitectura se usa en Nexus 9. Xamarin.Android 5.1 ha introducido soporte técnico para esta arquitectura (para
más información, consulte 64-bit runtime support [Soporte técnico del entorno de ejecución de 64 bits]).
x86
Este es el nombre de una ABI para CPU que admiten el conjunto de instrucciones conocido comúnmente como
x86 o IA -32. Esta ABI corresponde a las instrucciones del conjunto de instrucciones Pentium Pro, que incluye los
conjuntos de instrucciones MMX, SSE, SSE2 y SSE3. No incluye ninguna otra extensión opcional de conjunto de
instrucciones IA-32 como:
La instrucción MOVBE.
La extensión SSE3 complementaria (SSSE3).
Cualquier variante de SSE4.

NOTE
Aunque se ejecuta en x86, Google TV no es compatible con el NDK de Android.

x86_64
Este es el nombre de una ABI para CPU que admiten el conjunto de instrucciones x86 de 64 bits (también
conocido como x64 o AMD64). Xamarin.Android 5.1 ha introducido soporte técnico para esta arquitectura (para
más información, consulte 64-bit runtime support [Soporte técnico del entorno de ejecución de 64 bits]).
Formato de archivo de APK
El paquete de aplicaciones Android es el formato de archivo que contiene todo el código, los activos, los recursos y
los certificados necesarios para una aplicación Android. Es un archivo .zip , pero usa la extensión de nombre de
archivo .apk . Cuando se expande, se puede ver el contenido de un archivo .apk creado en Xamarin.Android en
la captura de pantalla siguiente:
Una descripción rápida del contenido del archivo .apk :
AndroidManifest.xml– este es el archivo AndroidManifest.xml , en formato XML binario.
classes.dex– contiene el código de la aplicación, compilado en el formato de archivo dex que usa la
máquina virtual en tiempo de ejecución de Android.
resources.arsc– este archivo contiene todos los recursos precompilados de la aplicación.
lib: este directorio contiene el código compilado de cada ABI. Contendrá una subcarpeta para cada ABI que
se ha descrito en la sección anterior. En la captura de pantalla anterior, el archivo .apk en cuestión tiene
bibliotecas nativas para armeabi-v7a y para x86 .
META -INF– este directorio (si existe) se usa para almacenar información de firma, paquetes y datos de
configuración de extensión.
res– este directorio contiene los recursos que no se compilaron en resources.arsc .

NOTE
El archivo libmonodroid.so es la biblioteca nativa que necesitan todas las aplicaciones Xamarin.Android.

Compatibilidad con ABI en dispositivos Android


Cada dispositivo Android admite la ejecución de código nativo en hasta dos ABI:
La ABI "principal" – corresponde al código máquina usado en la imagen del sistema.
Una ABI "secundaria" – una ABI opcional que también es compatible con la imagen del sistema.
Por ejemplo, normalmente un dispositivo ARMv5TE solo tendrá una ABI principal de armeabi , mientras que un
dispositivo ARMv7 especificaría una ABI principal de armeabi-v7a y una ABI secundaria de armeabi .
Normalmente, un dispositivo x86 solo debería especificar una ABI principal de x86 .
Instalación de bibliotecas nativas de Android
En el momento de la instalación del paquete, las bibliotecas nativas que contiene el archivo .apk se extraen en el
directorio de biblioteca nativa de la aplicación, normalmente /data/data/<package-name>/lib y, por tanto, se
conocen como $APP/lib .
El comportamiento de la instalación de bibliotecas nativas de Android varía considerablemente según la versión
de Android.
Instalación de bibliotecas nativas: Versiones anteriores a Android 4.0
Las versiones de Android anteriores a 4.0 Ice Cream Sandwich solo extraían las bibliotecas nativas de una única
ABI dentro del archivo .apk . Las aplicaciones Android de esta hornada primero intentan extraer todas las
bibliotecas nativas de la ABI principal, y si no están ahí, de la ABI secundaria. No se realiza ninguna combinación.
Por ejemplo, considere una situación donde una aplicación está instalada en un dispositivo armeabi-v7a . El
archivo .apk, que admite armeabi y armeabi-v7a , contiene los siguientes directorios y archivos lib de ABI:

lib/armeabi/libone.so
lib/armeabi/libtwo.so
lib/armeabi-v7a/libtwo.so

Después de la instalación, el directorio de bibliotecas nativas contendrá:

$APP/lib/libtwo.so # from the armeabi-v7a directory in the apk

En otras palabras, no se instala ningún archivo libone.so . Como consecuencia, se producen problemas, dado que
libone.so no existe para que la aplicación se cargue en tiempo de ejecución. Este comportamiento, aunque
inesperado, se ha registrado como un error y se vuelve a clasificar como que funciona según lo esperado.
Por lo tanto, cuando el destino son versiones de Android anteriores a la 4.0, es necesario proporcionar todas las
bibliotecas nativas para cada ABI que admita la aplicación, es decir, el archivo .apk debe contener:

lib/armeabi/libone.so
lib/armeabi/libtwo.so
lib/armeabi-v7a/libone.so
lib/armeabi-v7a/libtwo.so

Instalación de bibliotecas nativas: Android 4.0 – Android 4.0.3


Android 4.0 Ice Cream Sandwich cambia la lógica de extracción. Enumera todas las bibliotecas nativas, comprueba
si el nombre base del archivo ya se ha extraído y, si se cumplen las dos siguientes condiciones, se extrae la
biblioteca:
Aún no se ha extraído.
La ABI de la biblioteca nativa corresponde a la ABI principal o secundaria del destino.
Al cumplirse estas dos condiciones, es posible un comportamiento de "combinación"; es decir, si tenemos un
archivo .apk con el siguiente contenido:

lib/armeabi/libone.so
lib/armeabi/libtwo.so
lib/armeabi-v7a/libtwo.so

Tras la instalación, el directorio de biblioteca nativa contendrá:

$APP/lib/libone.so
$APP/lib/libtwo.so

Lamentablemente, este comportamiento depende del orden, tal como se describe en el documento Problema
24321: Galaxy Nexus 4.0.2 usa código nativo de armeabi cuando armeabi y armeabi-v7a se incluyen en el apk.
Las bibliotecas nativas se procesan "en orden" (como se enumeran al descomprimir, por ejemplo) y se extrae la
primera coincidencia. Dado que el archivo .apk contiene las versiones armeabi y armeabi-v7a de libtwo.so , y
armeabi se muestra en primer lugar, la versión que se extrae es armeabi y no la versión armeabi-v7a :

$APP/lib/libone.so # armeabi
$APP/lib/libtwo.so # armeabi, NOT armeabi-v7a!

Además, incluso si se especifican ambas ABI , armeabi y armeabi-v7a , (como se describe a continuación en la
sección Declaring Supported ABIs [Declaración de ABI admitidas]), Xamarin.Android creará el siguiente elemento
en . csproj :

<AndroidSupportedAbis>armeabi,armeabi-v7a</AndroidSupportedAbis>

Como consecuencia, armeabi libmonodroid.so se encontrará primero en el archivo .apk y armeabi


libmonodroid.so será el que se extraiga, aunque armeabi-v7a libmonodroid.so exista y esté optimizado para el
destino. Esta situación puede dar también lugar a extraños errores en tiempo de ejecución, dado que armeabi no
es seguro para SMP.
I n st a l a c i ó n d e b i b l i o t e c a s n a t i v a s: A n d r o i d 4 .0 .4 y v e r si o n e s p o st e r i o r e s

Android 4.0.4 cambia la lógica de extracción: se enumeran todas las bibliotecas nativas, se lee el nombre base del
archivo y luego se extrae la versión de la API principal o la ABI secundaria (la que sea que exista). Esto permite un
comportamiento de "combinación"; es decir, si tenemos un archivo .apk con el siguiente contenido:

lib/armeabi/libone.so
lib/armeabi/libtwo.so
lib/armeabi-v7a/libtwo.so

Tras la instalación, el directorio de biblioteca nativa contendrá:

$APP/lib/libone.so # from armeabi


$APP/lib/libtwo.so # from armeabi-v7a

Xamarin.Android y las ABI


Xamarin.Android admite las siguientes arquitecturas de 64 bits:
arm64-v8a
x86_64

NOTE
A partir de agosto de 2018 se necesitarán nuevas aplicaciones para alcanzar el nivel 26 de la API, y a partir de agosto de
2019 se requerirá que las aplicaciones proporcionen versiones de 64 bits además de la versión de 32 bits.

Xamarin.Android admite estas arquitecturas de 32 bits:


armeabi ^
armeabi-v7a
x86

NOTE
^ Desde Xamarin.Android 9.2, armeabi ya no se admite.
Xamarin.Android no proporciona actualmente compatibilidad con mips .
Declaración de las ABI admitidas
De forma predeterminada, Xamarin.Android adopta armeabi-v7a para las compilaciones de versión y
armeabi-v7a y x86 para las compilaciones de depuración. La compatibilidad con distintas ABI se puede
establecer mediante las opciones de proyecto de un proyecto de Xamarin.Android. En Visual Studio, esto se puede
establecer en la página Opciones de Android de Propiedades del proyecto, en la pestaña Avanzadas, tal y
como se muestra en la siguiente captura de pantalla:

En Visual Studio para Mac, las arquitecturas admitidas se pueden seleccionar en la página Compilación de
Android de Opciones del proyecto, en la pestaña Avanzadas, como se muestra en la siguiente captura de
pantalla:
Existen algunas situaciones en las que puede ser necesario declarar compatibilidad adicional con ABI, por ejemplo:
Al implementar la aplicación en un dispositivo x86 .
Al implementar la aplicación en un dispositivo armeabi-v7a para garantizar la seguridad para subprocesos.

Resumen
En este documento se tratan las distintas arquitecturas de CPU en las que se puede ejecutar una aplicación
Android. Se introduce la Interfaz binaria de aplicación y cómo se usa en Android para admitir arquitecturas de
CPU dispares. Luego, se pasa a describir cómo especificar la compatibilidad con ABI en una aplicación
Xamarin.Android y se resaltan los problemas que surgen al utilizar aplicaciones Xamarin.Android en un
dispositivo armeabi-v7a que está pensado solo para armeabi .

Vínculos relacionados
ABI para la arquitectura ARM (PDF )
NDK de Android
Problema 9089: Nexus One no carga ninguna biblioteca nativa de armeabi si hay al menos una biblioteca en
armeabi-v7a
Problema 24321: Galaxy Nexus 4.0.2 usa código nativo de armeabi cuando armeabi y armeabi-v7a se incluyen
en el apk.
Rendimiento de Xamarin.Android
01/08/2019 • 16 minutes to read • Edit Online

Existen muchas técnicas para aumentar el rendimiento de las aplicaciones compiladas con Xamarin.Android. En
conjunto, estas técnicas pueden reducir considerablemente la cantidad de trabajo que está realizando una CPU y
la cantidad de memoria consumida por una aplicación. En este artículo se describen y se explican estas técnicas.

Información general de rendimiento


El mal rendimiento de una aplicación se manifiesta de muchas formas. Puede hacer que parezca que una
aplicación deja de responder, puede ocasionar un desplazamiento lento y puede reducir la duración de la batería.
La optimización del rendimiento conlleva mucho más que la mera implementación de código eficaz. También debe
tenerse en cuenta la experiencia de rendimiento de la aplicación del usuario. Por ejemplo, asegurarse de que las
operaciones se ejecuten sin evitar que el usuario realice otras actividades puede ayudar a mejorar su experiencia.
Existen varias técnicas para aumentar el rendimiento, y la percepción de rendimiento, de las aplicaciones
compiladas con Xamarin.Android. Son los siguientes:
Optimizar las jerarquías de diseño
Optimizar las vistas de lista
Quitar controladores de eventos de actividades
Limitar la duración de los servicios
Liberar recursos cuando se notifique
Liberar recursos cuando se oculte la interfaz de usuario
Optimizar los recursos de imagen
Eliminar recursos de imágenes sin usar
Evitar la aritmética de punto flotante
Descartar cuadros de diálogo

NOTE
Antes de leer este artículo, debería leer Rendimiento multiplataforma, donde se explican técnicas no específicas de una
plataforma para mejorar el uso de memoria y el rendimiento de las aplicaciones compiladas con la plataforma Xamarin.

Optimizar las jerarquías de diseño


Cada diseño agregado a una aplicación exige inicialización, diseño y dibujo. El cálculo de diseño puede ser
consumir muchos recursos si se anidan instancias LinearLayout que usan el parámetro weight , ya que cada
elemento secundario se medirá dos veces. El empleo de instancias anidadas de LinearLayout puede dar lugar a
una jerarquía de vista profunda, lo que puede causar un mal rendimiento de los diseños que se inflan varias veces,
como en una ListView . Por lo tanto, es importante optimizar estos diseños, ya que las ventajas de rendimiento se
multiplicarán.
Por ejemplo, imagine un LinearLayout para una fila de vista de lista que tiene un icono, un título y una descripción.
El LinearLayout contendrá una ImageView y un LinearLayout vertical que contiene dos instancias TextView :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:padding="5dip">
<ImageView
android:id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_marginRight="5dip"
android:src="@drawable/icon" />
<LinearLayout
android:orientation="vertical"
android:layout_width="0dip"
android:layout_weight="1"
android:layout_height="fill_parent">
<TextView
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:gravity="center_vertical"
android:text="Mei tempor iuvaret ad." />
<TextView
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:singleLine="true"
android:ellipsize="marquee"
android:text="Lorem ipsum dolor sit amet." />
</LinearLayout>
</LinearLayout>

Este diseño tiene tres niveles de profundidad y desperdicia recursos si se infla para cada fila ListView . Pero se
puede mejorar si se reduce el diseño, como se muestra en el ejemplo de código siguiente:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:padding="5dip">
<ImageView
android:id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_alignParentTop="true"
android:layout_alignParentBottom="true"
android:layout_marginRight="5dip"
android:src="@drawable/icon" />
<TextView
android:id="@+id/secondLine"
android:layout_width="fill_parent"
android:layout_height="25dip"
android:layout_toRightOf="@id/icon"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:singleLine="true"
android:ellipsize="marquee"
android:text="Lorem ipsum dolor sit amet." />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/icon"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_above="@id/secondLine"
android:layout_alignWithParentIfMissing="true"
android:gravity="center_vertical"
android:text="Mei tempor iuvaret ad." />
</RelativeLayout>

La jerarquía de tres niveles anterior se ha reducido a una jerarquía de dos niveles y una sola instancia
RelativeLayout ha reemplazado a dos instancias LinearLayout . Se obtendrá un aumento considerable del
rendimiento cuando se infle el diseño de cada fila ListView .

Optimizar las vistas de lista


Los usuarios esperan un desplazamiento sin problemas y unos tiempos de carga rápidos para las instancias de
ListView . Pero el rendimiento del desplazamiento puede verse afectado si cada fila de vista de lista contiene
jerarquías de vista profundamente anidadas o si las filas de vista de lista contienen diseños complejos. Pero hay
técnicas que se pueden usar para evitar un mal rendimiento de ListView :
Vuelva a usar las vistas de fila. Para más información, vea Volver a usar vistas de fila.
Aligere los diseños, siempre que sea posible.
Almacene en caché el contenido de fila recuperado de un servicio web.
Evite el escalado de imagen.
Colectivamente, estas técnicas facilitan que las instancias de ListView se desplacen sin problemas.
Volver a usar vistas de fila
Al mostrar cientos de filas en una ListView , sería un desperdicio de memoria crear cientos de objetos View
cuando solo un pequeño número de ellos se muestra en pantalla a la vez. Así, se pueden cargar en la memoria solo
los objetos View visibles en las filas de la pantalla y cargar el contenido en estos objetos reutilizados. Esto evita la
creación de instancias de cientos de objetos adicionales, con lo que se ahorra tiempo y memoria.
Por lo tanto, cuando una fila desaparece de la pantalla, su vista puede colocarse en una cola para su reutilización,
como se muestra en el ejemplo de código siguiente:
public override View GetView(int position, View convertView, ViewGroup parent)
{
View view = convertView; // re-use an existing view, if one is supplied
if (view == null) // otherwise create a new one
view = context.LayoutInflater.Inflate(Android.Resource.Layout.SimpleListItem1, null);
// set view properties to reflect data for the given row
view.FindViewById<TextView>(Android.Resource.Id.Text1).Text = items[position];
// return the view, populated with data, for display
return view;
}

Cuando el usuario se desplaza, la ListView llama a la invalidación GetView para solicitar nuevas vistas para
mostrar: si está disponible, pasa una vista sin usar en el parámetro convertView . Si este valor es null , el código
crea una nueva instancia View , de lo contrario, se pueden volver a establecer y usar las propiedades convertView .
Para más información, vea Row View Re-Use (Reutilización de vista de lista) en Populating a ListView with Data
(Relleno de una ListView con datos).

Quitar controladores de eventos de actividades


Cuando se destruye una actividad en el runtime de Android, podría seguir activa en el runtime de Mono. Por lo
tanto, quite los controladores de eventos de los objetos externos de Activity.OnPause para evitar que el runtime
mantenga una referencia a una actividad que se ha destruido.
En una actividad, declare los controladores de eventos en el nivel de clase:

EventHandler<UpdatingEventArgs> service1UpdateHandler;

Luego implemente los controladores en la actividad, como en OnResume :

service1UpdateHandler = (object s, UpdatingEventArgs args) => {


this.RunOnUiThread (() => {
this.updateStatusText1.Text = args.Message;
});
};
App.Current.Service1.Updated += service1UpdateHandler;

Cuando la actividad sale del estado de ejecución, se llama a OnPause . En la implementación de OnPause , quite los
controladores de esta forma:

App.Current.Service1.Updated -= service1UpdateHandler;

Limitar la duración de los servicios


Cuando se inicia un servicio, Android mantiene el proceso de ese servicio en ejecución. Esto hace que el proceso
consuma muchos recursos, porque su memoria no se puede paginar ni usar en otro lugar. Dejar un servicio en
ejecución cuando no es necesario aumenta el riesgo de mal rendimiento de una aplicación debido a restricciones
de memoria. También puede hacer que el cambio entre aplicaciones sea menos eficaz, ya que reduce el número de
procesos que Android puede almacenar en caché.
Se puede limitar la duración de un servicio mediante un IntentService , que se cierra a sí mismo una vez
controlado el propósito que lo inició.

Liberar recursos cuando se notifique


Durante el ciclo de vida de la aplicación, la devolución de llamada OnTrimMemory envía una notificación si el
dispositivo tiene poca memoria. Esta devolución de llamada debería implementarse para escuchar las
notificaciones de nivel de memoria siguientes:
TrimMemoryRunningModerate : la aplicación podría querer liberar algunos recursos innecesarios.
TrimMemoryRunningLow : la aplicación debería liberar algunos recursos innecesarios.
TrimMemoryRunningCritical : la aplicación debería liberar tantos procesos no críticos como pudiera.

Además, cuando el proceso de la aplicación está almacenado en caché, la devolución de llamada OnTrimMemory
podría recibir las notificaciones de nivel de memoria siguientes:
TrimMemoryBackground : liberar recursos que se puedan compilar rápida y eficazmente si el usuario vuelve a la
aplicación.
TrimMemoryModerate : liberar recursos que puedan ayudar al sistema a mantener otros procesos almacenados en
caché para mejorar el rendimiento general.
TrimMemoryComplete : si no se recupera más memoria pronto, el proceso de la aplicación se cerrará.

Se debería responder a las notificaciones mediante la liberación de recursos según el nivel recibido.

Liberar recursos cuando se oculte la interfaz de usuario


Libere recursos usados por la interfaz de usuario de la aplicación cuando el usuario vaya a otra aplicación, ya que
eso puede aumentar considerablemente la capacidad de Android para procesos almacenados en caché, lo que a su
vez puede afectar a la calidad de la experiencia de usuario.
Para recibir una notificación cuando el usuario salga de la interfaz de usuario, implemente la devolución de
llamada OnTrimMemory en las clases Activity y escuche al nivel TrimMemoryUiHidden , que indica que la interfaz de
usuario está oculta. Esta notificación se recibirá solo cuando todos los componentes de la interfaz de usuario de la
aplicación estén ocultos. La liberación de recursos de la interfaz de usuario cuando se recibe esta notificación
garantiza que si el usuario vuelve desde otra actividad de la aplicación, los recursos de la interfaz de usuario
seguirán estando disponibles para reanudar rápidamente la actividad.

Optimizar los recursos de imagen


Las imágenes son uno de los recursos con más consumo usados por las aplicaciones y se suelen capturar en altas
resoluciones. Por lo tanto, al mostrar una imagen, hágalo en la resolución necesaria para la pantalla del dispositivo.
Si la imagen es de una resolución mayor que la pantalla, se debe reducir.
Para más información, vea Optimizar los recursos de imagen en la guía Rendimiento multiplataforma.

Eliminar recursos de imágenes sin usar


Para ahorrar consumo de memoria, se recomienda eliminar los recursos de imágenes grandes que ya no sean
necesarios. Es importante asegurarse de que las imágenes se eliminan correctamente. En lugar de usar una
invocación explícita .Dispose() , puede aprovechar las ventajas de las instrucciones using para garantizar el uso
correcto de objetos IDisposable .
Por ejemplo, la clase Bitmap implementa IDisposable . Si encapsula la creación de instancias de un objeto BitMap
en un bloque using , se asegurará de que se elimine correctamente al salir del bloque:

using (Bitmap smallPic = BitmapFactory.DecodeByteArray(smallImageByte, 0, smallImageByte.Length))


{
// Use the smallPic bit map here
}
Para más información sobre la liberación de recursos desechables, vea Release IDisposable Resources (Liberar los
recursos de IDisposable).

Evitar la aritmética de punto flotante


En los dispositivos Android, la aritmética de punto flotante es aproximadamente dos veces más lenta que la
aritmética de enteros. Por lo tanto, si es posible, reemplace la aritmética de punto flotante por la aritmética de
enteros. No obstante, no hay ninguna diferencia en cuanto a tiempo de ejecución entre la aritmética float y
double en el hardware reciente.

NOTE
Incluso para la aritmética de enteros, algunas CPU carecen de capacidades de división de hardware. Por lo tanto, la división
de enteros y las operaciones de módulo se suelen realizar en el software.

Cuadros de diálogo Dismiss (Descartar)


Cuando use la clase ProgressDialog (o cualquier cuadro de diálogo o alerta), en lugar de llamar al método Hide
cuando se complete la finalidad del cuadro de diálogo, llame al método Dismiss . De lo contrario, el cuadro de
diálogo permanecerá activo y perderá la actividad al mantener una referencia a ella.

Resumen
En este artículo se describen y se explican técnicas para aumentar el rendimiento de las aplicaciones compiladas
con Xamarin.Android. En conjunto, estas técnicas pueden reducir considerablemente la cantidad de trabajo que
está realizando una CPU y la cantidad de memoria consumida por una aplicación.

Vínculos relacionados
Rendimiento multiplataforma
Generar perfiles de aplicaciones Android
01/08/2019 • 7 minutes to read • Edit Online

Antes de implementar la aplicación en una tienda de aplicaciones, es importante que identifique y corrija los
cuellos de botella de rendimiento, los problemas de uso excesivo de memoria y el uso ineficaz de los recursos de
red. Para este propósito hay disponibles dos herramientas de generador de perfiles:
Generador de perfiles de Xamarin
Android Profiler en Android Studio
En esta guía se presenta el generador de perfiles de Xamarin y se proporciona información detallada sobre cómo
empezar a usar Android Profiler.

Generador de perfiles de Xamarin


Xamarin Profiler es una aplicación independiente integrada con Visual Studio y Visual Studio para Mac para
generar perfiles de aplicaciones Xamarin desde el IDE. Para obtener más información sobre el uso de Xamarin
Profiler, vea Xamarin Profiler.

NOTE
Debe ser un suscriptor de Visual Studio Enterprise para desbloquear la característica Xamarin Profiler en Visual Studio
Enterprise en Windows o Visual Studio para Mac.

Android Studio Profiler


Android Studio 3.0 y posterior incluye la herramienta Android Profiler. Puede usar Android Profiler para medir el
rendimiento de una aplicación Android de Xamarin compilada con Visual Studio – sin necesidad de disponer de
una licencia de Visual Studio Enterprise. Aun así, a diferencia de Xamarin Profiler, Android Profiler no está
integrado con Visual Studio y solo puede usarse para generar perfiles de un paquete de aplicaciones Android
(APK) que se haya compilado con antelación e importado en Android Profiler.
Iniciar una aplicación Android de Xamarin en Android Profiler
En los pasos siguientes se explica cómo iniciar una aplicación Android de Xamarin en la herramienta Android
Profiler de Android Studio. En las siguientes capturas de pantalla de ejemplo, se usa Android Profiler para
compilar la aplicación XamagonXuzzle de Xamarin.Forms y generar los perfiles:
1. En las opciones de compilación del proyecto de Android, deshabilite Use Shared Runtime (Usar tiempo de
ejecución compartido). Esto garantiza que el paquete de aplicaciones Android (APK) se compile sin una
dependencia en el tiempo de ejecución de Mono en tiempo de desarrollo compartido.
2. Compile la aplicación para la depuración e impleméntela en un dispositivo físico o un emulador. Esto hace
que se compile una versión de depuración del APK. Para el ejemplo de XamagonXuzzle, el APK
resultante se denomina com.companyname.XamagonXuzzle-Signed.apk.
3. Abra la carpeta del proyecto y vaya a bin/Debug. En esta carpeta, busque la versión Signed.apk de la
aplicación y cópiela en un lugar fácilmente accesible (como el escritorio). En la siguiente captura de pantalla,
se localiza el APK com.companyname.XamagonXuzzle-Signed.apk y se copia en el escritorio:

4. Inicie Android Studio y seleccione Profile or debug APK (Generar perfiles del APK o depurarlo):

5. En el cuadro de diálogo Select APK File (Seleccionar archivo APK), desplácese hasta el APK que ha
compilado y copiado anteriormente. Seleccione el APK y haga clic en Aceptar:
6. Android Studio cargará el APK y desensamblará classes.dex:

7. Una vez cargado el APK, Android Studio mostrará la siguiente pantalla de proyecto para el APK. Haga clic
con el botón derecho en el nombre de la aplicación en la vista de árbol a la izquierda y seleccione Open
Module Settings (Abrir configuración del módulo):

8. Vaya a Configuración del proyecto > Módulos, seleccione el nodo -Signed de la aplicación y haga clic
en <No SDK> (Sin SDK):
9. En el menú desplegable Module SDK (SDK de módulo), seleccione el nivel de Android SDK que se ha
usado para compilar la aplicación (en este ejemplo, se ha usado el nivel de API 26 para compilar
XamagonXuzzle):

Haga clic en Aplicar y Aceptar para guardar esta configuración.


10. Inicie el generador de perfiles desde el icono de la barra de herramientas:

11. Seleccione el destino de implementación para ejecutar la aplicación o generar perfiles y haga clic en
Aceptar. El destino de implementación puede ser un dispositivo físico o un dispositivo virtual que se
ejecute en un emulador. En este ejemplo, se usa un dispositivo Nexus 5X:

12. Cuando se inicie el generador de perfiles, tardará unos segundos en conectar con el dispositivo de
implementación y el proceso de aplicación. Mientras está instalando el APK, Android Profiler mostrará No
connected devices (No hay dispositivos conectados) y No debuggable processes (No hay procesos
depurables).
13. Tras unos segundos, Android Profiler completará la instalación del APK y lo iniciará. Además, mostrará el
nombre del dispositivo y el nombre del proceso de aplicación del que se van a generar perfiles (en este
ejemplo, LGE Nexus 5X y com.companyname.XamagonXuzzle, respectivamente):

14. Después de identificar el dispositivo y los procesos depurables, Android Profiler comienza la generación de
perfiles de la aplicación:

15. Si pulsa el botón Aleatorizar en XamagonXuzzle (que hace que desplace y aleatorice los iconos), verá que
el uso de la CPU aumentará durante el intervalo de aleatorización de la aplicación:

Uso de Android Profiler


En la documentación de Android Studio se incluye información detallada para usar Android Profiler. Los temas
siguientes pueden ser de interés para desarrolladores de Android de Xamarin:
CPU Profiler: explica cómo inspeccionar la actividad de subprocesos y el uso de CPU de la aplicación en
tiempo real.
Memory Profiler: muestra un gráfico en tiempo real del uso de memoria de la aplicación e incluye un botón
para registrar las asignaciones de memoria para el análisis.
Network Profiler: muestra la actividad de red en tiempo real de los datos que la aplicación envía y recibe.
Preparar una aplicación para su lanzamiento
11/07/2019 • 35 minutes to read • Edit Online

Después de haber codificado y probado una aplicación, es necesario preparar un paquete para la distribución. La
primera tarea en la preparación de este paquete es compilar la aplicación para el lanzamiento, lo que implica
principalmente establecer algunos atributos de la aplicación.
Para compilar la aplicación para lanzamiento, siga estos pasos:
Especificar el icono de la aplicación: cada aplicación de Xamarin.Android debe tener un icono de
aplicación especificado. Aunque técnicamente no es necesario, algunos mercados lo requieren, como
Google Play.
Versión de la aplicación: este paso consiste en inicializar o actualizar la información de control de
versiones. Esto es importante para las actualizaciones futuras de la aplicación y para asegurarse de que los
usuarios sean conscientes de qué versión de la aplicación han instalado.
Reducir el APK: se puede reducir considerablemente el tamaño del APK final si se usa el enlazador de
Xamarin.Android en el código administrado y ProGuard en el código de bytes de Java.
Proteger la aplicación: impida que los usuarios o los atacantes depuren, alteren o usen técnicas de
ingeniería inversa en la aplicación. Para ello, deshabilite la depuración, ofusque el código administrado,
agregue protección contra la depuración y la alteración y use compilación nativa.
Establecer las propiedades de empaquetado: las propiedades de empaquetado controlan la creación
del paquete de aplicaciones Android (APK). En este paso se optimiza el APK, se protegen sus activos y se
modulariza el empaquetado según sea necesario.
Compilar: en este paso se compilan el código y los activos para comprobar que se compila en el modo de
versión.
Archivar para la publicación: en este paso se compila la aplicación y se coloca en un archivo para la firma
y la publicación.
Cada uno de estos pasos se describe con más detalle a continuación.

Especificar el icono de la aplicación


Se recomienda encarecidamente que cada aplicación de Xamarin.Android especifique un icono de aplicación.
Algunos mercados de aplicaciones no permitirán que una aplicación de Android se publique sin uno. La propiedad
Icon del atributo Application se usa para especificar el icono de la aplicación para un proyecto de
Xamarin.Android.
Visual Studio
Visual Studio para Mac
En Visual Studio 2017 y versiones posteriores, especifique el icono de aplicación en la sección Manifiesto de
Android de las Propiedades del proyecto, como se muestra en la siguiente captura de pantalla:
En estos ejemplos, @drawable/icon hace referencia a un archivo de icono que se encuentra en
Resources/drawable/icon.png (tenga en cuenta que la extensión .png no está incluida en el nombre del
recurso). Este atributo se puede declarar también en el archivo Properties\AssemblyInfo.cs, como se muestra
en este fragmento de código de ejemplo:

[assembly: Application(Icon = "@drawable/icon")]

Normalmente, using Android.App se declara en la parte superior de AssemblyInfo.cs (el espacio de nombres del
atributo Application es Android.App ); sin embargo, puede que necesite agregar esta instrucción using si todavía
no está presente.

Versión de la aplicación
El control de versiones es importante para el mantenimiento y la distribución de aplicaciones de Android. Sin
ningún tipo de control de versiones, resulta difícil determinar si una aplicación ha de actualizarse o cómo ha de
hacerse. Para ayudar con el control de versiones, Android reconoce dos tipos diferentes de información:
Número de versión: valor entero (usado internamente por la aplicación y Android) que representa la
versión de la aplicación. La mayoría de las aplicaciones empieza con este valor establecido en 1, que luego
se incrementa con cada versión. Este valor no tiene relación ni afinidad con el atributo de nombre de
versión (ver abajo). Las aplicaciones y los servicios de publicación no deberían mostrar este valor a los
usuarios. Este valor se almacena en el archivo AndroidManifest.xml como android:versionCode .
Nombre de versión: cadena que solo se usa para comunicar información al usuario sobre la versión de la
aplicación (según esté instalada en un dispositivo concreto). El nombre de versión está pensado para
mostrarse a los usuarios o en Google Play. Android no usa esta cadena internamente. El nombre de versión
puede ser cualquier valor de cadena que ayude a un usuario a identificar la versión instalada en el
dispositivo. Este valor se almacena en el archivo AndroidManifest.xml como android:versionName .
Visual Studio
Visual Studio para Mac
En Visual Studio, estos valores se pueden establecer en la sección Manifiesto de Android de las Propiedades
del proyecto, como se muestra en la siguiente captura de pantalla:
Reducir el APK
Es posible reducir el tamaño de los APK de Xamarin.Android. Para ello, use el enlazador de Xamarin.Android, que
quita el código administrado innecesario, y la herramienta ProGuard de Android SDK, que elimina el código de
bytes de Java que no se usa. El proceso de compilación usa primero el enlazador de Xamarin.Android para
optimizar la aplicación a nivel de código administrado (C#) y, después, usa ProGuard (si está habilitado) para
optimizar el APK a nivel de código de bytes de Java.
Configurar el enlazador
El modo de versión desactiva el tiempo de ejecución compartido y activa la vinculación, de modo que la aplicación
solo envía las partes de Xamarin.Android necesarias en tiempo de ejecución. El enlazador de Xamarin.Android usa
el análisis estático para determinar qué ensamblados, tipos y miembros de tipo se usan o a los que hace referencia
una aplicación de Xamarin.Android. Después, el enlazador descarta todos los ensamblados, tipos y miembros que
no se usan (o a los que no se hace referencia). De este modo, se puede producir una reducción significativa del
tamaño del paquete. Por ejemplo, tenga en cuenta el ejemplo de HelloWorld, que experimenta una reducción del
83 % en el tamaño final de su APK:
Configuración: Ninguna – Tamaño de Xamarin.Android 4.2.5 = 17,4 MB.
Configuración: Solo ensamblados de SDK – Tamaño de Xamarin.Android 4.2.5 = 3,0 MB.
Visual Studio
Visual Studio para Mac
Establezca las opciones del enlazador en la sección Opciones de Android de las Propiedades del proyecto:

El menú desplegable Linking (Vinculación) proporciona las siguientes opciones para controlar el enlazador:
Ninguno: esta opción desactiva el enlazador, por lo que no se realizará la vinculación.
SDK Assemblies Only (Solo ensamblados del SDK): esta opción vinculará solo los ensamblados que
requiere Xamarin.Android. No se vincularán otros ensamblados.
Sdk and User Assemblies (Ensamblados del SDK y del usuario): se vincularán todos los ensamblados que
requiere la aplicación, y no solo los que requiere Xamarin.Android.
La vinculación puede producir algunos efectos secundarios no deseados, por lo que es importante que la
aplicación se vuelva a probar en el modo de versión en un dispositivo físico.
ProGuard
ProGuard es una herramienta de Android SDK que vincula y oculta el código de Java. ProGuard normalmente se
utiliza para crear aplicaciones más pequeñas reduciendo el tamaño de las grandes bibliotecas incluidas, como
Google Play Services, en el APK. ProGuard elimina el código de bytes de Java que no se utiliza, de modo que la
aplicación resultante es más pequeña. Por ejemplo, el uso de ProGuard en pequeñas aplicaciones de
Xamarin.Android suele llegar a reducir su tamaño hasta en un 24 %, mientras que el uso de ProGuard en
aplicaciones más grandes con varias dependencias de bibliotecas suele alcanzar una reducción de tamaño aún
mayor.
ProGuard no es una alternativa al enlazador Xamarin.Android. El enlazador de Xamarin.Android vincula el código
administrado, mientras que ProGuard vincula el código de bytes de Java. El proceso de compilación usa, en
primer lugar, el enlazador de Xamarin.Android para optimizar el código administrado (C#) en la aplicación y,
después, usa ProGuard (si está habilitado) para optimizar el APK a nivel del código de bytes de Java.
Cuando se activa Habilitar ProGuard, Xamarin.Android ejecuta la herramienta ProGuard en el APK resultante.
Se genera un archivo de configuración de ProGuard que ProGuard usa en tiempo de compilación.
Xamarin.Android también admite las acciones de compilación personalizadas de ProguardConfiguration. Puede
agregar un archivo de configuración de ProGuard personalizado al proyecto. Para ello, haga clic en él con el botón
derecho y selecciónelo como una acción de compilación, tal como se muestra en este ejemplo:
Visual Studio
Visual Studio para Mac

ProGuard está deshabilitado de forma predeterminada. La opción Habilitar ProGuard solo está disponible
cuando el proyecto se establece en modo de Lanzamiento. Se omiten todas las acciones de compilación de
ProGuard a menos que Enable ProGuard (Habilitar ProGuard) esté activado. La configuración de ProGuard de
Xamarin.Android no ofusca el APK y no es posible habilitar la ofuscación, ni siquiera con archivos de
configuración personalizados. Si quiere usar la ofuscación, consulte Application Protection with Dotfuscator
(Protección de aplicaciones con Dotfuscator).
Para obtener más información sobre cómo usar la herramienta ProGuard, consulte ProGuard.

Proteger la aplicación
Deshabilitar la depuración
Durante el desarrollo de una aplicación Android, la depuración se realiza mediante el uso del Protocolo de
conexión de depuración de Java (JDWP ). Se trata de una tecnología que permite que herramientas como adb se
comuniquen con una JVM para fines de depuración. JDWP está activado de forma predeterminada para las
compilaciones de depuración de una aplicación Xamarin.Android. Aunque JDWP es importante durante el
desarrollo, puede suponer un problema de seguridad para las aplicaciones lanzadas.

IMPORTANT
Deshabilite siempre el estado de depuración en una aplicación lanzada cuando sea posible (a través de JDWP) para obtener
acceso completo al proceso de Java y ejecutar un código arbitrario en el contexto de la aplicación si no se deshabilita este
estado de depuración.

El manifiesto de Android contiene el atributo android:debuggable , que controla si se puede depurar la aplicación o
no. Se considera una buena práctica establecer el atributo android:debuggable en false . La manera más sencilla
de hacerlo es mediante la adición de una instrucción de compilación condicional en AssemblyInfo.cs:

#if DEBUG
[assembly: Application(Debuggable=true)]
#else
[assembly: Application(Debuggable=false)]
#endif

Tenga en cuenta que las compilaciones de depuración establecen automáticamente algunos permisos para que la
depuración sea más sencilla (como Internet y ReadExternalStorage). Sin embargo, las compilaciones de versión
solo utilizan los permisos que usted configure explícitamente. Si al cambiar a la compilación de versión, la
aplicación pierde un permiso que estaba disponible en la compilación de depuración, compruebe que ha
habilitado explícitamente este permiso en la lista Permisos necesarios como se describe en Permisos.
Protección de aplicaciones con Dotfuscator
Visual Studio
Visual Studio para Mac
Incluso con la depuración deshabilitada, los atacantes siguen teniendo la posibilidad de volver a empaquetar una
aplicación, así como de agregar o quitar opciones de configuración o permisos. Esto les permite usar técnicas de
ingeniería inversa en la aplicación, depurarla o alterarla. Puede usar Dotfuscator Community Edition (CE ) para
ofuscar el código administrado e inyectar código de detección de estado de seguridad en tiempo de ejecución en
una aplicación de Xamarin.Android en tiempo de compilación para detectar si la aplicación se está ejecutando en
un dispositivo liberado y reaccionar en consecuencia.
Dotfuscator CE está incluido con Visual Studio 2017. Para usar Dotfuscator, haga clic en Herramientas >
PreEmptive Protection - Dotfuscator.
Para configurar Dotfuscator CE, consulte Using Dotfuscator Community Edition with Xamarin (Usar Dotfuscator
Community Edition con Xamarin). Una vez que lo haya configurado, Dotfuscator CE protegerá automáticamente
todas las compilaciones que cree.
Empaquetar ensamblados en código nativo
Cuando esta opción está habilitada, los ensamblados se agrupan en una biblioteca compartida nativa. Esta opción
garantiza la seguridad del código y protege los ensamblados administrados incrustándolos en archivos binarios
nativos.
Esta opción requiere una licencia empresarial y solo está disponible cuando está deshabilitada la opción Use Fast
Deployment (Utilizar la implementación rápida). La opción Bundle assemblies into native code
(Agrupar los ensamblados en el código nativo) está deshabilitada de forma predeterminada.
Tenga en cuenta que la opción Bundle into Native Code (Agrupar en código nativo) no implica que los
ensamblados se compilen en código nativo. No es posible utilizar Compilación AOT para compilar ensamblados
en código nativo. Actualmente solo es una función experimental y no está destinada a la tareas de producción.
Compilación AOT
La opción compilación AOT (de la página Propiedades de empaquetado) habilita la compilación Ahead Of Time
(AOT) de los ensamblados. Cuando esta opción está habilitada, la sobrecarga de inicio Just-In-Time (JIT) se
minimiza al precompilar ensamblados antes del tiempo de ejecución. El código nativo resultante se incluye en el
APK junto con los ensamblados sin compilar. Esto da como resultado un tiempo de inicio de la aplicación más
corto, pero a costa de tamaños APK ligeramente más grandes.
La opción compilación AOT necesita una licencia de Enterprise o superior. Compilación AOT solo está
disponible cuando el proyecto se configura para el modo de versión, y está deshabilitado de manera
predeterminada. Para obtener más información sobre la compilación AOT, consulte AOT.
Compilador de optimización de LLVM
El Compilador de optimización de LLVM creará un código compilado más pequeño y rápido y convertirá
ensamblados compilados mediante AOT en código nativo, pero a costa de tiempos de compilación más lentos. El
compilador de LLVM está deshabilitado de manera predeterminada. Para usar el compilador de LLVM, es
necesario habilitar primero la opción Compilación de AOT en la página Propiedades de empaquetado.

NOTE
La opción Compilador de optimización de LLVM necesita una licencia Enterprise.

Establecer las propiedades de empaquetado


Visual Studio
Visual Studio para Mac
Las propiedades de empaquetado se pueden establecer en la sección Android Options (Opciones de Android) de
las Properties (Propiedades) del proyecto, como se muestra en la siguiente captura de pantalla:
Muchas de estas propiedades, como Use Shared Runtime (Usar tiempo de ejecución compartido) y Use Fast
Deployment (Usar implementación rápida), están pensadas para el modo de depuración. Pero cuando la
aplicación está configurada para el modo de versión, hay otras opciones que determinan cómo se optimiza la
aplicación para el tamaño y la velocidad de ejecución, cómo se protege contra la alteración y cómo puede
empaquetarse para admitir distintas arquitecturas y restricciones de tamaño.
Especificar arquitecturas compatibles
Al preparar una aplicación Xamarin.Android para publicarla, es necesario especificar las arquitecturas de CPU que
se admiten. Un APK único puede contener código máquina para admitir varias arquitecturas diferentes. Consulte
Arquitecturas de CPU para obtener más información sobre la compatibilidad con varias arquitecturas de CPU.
Generar un paquete (.APK ) por ABI seleccionado
Cuando esta opción está habilitada, se creará un APK para cada uno de los ABI admitidos (seleccionados en la
pestaña Opciones avanzadas, como se describe en Arquitecturas de CPU ) en lugar de un único APK grande
para todos los ABI que se admiten. Esta opción solo está disponible cuando el proyecto se configura para el modo
de versión, y está deshabilitado de manera predeterminada.
Multi-Dex
Cuando la opción Habilitar Multi-Dex está habilitada, se usan herramientas del SDK de Android para omitir el
límite de 65 000 métodos del formato de archivo .dex. La limitación de 65 000 métodos se basa en el número de
métodos de Java a los que una aplicación hace referencia (incluidos los de las bibliotecas de las que depende la
aplicación) – no se basa en el número de métodos que se escriben en el código fuente. Si una aplicación solo
define algunos métodos pero usa muchos (o bibliotecas grandes), es posible que se supere el límite de 65 000.
Es posible que una aplicación no use todos los métodos de todas las bibliotecas a los que se haga referencia, de
modo que es posible que una herramienta como ProGuard (vea más arriba) pueda eliminar del código los
métodos que no se usen. La práctica recomendada es habilitar Habilitar Multi-Dex solo si es absolutamente
necesario, por ejemplo, si aplicación aún hace referencia a más de 65 000 métodos de Java incluso después de
usar ProGuard.
Para más información sobre Multi-Dex, vea Configurar aplicaciones con más de 64 000 métodos.

Compile
Visual Studio
Visual Studio para Mac
Una vez que haya completado todos los pasos anteriores, la aplicación estará lista para la compilación. Seleccione
Compilar > Recompilar solución para comprobar que se compila correctamente en el modo de versión. Tenga
en cuenta que en este paso todavía no se produce un APK.
En Signing the App Package (Firmar el paquete de aplicación) se describe con más detalle el proceso de
empaquetar y firmar.

Archivo para la publicación


Visual Studio
Visual Studio para Mac
Para empezar el proceso de publicación, haga clic con el botón derecho en el proyecto en el Explorador de
soluciones y seleccione el elemento de menú contextual Archivo…:

La opción Archivo… inicia Archive Manager y comienza el proceso de archivado del paquete de aplicaciones,
como se muestra en esta captura de pantalla:

Otra forma de crear un archivo consiste en hacer clic con el botón derecho en la solución en el Explorador de
soluciones y seleccionar Archivar todo…, con lo que se compila la solución y se archivan todos los proyectos de
Xamarin que pueden generar un archivo:
Tanto la opción Archivo como la opción Archivar todo inician automáticamente Archive Manager. Para iniciar
Archive Manager directamente, haga clic en el elemento de menú Herramientas > Archive Manager…:

Puede ver los archivos de la solución en cualquier momento. Para ello, haga clic con el botón derecho en el nodo
Solución y seleccione Ver archivos:

Archive Manager
Archive Manager está formado por una lista de soluciones, una lista de archivos y un panel de detalles:
En la lista de soluciones se muestran todas las soluciones que tienen como mínimo un proyecto archivado. En la
lista de soluciones se incluyen las secciones siguientes:
Solución actual: muestra la solución actual. Tenga en cuenta que esta área puede estar vacía si la solución
actual no tiene ningún archivo.
Todos los archivos: muestra todas las soluciones que tienen un archivo.
Cuadro de texto de Búsqueda (en la parte superior): filtra las soluciones incluidas en la lista Todos los
archivos según la cadena de búsqueda especificada en el cuadro de texto.
En la lista de archivos se muestra una lista de todos los archivos de la solución seleccionada. En la lista de
archivos se incluyen las secciones siguientes:
Nombre de la solución seleccionada: muestra el nombre de la solución seleccionada en la lista de
soluciones. Toda la información que se muestra en la lista de archivos hace referencia a esta solución
seleccionada.
Filtro de plataformas: este campo permite filtrar archivos por tipo de plataforma (por ejemplo, iOS o
Android).
Elementos de archivo: muestra los archivos de la solución seleccionada. Cada elemento de esta lista incluye
el nombre del proyecto, la fecha de creación y la plataforma. También puede incluir información adicional,
como el progreso cuando se está archivando o publicando un elemento.
En el panel de detalles se muestra información adicional sobre cada archivo. El panel también permite al usuario
iniciar el flujo de trabajo de distribución o abrir la carpeta donde se ha creado la distribución. En la sección
Comentarios de la compilación se pueden incluir comentarios de compilación en el archivo.
Distribución
Cuando una versión archivada de la aplicación esté lista para la publicación, seleccione el archivo en Archive
Manager y haga clic en el botón Distribuir…:
En el cuadro de diálogo Canal de distribución se muestra información sobre la aplicación, una indicación del
progreso del flujo de trabajo de distribución y las opciones de canales de distribución. En la primera ejecución, se
ofrecen dos opciones:

Es posible elegir uno de los siguientes canales de distribución:


Ad hoc: guarda un APK firmado en el disco que se puede instalar como prueba en dispositivos Android.
Vaya a Signing the App Package (Firmar el paquete de aplicación) para obtener información sobre cómo
crear una identidad de firma de Android, crear un certificado de firma para aplicaciones de Android y
publicar una versión ad hoc de la aplicación en disco. Esta es una buena forma de crear un APK para
realizar pruebas.
Google Play: publica un APK firmado en Google Play. Vaya a Publicación en Google Play para obtener
información sobre cómo firmar y publicar un APK en Google Play Store.

Vínculos relacionados
Dispositivos de varios núcleos y Xamarin.Android
Arquitecturas de CPU
AOT
Reducción del código y los recursos
Configuración de aplicaciones con más de 64 000 métodos
ProGuard
11/07/2019 • 16 minutes to read • Edit Online

ProGuard de Xamarin.Android es un reductor, optimizador, y comprobador previo de archivos de clase Java.


Permite detectar y quitar el código sin usar, así como analizar y optimizar el código de bytes. En esta guía se
explica cómo funciona ProGuard, cómo se habilita en el proyecto y cómo se configura. También se proporcionan
varios ejemplos de configuraciones de ProGuard.

Información general
ProGuard detecta y quita las clases, los campos, los métodos y los atributos sin usar de la aplicación
empaquetada. Incluso puede hacer lo mismo en las bibliotecas a las que se hace referencia, lo que puede ayudar a
evitar el límite de 64 000 referencias. La herramienta ProGuard de Android SDK también optimiza el código de
bytes y quita las instrucciones de código sin usar. ProGuard lee los archivos JAR de entrada, los reduce, los
optimiza y los comprueba previamente y, después, escribe los resultados en uno o varios archivos JAR de salida.
ProGuard procesa los APK de entrada mediante los pasos siguientes:
1. Paso de reducción – ProGuard determina de forma recursiva qué clases y miembros de clases se usan.
Todas las demás clases y miembros de clases se descartan.
2. Paso de optimización – ProGuard optimiza todavía más el código. Entre otras optimizaciones, se pueden
hacer privadas, estáticas o finales las clases y los métodos que no son puntos de entrada, se pueden quitar
los parámetros sin usar y se pueden insertar algunos métodos.
3. Paso de ofuscación: en el desarrollo nativo de Android, ProGuard cambia el nombre de las clases y los
miembros de clases que no son puntos de entrada. La conservación de los puntos de entrada garantiza que
todavía se pueda tener acceso a ellos mediante sus nombres originales. Sin embargo, este paso no es
compatible con Xamarin.Android, dado que la aplicación se compila en lenguaje intermedio (IL ).
4. Paso de comprobación previa – se realizan comprobaciones en los códigos de bytes de Java antes del
tiempo de ejecución y se anotan los archivos de clase para que pueda aprovecharlo la máquina virtual Java.
Este es el único paso que no tiene que conocer los puntos de entrada.
Cada uno de estos pasos es opcional. Como se explicará en la sección siguiente, ProGuard Xamarin.Android solo
usa un subconjunto de estos pasos.

ProGuard en Xamarin.Android
La configuración de ProGuard de Xamarin.Android no ofusca el APK. De hecho, no es posible habilitar la
ofuscación mediante ProGuard (ni siquiera mediante el uso de archivos de configuración personalizados). Por lo
tanto, ProGuard de Xamarin.Android solo realiza los pasos de reducción y optimización:
Antes de usar ProGuard, es importante saber cómo funciona dentro del proceso de compilación de
Xamarin.Android . Este proceso usa dos pasos independientes:

1. Enlazador de Xamarin Android


2. ProGuard
Cada uno de estos pasos se describe a continuación.
Paso de enlazador
El enlazador de Xamarin.Android emplea el análisis estático de la aplicación para determinar lo siguiente:
Qué ensamblados se usan realmente.
Qué tipos se usan realmente.
Qué miembros se usan realmente.
El enlazador siempre se ejecutará antes del paso de ProGuard. Por este motivo, el enlazador puede eliminar un
ensamblado, un tipo o un miembro en el que cabría esperar que se ejecutase ProGuard. (Para obtener más
información sobre la vinculación en Xamarin.Android, consulte Linking on Android (Vinculación en Android)).
Paso de ProGuard
Una vez que haya finalizado correctamente el paso de enlazador, ProGuard se ejecuta para quitar el código de
bytes de Java sin usar. Este es el paso que optimiza el APK.

Uso de ProGuard
Para usar ProGuard en el proyecto de aplicación, primero debe habilitar ProGuard. Después, puede dejar que el
proceso de compilación de Xamarin.Android use un archivo de configuración de ProGuard predeterminado, o
bien puede crear su propio archivo de configuración personalizado para que lo use ProGuard.
Habilitación de ProGuard
Use los pasos siguientes para habilitar ProGuard en el proyecto de aplicación:
1. Asegúrese de que el proyecto está establecido en la configuración de lanzamiento (esto es importante
porque el enlazador debe ejecutarse para que se pueda ejecutar ProGuard):

2. Habilite ProGuard. Para ello, active la opción Habilitar ProGuard en la pestaña Empaquetado de
Propiedades > Opciones de Android:

Para la mayoría de las aplicaciones de Xamarin.Android, el archivo de configuración de ProGuard predeterminado


que Xamarin.Android proporciona será suficiente para quitar (exclusivamente) todo el código sin usar. Para ver la
configuración de ProGuard predeterminada, abra el archivo que se encuentra en
obj\Release\proguard\proguard_xamarin.cfg. En la sección siguiente se describe cómo crear un archivo de
configuración de ProGuard personalizado.
Personalización de ProGuard
Opcionalmente, puede agregar un archivo de configuración de ProGuard personalizado para ejercer más control
sobre las herramientas de ProGuard. Por ejemplo, tal vez le interese indicarle a ProGuard de manera explícita qué
clases debe conservar. Para ello, cree un archivo .cfg y aplique la acción de compilación ProGuardConfiguration del
panel de Propiedades del Explorador de soluciones:
Tenga en cuenta que este archivo de configuración no reemplaza al archivo proguard_xamarin.cfg de
Xamarin.Android, ya que ProGuard usa ambos.
En el ejemplo siguiente se muestra un archivo de configuración de ProGuard típico:

# This is Xamarin-specific (and enhanced) configuration.

-dontobfuscate

-keep class mono.MonoRuntimeProvider { *; <init>(...); }


-keep class mono.MonoPackageManager { *; <init>(...); }
-keep class mono.MonoPackageManager_Resources { *; <init>(...); }
-keep class mono.android.** { *; <init>(...); }
-keep class mono.java.** { *; <init>(...); }
-keep class mono.javax.** { *; <init>(...); }
-keep class opentk.platform.android.AndroidGameView { *; <init>(...); }
-keep class opentk.GameViewBase { *; <init>(...); }
-keep class opentk_1_0.platform.android.AndroidGameView { *; <init>(...); }
-keep class opentk_1_0.GameViewBase { *; <init>(...); }

-keep class android.runtime.** { <init>(***); }


-keep class assembly_mono_android.android.runtime.** { <init>(***); }
# hash for android.runtime and assembly_mono_android.android.runtime.
-keep class md52ce486a14f4bcd95899665e9d932190b.** { *; <init>(...); }
-keepclassmembers class md52ce486a14f4bcd95899665e9d932190b.** { *; <init>(...); }

# Android's template misses fluent setters...


-keepclassmembers class * extends android.view.View {
*** set*(***);
}

# also misses those inflated custom layout stuff from xml...


-keepclassmembers class * extends android.view.View {
<init>(android.content.Context,android.util.AttributeSet);
<init>(android.content.Context,android.util.AttributeSet,int);
}

En algunos casos, ProGuard no puede analizar correctamente la aplicación y podría eliminar código que la
aplicación realmente necesita. Si esto ocurre, puede agregar una línea -keep al archivo de configuración de
ProGuard personalizado:

-keep public class MyClass


En este ejemplo, se establece MyClass en el nombre real de la clase que se quiere que ProGuard omita.
También puede registrar sus propios nombres con anotaciones [Register] y usar estos nombres para
personalizar las reglas de ProGuard. Puede registrar nombres para Adapters, Views, BroadcastReceivers, Services,
ContentProviders, Activities y Fragments. Para más información sobre cómo usar el atributo personalizado
[Register] , consulte Working with JNI ( Uso de JNI ).

Opciones de ProGuard
ProGuard ofrece una serie de opciones que puede configurar para proporcionar un mayor control sobre su
funcionamiento. En el manual de ProGuard se proporciona documentación de referencia completa sobre el uso de
ProGuard.
Xamarin.Android admite las siguientes opciones de ProGuard:
Opciones de entrada/salida
Opciones de conservación
Opciones de reducción
Opciones generales
Rutas de clase
Nombres de archivo
Filtros de archivo
Filtros
Información general sobre las opciones Keep

Modificadores de las opciones de conservación


Especificaciones de clase
Xamarin.Android omite las opciones siguientes:
Opciones de optimización
Opciones de ofuscación
Opciones de comprobación previa

ProGuard y Android Nougat


Si intenta usar ProGuard con Android 7.0 o versiones posteriores, debe descargar una versión más reciente de
ProGuard, ya que Android SDK no incluye una versión nueva que sea compatible con JDK 1.8.
Puede usar este paquete NuGet para instalar una versión más reciente de proguard.jar . Para obtener más
información sobre cómo actualizar el archivo proguard.jar predeterminado de Android SDK, consulte esta
explicación de Stack Overflow.
Encontrará todas las versiones de ProGuard en la página de SourceForge.

Ejemplo de configuraciones de ProGuard


A continuación se muestran dos archivos de configuración de ProGuard de ejemplo. Tenga en cuenta que, en
estos casos, el proceso de compilación de Xamarin.Android proporcionará los archivos JAR de entrada, salida y
biblioteca. Por lo tanto, puede centrarse en otras opciones como -keep .
Actividad simple de Android
En el ejemplo siguiente se ilustra la configuración de una sencilla actividad de Android:

-injars bin/classes
-outjars bin/classes-processed.jar
-libraryjars /usr/local/java/android-sdk/platforms/android-9/android.jar

-dontpreverify
-repackageclasses ''
-allowaccessmodification
-optimizations !code/simplification/arithmetic

-keep public class mypackage.MyActivity

Aplicación completa de Android


En el ejemplo siguiente se ilustra la configuración de una aplicación completa de Android:

-injars bin/classes
-injars libs
-outjars bin/classes-processed.jar
-libraryjars /usr/local/java/android-sdk/platforms/android-9/android.jar

-dontpreverify
-repackageclasses ''
-allowaccessmodification
-optimizations !code/simplification/arithmetic
-keepattributes *Annotation*

-keep public class * extends android.app.Activity


-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider

-keep public class * extends android.view.View {


public <init>(android.content.Context);
public <init>(android.content.Context, android.util.AttributeSet);
public <init>(android.content.Context, android.util.AttributeSet, int);
public void set*(...);
}

-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
}

-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}

-keepclassmembers class * implements android.os.Parcelable {


static android.os.Parcelable$Creator CREATOR;
}

-keepclassmembers class **.R$* {


public static <fields>;
}

ProGuard y el proceso de compilación de Xamarin.Android


En las secciones siguientes se explica cómo se ejecuta ProGuard durante una compilación de lanzamiento de
Xamarin.Android.
¿Qué comando ejecuta ProGuard?
ProGuard es simplemente un archivo .jar que se proporciona con Android SDK. Por lo tanto, se invoca en un
comando:

java -jar proguard.jar options ...

La tarea ProGuard
La tarea ProGuard se encuentra dentro del ensamblado Xamarin.Android.Build.Tasks.dll. Forma parte del
destino _CompileToDalvikWithDx , que a su vez forma parte del destino _CompileDex .
En la lista siguiente se proporciona un ejemplo de los parámetros predeterminados que se generan después de
crear un proyecto mediante Archivo > Nuevo proyecto:

ProGuardJarPath = C:\Android\android-sdk\tools\proguard\lib\proguard.jar
AndroidSdkDirectory = C:\Android\android-sdk\
JavaToolPath = C:\Program Files (x86)\Java\jdk1.8.0_92\\bin
ProGuardToolPath = C:\Android\android-sdk\tools\proguard\
JavaPlatformJarPath = C:\Android\android-sdk\platforms\android-25\android.jar
ClassesOutputDirectory = obj\Release\android\bin\classes
AcwMapFile = obj\Release\acw-map.txt
ProGuardCommonXamarinConfiguration = obj\Release\proguard\proguard_xamarin.cfg
ProGuardGeneratedReferenceConfiguration = obj\Release\proguard\proguard_project_references.cfg
ProGuardGeneratedApplicationConfiguration = obj\Release\proguard\proguard_project_primary.cfg
ProGuardConfigurationFiles

{sdk.dir}tools\proguard\proguard-android.txt;
{intermediate.common.xamarin};
{intermediate.references};
{intermediate.application};
;

JavaLibrariesToEmbed = C:\Program Files (x86)\Reference


Assemblies\Microsoft\Framework\MonoAndroid\v7.0\mono.android.jar
ProGuardJarInput = obj\Release\proguard\__proguard_input__.jar
ProGuardJarOutput = obj\Release\proguard\__proguard_output__.jar
DumpOutput = obj\Release\proguard\dump.txt
PrintSeedsOutput = obj\Release\proguard\seeds.txt
PrintUsageOutput = obj\Release\proguard\usage.txt
PrintMappingOutput = obj\Release\proguard\mapping.txt

En el ejemplo siguiente se muestra un comando de ProGuard típico que se ejecuta desde el IDE:

C:\Program Files (x86)\Java\jdk1.8.0_92\\bin\java.exe -jar C:\Android\android-


sdk\tools\proguard\lib\proguard.jar -include obj\Release\proguard\proguard_xamarin.cfg -include
obj\Release\proguard\proguard_project_references.cfg -include
obj\Release\proguard\proguard_project_primary.cfg "-injars
'obj\Release\proguard\__proguard_input__.jar';'C:\Program Files (x86)\Reference
Assemblies\Microsoft\Framework\MonoAndroid\v7.0\mono.android.jar'" "-libraryjars 'C:\Android\android-
sdk\platforms\android-25\android.jar'" -outjars "obj\Release\proguard\__proguard_output__.jar" -optimizations
!code/allocation/variable

Solución de problemas
Problemas de archivos
Cuando ProGuard lee su archivo de configuración, puede aparecer el mensaje de error siguiente:

Unknown option '-keep' in line 1 of file 'proguard.cfg'


Este problema suele producirse en Windows porque el archivo .cfg tiene una codificación incorrecta. ProGuard
no puede controlar la marca de orden de bytes (BOM ) que puede estar presente en los archivos de texto. Si hay
una marca BOM, ProGuard se cerrará con el error anterior.
Visual Studio
Visual Studio para Mac
Para evitar este problema, edite el archivo de configuración personalizado desde un editor de texto que permita
guardar el archivo sin una marca BOM. Para solucionar este problema, asegúrese de que el editor de texto tenga
la codificación establecida en UTF-8 . Por ejemplo, el editor de texto Notepad++ puede guardar archivos sin la L.
MAT seleccionando Encoding (Codificación) > Encode in UTF-8 Without BOM (Codificar en UTF-8 sin
BOM ) al guardar el archivo.
Otros problemas
En la página de solución de problemas de ProGuard se tratan los problemas comunes (junto con sus soluciones)
que se pueden producir cuando se usa ProGuard.

Resumen
En esta guía se explica cómo funciona ProGuard en Xamarin.Android, cómo se habilita en el proyecto de
aplicación y cómo se configura. Se proporcionan configuraciones de ejemplo de ProGuard y se describen las
soluciones de los problemas comunes. Para obtener más información sobre la herramienta ProGuard y Android,
consulte Reducir tu código y tus recursos.

Vínculos relacionados
Preparar una aplicación para su lanzamiento
Firmar el paquete de aplicación de Android
11/07/2019 • 10 minutes to read • Edit Online

En Preparar una aplicación para su lanzamiento, ha usado Archive Manager para compilar la aplicación y
colocarla en un archivo para su firma y publicación. En esta sección, obtendrá información sobre cómo crear una
identidad de firma de Android, crear un nuevo certificado de firma para aplicaciones de Android y publicar la
aplicación archivada ad hoc en disco. Se puede realizar una instalación de prueba del APK resultante en
dispositivos Android sin pasar por una tienda de aplicaciones.
Visual Studio
Visual Studio para Mac
En Archive for Publishing (Archivo para publicar), el cuadro de diálogo Canal de distribución ofrece dos
opciones para la distribución. Seleccione Ad-Hoc (Ad hoc):

Crear un certificado
Visual Studio
Visual Studio para Mac
Una vez que haya seleccionado Ad-Hoc (Ad hoc), Visual Studio abre la página Identidad de firma del cuadro
de diálogo, como se muestra en la captura de pantalla siguiente. Para publicar el .APK, debe estar firmado con
una clave de firma (también denominada certificado).
Para usar un certificado existente, haga clic en el botón Importar y, después, seleccione Firmar el APK. En caso
contrario, haga clic en el botón + para crear un certificado:
Se muestra el cuadro de diálogo Create Android Key Store (Crear almacén de claves de Android). Úselo para
crear un certificado de firma que se pueda usar para firmar aplicaciones de Android. Escriba la información
necesaria (resaltada en rojo), como se muestra en este cuadro de diálogo:

En el ejemplo siguiente se muestra el tipo de información que se debe proporcionar. Haga clic en Crear para
crear el certificado:
El almacén de claves resultante se encuentra en la ubicación siguiente:
C:\Usuarios\NOMBRE DE USUARIO\AppData\Local\Xamarin\Mono for
Android\Keystore\ALIAS\ALIAS.keystore
Por ejemplo, mediante el uso de chimp como alias, los pasos anteriores podrían crear una clave de firma en la
ubicación siguiente:
C:\Usuarios\NOMBRE DE USUARIO\AppData\Local\Xamarin\Mono for
Android\Keystore\chimp\chimp.keystore

NOTE
Debe crear una copia de seguridad del archivo de almacén de claves y la contraseña resultantes en un lugar seguro, ya
que no se incluye en la solución. Si pierde el archivo (por ejemplo, porque ha cambiado de equipo o porque ha reinstalado
Windows), no podrá firmar la aplicación con el mismo certificado que las versiones anteriores.

Para obtener más información sobre el almacén de claves, consulte Finding your Keystore's MD5 or SHA1
Signature (Buscar la firma MD5 o SHA1 del almacén de claves).

Firmar el APK
Visual Studio
Visual Studio para Mac
Al hacer clic en Crear, se guardará un nuevo almacén de claves (con un nuevo certificado). Aparecerá en
Identidad de firma, como se muestra en la captura de pantalla siguiente. Para publicar una aplicación en
Google Play, haga clic en Cancelar y vaya a Publicación en Google Play. Para publicar ad hoc, seleccione la
identidad de firma que se va a usar para firmar y haga clic en Guardar como para publicar la aplicación para su
distribución independiente. Por ejemplo, en esta captura de pantalla se ha seleccionado la identidad de firma
chimp (creada anteriormente):
Después, el administrador de archivos muestra el progreso de la publicación. Cuando se completa el proceso
de publicación, se abre el cuadro de diálogo Guardar como para solicitar la ubicación donde se almacenará el
archivo .APK generado:

Vaya a la ubicación deseada y haga clic en Guardar. Si la contraseña de la clave es desconocida, aparecerá el
cuadro de diálogo Contraseña de firma, en el que se le solicitará la contraseña del certificado seleccionado:
Al finalizar el proceso de firma, haga clic en Abrir distribución:

Esto hace que el Explorador de Windows abra la carpeta que contiene el archivo APK generado. Llegados a este
punto, Visual Studio ha compilado la aplicación de Xamarin.Android en un APK listo para su distribución. En la
captura de pantalla siguiente se muestra un ejemplo de la aplicación lista para su publicación,
MyApp.MyApp.apk:

Pasos siguientes
Una vez que el paquete de aplicación se haya firmado para su lanzamiento, es necesario publicarlo. En las
secciones siguientes se describen varias formas de publicar una aplicación.
Firma manual del APK
11/07/2019 • 11 minutes to read • Edit Online

Tras compilar la aplicación para su lanzamiento, es necesario firmar el APK antes de distribuirla. De este modo
podrá ejecutarse en un dispositivo Android. Este proceso normalmente se administra con el IDE, aunque hay casos
en los que es necesario firmar el APK manualmente en la línea de comandos. El proceso de firma de APK incluye
los siguientes pasos:
1. Crear una clave privada. Este paso debe realizarse una sola vez. Es necesaria una clave privada para firmar
digitalmente el APK. Una vez que se ha preparado la clave privada, se puede omitir este paso para las
futuras compilaciones de versión.
2. Aplicar la herramienta zipalign al APK. Zipalign es un proceso de optimización que se lleva a cabo en
una aplicación. Permite a Android interactuar de forma más eficaz con el APK en tiempo de ejecución.
Xamarin.Android realiza una comprobación en runtime y no permite que la aplicación se ejecute si no se ha
aplicado la herramienta zipalign al APK.
3. Firmar el APK. Este paso conlleva usar la herramienta apksigner del SDK de Android y firmar el APK con
la clave privada creada en el paso anterior. Las aplicaciones desarrolladas con versiones anteriores a la
24.0.3 de las herramientas de compilación del SDK de Android usarán la aplicación jarsigner del JDK.
Ambas herramientas se tratarán con más detalle a continuación.
El orden de los pasos es importante y depende de qué herramienta se utiliza para firmar el APK. Si se usa
apksigner, en primer lugar es importante usar zipalign con la aplicación y, después, firmarla con apksigner. En
caso de que sea necesario usar jarsigner para firmar el APK, es importante firmar primero el APK y, después,
ejecutar zipalign.

Requisitos previos
Esta guía se centra en el uso de apksigner de las herramientas de compilación del SDK de Android, versión 24.0.3
o posterior. En ella se da por supuesto que ya ha creado el APK.
Las aplicaciones compiladas con una versión anterior de las herramientas de compilación del SDK de Android
deben usar jarsigner, como se describe en la sección Firma del APK con jarsigner de a continuación.

Crear un almacén de claves privadas


Un almacén de claves es una base de datos de certificados de seguridad que se crea mediante el programa keytool
del SDK de Java. Es fundamental que exista un almacén de claves para publicar una aplicación de Xamarin.Android,
dado que Android no ejecuta las aplicaciones que no están firmadas digitalmente.
Durante el desarrollo, Xamarin.Android usa un almacén de claves de depuración para firmar la aplicación, lo que
permite que la aplicación se implemente directamente en el emulador o en dispositivos configurados para usar
aplicaciones depurables. Pero este almacén de claves no se reconoce como un almacén de claves válido para
distribuir aplicaciones.
Por este motivo, se debe crear y usar un almacén de claves privadas para firmar las aplicaciones. Este es un paso
que solo debe realizarse una vez, dado que la misma clave se usará para publicar actualizaciones y, después, puede
usarse para firmar otras aplicaciones.
Es importante proteger este almacén de claves. Si se pierde, no será posible publicar actualizaciones de la
aplicación con Google Play. La única manera de solucionar los problemas causados por la pérdida de un almacén
de claves sería crear otro almacén de claves, volver a firmar el APK con la clave nueva y, después, enviar una
aplicación nueva. Después, la aplicación anterior tendría que quitarse de Google Play. Del mismo modo, si este
nuevo almacén de claves corre peligro o se distribuye públicamente, es posible que se distribuyan versiones no
oficiales o malintencionadas de una aplicación.
Crear un almacén de claves nuevo
La creación de un almacén de claves nuevo requiere la herramienta de línea de comandos keytool del SDK de Java.
El fragmento de código siguiente es un ejemplo de cómo usar keytool (reemplace <my-filename> por el nombre
de archivo del almacén de claves y <key-name> por el nombre de la clave del almacén de claves):

$ keytool -genkeypair -v -keystore <filename>.keystore -alias <key-name> -keyalg RSA \


-keysize 2048 -validity 10000

Lo primero que keytool pedirá es la contraseña del almacén de claves. Después, solicitará cierta información para
ayudar a crear la clave. El fragmento de código siguiente es un ejemplo de cómo crear una nueva clave
denominada publishingdoc que se almacenará en el archivo xample.keystore :

$ keytool -genkeypair -v -keystore xample.keystore -alias publishingdoc -keyalg RSA -keysize 2048 -validity
10000
Enter keystore password:
Re-enter new password:
What is your first and last name?
[Unknown]: Ham Chimpanze
What is the name of your organizational unit?
[Unknown]: NASA
What is the name of your organization?
[Unknown]: NASA
What is the name of your City or Locality?
[Unknown]: Cape Canaveral
What is the name of your State or Province?
[Unknown]: Florida
What is the two-letter country code for this unit?
[Unknown]: US
Is CN=Ham Chimpanze, OU=NASA, O=NASA, L=Cape Canaveral, ST=Florida, C=US correct?
[no]: yes

Generating 2,048 bit RSA key pair and self-signed certificate (SHA1withRSA) with a validity of 10,000 days
for: CN=Ham Chimpanze, OU=NASA, O=NASA, L=Cape Canaveral, ST=Florida, C=US
Enter key password for <publishingdoc>
(RETURN if same as keystore password):
Re-enter new password:
[Storing xample.keystore]

Para enumerar las claves que están almacenadas en un almacén de claves, use keytool con la opción – list :

$ keytool -list -keystore xample.keystore

Aplicar zipalign al APK


Antes de firmar un APK con apksigner, es importante optimizar el archivo con la herramienta zipalign del SDK
de Android. La herramienta zipalign reestructurará los recursos de un APK con límites de 4 bytes. Esta alineación
permite a Android cargar rápidamente los recursos del APK, con lo que se aumenta el rendimiento de la aplicación
y se reduce sustancialmente el uso de memoria. Xamarin.Android llevará a cabo una comprobación en runtime
para determinar si se ha aplicado zipalign al APK. Si no se ha aplicado zipalign al APK, no se ejecutará la aplicación.
El siguiente comando usará el APK firmado y generará un APK firmado con zipalign aplicado denominado
helloworld.apk listo para su distribución.
$ zipalign -f -v 4 mono.samples.helloworld-unsigned.apk helloworld.apk

Firmar el APK
Después de usar zipalign con el APK, es necesario firmarlo con un almacén de claves. Esto se hace con la
herramienta apksigner, disponible en el directorio build-tools de la versión de las herramientas de compilación
del SDK. Por ejemplo, si tiene instalada la versión 25.0.3 de las herramientas de compilación del SDK de Android,
apksigner puede encontrarse en el directorio:

$ ls $ANDROID_HOME/build-tools/25.0.3/apksigner
/Users/tom/android-sdk-macosx/build-tools/25.0.3/apksigner*

El siguiente fragmento de código da por hecho que la variable de entorno PATH puede acceder a apksigner.
Firmará un APK con el alias de clave publishingdoc incluido en el archivo xample.keystore:

$ apksigner sign --ks xample.keystore --ks-key-alias publishingdoc mono.samples.helloworld.apk

Al ejecutar este comando, y si fuera necesario, apksigner solicitará la contraseña del almacén de claves.
Para obtener las información sobre el uso de apksigner, consulte la documentación de Google.

NOTE
De acuerdo con el problema 62696222 de Google, apksigner "no se encuentra" en Android SDK. La solución alternativa a
este problema es instalar la versión 25.0.3 de las herramientas de compilación del SDK de Android y usar dicha versión de
apksigner.

Firma del APK con jarsigner

WARNING
Esta sección solo es aplicable si es necesario firmar el APK con la herramienta jarsigner. Se recomienda a los desarrolladores
que usen apksigner para firmar el APK.

Este técnica implica firmar el archivo APK con el comando jarsigner del SDK de Java. La herramienta jarsigner se
proporciona mediante el SDK de Java.
A continuación se muestra cómo firmar un APK mediante jarsigner y la clave publishingdoc que se encuentra en
un archivo de almacén de claves denominado xample.keystore:

$ jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore xample.keystore mono.samples.helloworld.apk


publishingdoc

NOTE
Al usar jarsigner, es importante firmar el APK en primer lugar y, luego, usar zipalign.

Vínculos relacionados
Firma de aplicaciones
Firma de JAR de Java
jarsigner
keytool
zipalign
Herramientas de compilación 26.0.0: ¿dónde está apksigner?
Búsqueda de la firma de su almacén de claves
11/07/2019 • 6 minutes to read • Edit Online

La firma MD5 o SHA1 de una aplicación Xamarin.Android depende del archivo .keystore que se usó para
firmar el APK. Normalmente, una compilación de depuración usará un archivo .keystore diferente de una
compilación de versión.

Compilaciones para depurar o firmadas no personalizadas


Xamarin.Android firma todas las compilaciones de depuración con el mismo archivo debug.keystore. Este
archivo se genera cuando se instala por primera vez Xamarin.Android. Los siguientes pasos detallan el proceso
para buscar la firma MD5 o SHA1 de archivo predeterminado de Xamarin.Android debug.keystore.
Visual Studio
Visual Studio para Mac
Busque el archivo de Xamarin debug.keystore que se utiliza para firmar la aplicación. De forma
predeterminada, el almacén de claves que se utiliza para firmar las versiones de depuración de una aplicación de
Xamarin.Android puede encontrarse en la siguiente ubicación:
C:\Usuarios\NOMBRE DE USUARIO\AppData\Local\Xamarin\Mono for Android\debug.keystore
La información acerca de un almacén de claves se obtiene ejecutando el comando keytool.exe desde el JDK. La
herramienta normalmente se encuentra en la siguiente ubicación:
C:\Archivos de programa (x86)\Java\jdkVERSIÓN\bin\keytool.exe
Agregue el directorio que contiene keytool.exe a la variable de entorno PATH . Abra una ventana del símbolo
del sistema y ejecute keytool.exe mediante el siguiente comando:

keytool.exe -list -v -keystore "%LocalAppData%\Xamarin\Mono for Android\debug.keystore" -alias


androiddebugkey -storepass android -keypass android

Cuando se ejecuta, keytool.exe debe dar como resultado el siguiente texto. Las etiquetas MD5: y SHA1:
identifican las firmas correspondientes:

Alias name: androiddebugkey


Creation date: Aug 19, 2014
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=Android Debug, O=Android, C=US
Issuer: CN=Android Debug, O=Android, C=US
Serial number: 53f3b126
Valid from: Tue Aug 19 13:18:46 PDT 2014 until: Sun Nov 15 12:18:46 PST 2043
Certificate fingerprints:
MD5: 27:78:7C:31:64:C2:79:C6:ED:E5:80:51:33:9C:03:57
SHA1: 00:E5:8B:DA:29:49:9D:FC:1D:DA:E7:EE:EE:1A:8A:C7:85:E7:31:23
SHA256: 21:0D:73:90:1D:D6:3D:AB:4C:80:4E:C4:A9:CB:97:FF:34:DD:B4:42:FC:
08:13:E0:49:51:65:A6:7C:7C:90:45
Signature algorithm name: SHA1withRSA
Version: 3
Compilaciones de versión o firmadas personalizadas
Los procesos para crear compilaciones de versión que se firman con un archivo .keystore personalizado son los
mismos que los explicados anteriormente, con la versión del archivo .keystore reemplazando el archivo
debug.keystore que utiliza Xamarin.Android. Sustituya sus propios valores para la contraseña de KeyStore y el
nombre de alias utilizado cuando se creó el archivo del almacén de claves de la versión.
Visual Studio
Visual Studio para Mac
Cuando se utilice el asistente de Visual Studio Distribuir para firmar una aplicación de Xamarin.Android,
encontrará el almacén de claves resultante en la siguiente ubicación:
C:\Usuarios\NOMBRE DE USUARIO\AppData\Local\Xamarin\Mono for
Android\Keystore\alias\alias.keystore
Por ejemplo, si ha seguido los pasos de Crear un nuevo certificado para crear una nueva clave de firma, el
almacén de claves de ejemplo resultante reside en la siguiente ubicación:
C:\Usuarios\NOMBRE DE USUARIO\AppData\Local\Xamarin\Mono for
Android\Keystore\chimp\chimp.keystore
Para más información sobre cómo firmar una aplicación de Xamarin.Android, vea Firmar el paquete de
aplicación de Android.
Publicar una aplicación
01/08/2019 • 6 minutes to read • Edit Online

Después de crear una gran aplicación, la gente querrá usarla. En este artículo se describen los pasos implicados en
la distribución pública de una aplicación creada con Xamarin.Android a través de canales como el correo
electrónico, un servidor web privado, Google Play o la Tienda Apps de Amazon para Android.

Información general
El paso final en el desarrollo de una aplicación de Xamarin.Android es publicar la aplicación. La publicación es el
proceso de compilación de una aplicación de Xamarin.Android para que esté lista para que los usuarios la instalen
en sus dispositivos, e implica dos tareas esenciales:
Preparar la publicación: se crea una versión de lanzamiento de la aplicación que se puede implementar
en dispositivos Android (consulte Preparar una aplicación para su lanzamiento para más información sobre
la preparación de lanzamiento).
Distribución: la versión de lanzamiento de una aplicación estará disponible a través de uno o varios
canales de distribución.
El siguiente diagrama ilustra los pasos de publicación de una aplicación de Xamarin.Android:

Como puede observarse en el diagrama anterior, la preparación es la misma independientemente del método de
distribución que se utilice. Hay varias formas de poner una aplicación de Android a disposición de los usuarios:
A través de un sitio web: una aplicación Xamarin.Android puede estar disponible para su descarga en un
sitio web, desde el que los usuarios pueden instalarla haciendo clic en un vínculo.
Por correo electrónico: los usuarios pueden instalar una aplicación Xamarin.Android desde su correo
electrónico. La aplicación se instalará cuando se abra el archivo adjunto con un dispositivo Android.
A través de una tienda: existen varias tiendas de aplicaciones para la distribución, como Google Play o la
Tienda Apps de Amazon para Android.
Utilizar una tienda establecida es la manera más común para publicar una aplicación, ya que proporciona la
mayor cobertura de mercado y el máximo control sobre la distribución. Sin embargo, publicar una aplicación a
través de una tienda requiere un esfuerzo adicional.
Varios canales pueden distribuir una aplicación de Xamarin.Android simultáneamente. Por ejemplo, una aplicación
puede publicarse en Google Play, la Tienda Apps de Amazon para Android y también se puede descargar desde
un servidor web.
Los otros dos métodos de distribución (descarga o correo electrónico) son más útiles para un subconjunto de
usuarios, como un entorno empresarial o una aplicación que solo está destinada a un conjunto de usuarios
pequeño o controlado. La distribución a través de un servidor y de correo electrónico también son modelos de
publicación más sencillos, que requieren menos preparación para publicar una aplicación.
El programa de distribución de aplicaciones de Amazon Mobile permite a los desarrolladores de aplicaciones
móviles distribuir y vender sus aplicaciones en Amazon. Los usuarios pueden descubrir y comprar aplicaciones en
sus dispositivos Android mediante la aplicación Tienda Apps de Amazon. A continuación aparece una captura de
pantalla de la Tienda Apps de Amazon en un dispositivo Android:
Google Play es, posiblemente, la tienda más completa y popular para aplicaciones Android. Google Play permite a
los usuarios detectar, descargar, evaluar y pagar por aplicaciones haciendo clic en un solo icono en su dispositivo o
su equipo. Google Play también proporciona herramientas para ayudar en el análisis de ventas y las tendencias
del mercado y controlar qué dispositivos y usuarios pueden descargar una aplicación. A continuación aparece una
captura de pantalla de Google Play en un dispositivo Android:
En esta sección se muestra cómo cargar la aplicación en una tienda, como Google Play, junto con el material
promocional adecuado. Se describen los archivos de expansión del APK y se ofrece información general
conceptual sobre qué son y cómo funcionan. También se describen los servicios de Licencias de Google. Por
último, se presentan medios alternativos de distribución, incluido el uso de un servidor web HTTP, la distribución
por correo electrónico simple y Amazon Appstore para Android.

Vínculos relacionados
HelloWorldPublishing (ejemplo)
Creación de proceso
Vinculación
Obtener una clave de API de Google Maps
Firma de aplicaciones
Publicación en Google Play
Licencias de aplicaciones de Google
Android.Play.ExpansionLibrary
Portal de distribución de aplicaciones móviles
Preguntas más frecuentes sobre la distribución de aplicaciones móviles de Amazon
Publicación en Google Play
11/07/2019 • 27 minutes to read • Edit Online

Aunque hay muchos mercados de aplicaciones para distribuirlas, Google Play es posiblemente el mayor almacén
y el más visitado del mundo para aplicaciones Android. Google Play proporciona una plataforma única para
distribuir, publicitar, vender y analizar las ventas de una aplicación Android.
En esta sección se tratan temas específicos de Google Play, como registrarse para convertirse en editor, recopilar
recursos para ayudar a Google Play a promocionar y publicitar la aplicación, las directrices para la clasificación
de la aplicación en Google Play y el uso de filtros para restringir la implementación de una aplicación en
determinados dispositivos.

Requisitos
Para distribuir una aplicación a través de Google Play, debe crearse una cuenta de desarrollador. Solo debe
efectuarse una vez y conlleva una tarifa única de 25 USD.
Todas las aplicaciones deben estar registradas con una clave criptográfica que expirará después del 22 de octubre
de 2033.
El tamaño máximo de un APK publicado en Google Play es de 100 MB. Si una aplicación supera ese tamaño,
Google Play permitirá la entrega de recursos adicionales mediante archivos de expansión de APK. Los archivos
de expansión Android permiten que el APK tenga 2 archivos adicionales, cada uno de ellos con un tamaño
máximo de 2 GB. Google Play hospedará y distribuirá estos archivos sin costo alguno. Los archivos de expansión
se tratarán en otra sección.
Google Play no está disponible en todo el mundo. Es posible que en algunas ubicaciones no se admita la
distribución de aplicaciones.

Convertirse en editor
Para publicar aplicaciones en Google Play, es necesario tener una cuenta de editor. Para suscribirse a una cuenta
de editor, siga estos pasos:
1. Visite Google Play Developer Console.
2. Escriba la información básica de su identidad de desarrollador.
3. Lea y acepte el contrato de distribución para desarrolladores que le corresponda.
4. Abone la tarifa de registro de 25 USD.
5. Confirme la verificación por correo electrónico.
6. Una vez creada la cuenta, ya es posible publicar aplicaciones mediante Google Play.
Google Play no se admite en todos los países del mundo. Las listas de países más recientes se pueden encontrar
en los siguientes vínculos:
1. Ubicaciones admitidas para el registro de comerciantes y desarrolladores – Se trata de una lista de todos
los países en los que los desarrolladores pueden registrarse como comerciantes y vender aplicaciones de
pago.
2. Ubicaciones admitidas para la distribución de aplicaciones a usuarios de Google Play – Se trata de una
lista de todos los países en los que se pueden distribuir aplicaciones.
Preparación de los recursos promocionales
Para promocionar y publicitar de forma eficaz una aplicación en Google Play, Google permite a los
desarrolladores enviar recursos promocionales, como capturas de pantalla, gráficos y vídeos. Google Play utiliza
dichos recursos para publicitar y promocionar la aplicación.
Iconos del iniciador
Un icono del iniciador es un gráfico que representa una aplicación. Cada icono del iniciador debe ser un archivo
PNG de 32 bits con un canal alfa en caso de transparencia. Una aplicación debe tener iconos de todas las
densidades de pantalla generalizadas, tal como se describe en la siguiente lista:
ldpi (120 ppp) – 36 x 36 px
mdpi (160 ppp) – 48 x 48 px
hdpi (240 ppp) – 72 x 72 px
xhdpi (320 ppp) – 96 x 96 px
Los iconos del iniciador son lo primero que verá un usuario de aplicaciones de Google Play, por lo que debe
prestarse mucha atención para conseguir que los iconos del iniciador sean visualmente atractivos y significativos.
Sugerencias para los iconos de iniciador:
1. Simples y ordenados– Los iconos del iniciador deben mostrarse de forma simple y ordenada. Esto
significa que hay que excluir el nombre de la aplicación del icono. Los iconos más sencillos serán más
fáciles de recordar y, además, serán más fáciles distinguir en tamaños más pequeños.
2. Iconos que no sean finos– Los iconos demasiado finos no destacan bien en todos los fondos.
3. Uso del canal alfa– Los iconos deben usar el canal alfa y no deben ser imágenes enmarcadas por
completo.
Iconos de aplicaciones de alta resolución
Las aplicaciones de Google Play requieren una versión de alta fidelidad del icono de la aplicación. Solo se utiliza
en Google Play y no reemplaza el icono del iniciador de la aplicación. Las especificaciones de los iconos de alta
resolución son los siguientes:
1. PNG de 32 bits con un canal alfa
2. 512 x 512 píxeles
3. Tamaño máximo de 1024 KB
Android Asset Studio es una herramienta útil para la creación de iconos adecuados para el iniciador y las
aplicaciones de alta resolución.
Capturas de pantalla
Google Play requiere un mínimo de dos y un máximo de ocho capturas de pantalla para una aplicación. Se
muestran en la página de detalles de la aplicación en Google Play.
Las especificaciones para las capturas de pantalla son las siguientes:
1. PNG o JPG 24 bits sin ningún canal alfa
2. 320 de ancho x 480 de alto, 480 de ancho x 800 de alto o 480 de ancho x 854 de alto. Las imágenes con
paisajes se recortarán.
Gráfico promocional
Se trata de una imagen opcional utilizada por Google Play:
1. Es un archivo PNG o JPG de 24 bits y de 180 de ancho x 120 de alto sin ningún canal alfa.
2. No incluye bordes.
Gráfico de características
Se utiliza en la sección de características de Google Play. Este gráfico puede aparecer solo, sin un icono de
aplicación.
1. Es un archivo PNG o JPG de 1024 de ancho x 500 de alto sin ningún canal alfa y sin transparencia.
2. Todo el contenido importante debe estar dentro de un marco de 924 x 500. Para fines estilísticos, se pueden
recortar los píxeles que estén fuera de este marco.
3. También puede reducirse: utilice texto grande y simplifique los gráficos.
Vínculo de vídeo
Se trata de una dirección URL de un vídeo de YouTube que muestra la aplicación. El vídeo debe durar entre 30
segundos y 2 minutos, y debe mostrar las mejores partes de la aplicación.
Publicación en Google Play
Visual Studio
Visual Studio para Mac
Xamarin Android 7.0 introduce un flujo de trabajo integrado para publicar aplicaciones en Google Play desde
Visual Studio. Si utiliza una versión de Xamarin Android anterior a la 7.0, debe cargar manualmente el APK
mediante Google Play Developer Console. Además, debe tener al menos un APK que ya esté cargado para poder
utilizar el flujo de trabajo integrado. Si todavía no ha cargado su primer APK, debe cargarlo manualmente. Para
obtener más información, consulte Manually Uploading the APK (Carga manual del APK).
En Creating a New Certificate (Crear un certificado) se explica cómo crear un nuevo certificado para firmar
aplicaciones Android. El siguiente paso es publicar una aplicación firmada en Google Play:
1. Inicie sesión en su cuenta de desarrollador de Google Play para crear un nuevo proyecto que esté vinculado a
ella.
2. Cree un Cliente de OAuth que autentique su aplicación.
3. Escriba el id. de cliente y el secreto del cliente resultantes en Visual Studio.
4. Registre la cuenta con Visual Studio.
5. Firme la aplicación con el certificado.
6. Publique la aplicación firmada en Google Play.
En Archive for Publishing (Archivo para publicar), el cuadro de diálogo Canal de distribución ofrece dos
opciones para la distribución: Ad Hoc y Google Play. Si aparece el cuadro de diálogo Signing Identity
(Identidad de firma), haga clic en Atrás para volver al cuadro de diálogo Distribution Channel (Canal de
distribución). Seleccione Google Play y haga clic en Siguiente:
En el cuadro de diálogo Identidad de firma, seleccione la identidad que se ha creado en Creating a New
Certificate (Crear un certificado) y haga clic en Continuar:

En el cuadro de diálogo Cuentas de Google Play, haga clic en el botón + para agregar una nueva cuenta de
Google Play:
En el cuadro de diálogo Register Google API Access (Registrar acceso de API de Google) debe
proporcionar el id. de cliente y el secreto de cliente que proporcionan acceso a la API a su cuenta de
desarrollador Google Play:

En la siguiente sección se explica cómo crear un nuevo proyecto de API de Google y generar el id. de cliente y el
secreto de cliente que se necesitan.
Creación de un proyecto de API de Google
En primer lugar, inicie sesión en su cuenta de desarrollador de Google Play. Si no dispone de una cuenta de
desarrollador de Google Play, consulte Primeros pasos con la publicación. Además, en la Introducción la API
para desarrolladores de Google Play se explica cómo utilizar la API. Después de iniciar sesión en Google Play
Developer Console, haga clic en Configuración:
En el la página CONFIGURACIÓN, seleccione Acceso de API y haga clic en el botón Crear nuevo proyecto:

Tras un minuto aproximadamente, el nuevo proyecto de API se genera de forma automática y se vincula a su
cuenta de Google Play Developer Console.
El siguiente paso es crear un cliente de OAuth para la aplicación, si aún no se ha creado uno. Cuando los usuarios
solicitan acceso a sus datos privados mediante la aplicación, el id. de cliente OAuth se usa para autenticar su
aplicación. Haga clic en Crear cliente de OAuth para crear un nuevo cliente de OAuth:

Después de unos segundos, se genera un nuevo id. de cliente. Haga clic en Ver en Google Developers
Console para ver su nuevo id. de cliente en Google Developers Console:

El id. de cliente se muestra con su fecha de creación y el nombre. Haga clic en el icono Editar cliente de OAuth
para ver el secreto de cliente de la aplicación:

El nombre predeterminado del cliente de OAuth es Desarrollador de Google Play Android. Se puede cambiar
por nombre de la aplicación de Xamarin.Android o por cualquier nombre adecuado. En este ejemplo, se cambia
el nombre de cliente OAuth por el nombre de la aplicación, MyApp:

Haga clic en Guardar para guardar los cambios. De este modo volverá a la página Credenciales, donde puede
descargar las credenciales haciendo clic en el icono Descargar JSON:
Este archivo JSON contiene el id. de cliente y el secreto del cliente que puede cortar y pegar en el cuadro de
diálogo Sign and Distribute (Firmar y distribuir) en el paso siguiente.
Registro del acceso de la API de Google
Visual Studio
Visual Studio para Mac
Utilice el identificador de cliente y el secreto de cliente para completar el cuadro de diálogo Cuenta de API de
Google Play de Visual Studio para Mac. Es posible proporcionar una descripción a la cuenta, lo que permite
registrar más de una cuenta de Google Play y cargar futuros APK en diferentes cuentas de Google Play. Copie el
id. de cliente y el secreto de cliente en este cuadro de diálogo y haga clic en Registrar:

Se abrirá un explorador web y le solicitará que, si aún no lo ha hecho, inicie sesión en su cuenta de desarrollador
de Android de Google Play. Después de iniciar sesión, se mostrará el mensaje siguiente en el explorador web.
Haga clic en Permitir para autorizar la aplicación:
Publicar
Después de hacer clic en Permitir, el explorador indica Received verification code. Closing... (Código de
verificación recibido. Cerrando...) y la aplicación se agrega a la lista de cuentas de Google Play en Visual Studio.
En el cuadro de diálogo Cuentas de Google Play, haga clic en Continuar:

Después, se muestra el cuadro de diálogo Pista de Google Play. Google Play ofrece cuatro pistas posibles para
cargar la aplicación:
Alfa – Se usa para cargar una versión muy temprana de la aplicación en una lista reducida de evaluadores.
Beta – Se usa para cargar una versión temprana de la aplicación en una lista amplia de evaluadores.
Lanzamiento – Permite a un porcentaje de los usuarios recibir una versión actualizada de la aplicación. Así,
puede aumentar lentamente el porcentaje de aproximadamente el 10 % de los usuarios hasta el 100 %
mientras corrige errores.
Producción – Seleccione esta pista cuando la aplicación esté lista para su distribución completa desde
Google Play Store.
Elija qué pista de Google Play se utilizará para cargar la aplicación y haga clic en Cargar. Si selecciona Rollout
(Implementación), asegúrese de especificar un valor porcentual:
Para obtener más información sobre las pruebas y las implementaciones graduales de Google Play, consulte
Configurar pruebas alpha o beta.
A continuación, se muestra un cuadro de diálogo para especificar la contraseña del certificado de firma. Escriba
la contraseña y haga clic en Aceptar:

El administrador de archivos muestra el progreso de la carga:

Cuando finaliza la carga, el estado se muestra en la esquina inferior izquierda de Visual Studio:
Solución de problemas
Tenga en cuenta que se debe haber enviado antes un APK a Google Play Store para que Publish to Google
Play (Publicación en Google Play) funcione. Si aún no se ha cargado un APK, el Asistente para publicación
mostrará el siguiente error en la panel Errores:

Si se produce este error, cargue un APK manualmente, por ejemplo, una compilación ad hoc, mediante Google
Play Developer Console y utilice el cuadro de diálogo Distribution Channel (Canal de distribución) para
posteriores actualizaciones del APK. Para obtener más información, consulte Manually Uploading the APK (Carga
manual del APK). El código de la versión del APK debe cambiar con cada carga. De lo contrario, se producirá el
siguiente error:

Para resolver este error, vuelva a compilar la aplicación con un número de versión diferente y reenvíela a Google
Play mediante el cuadro de diálogo Distribution Channel (Canal de distribución).
Servicios de licencia de Google
11/07/2019 • 4 minutes to read • Edit Online

Antes de Google Play, las aplicaciones de Android se basaban en la protección contra copia heredada
proporcionada por Google Market para garantizar que solo los usuarios autorizados pudieran ejecutar aplicaciones
en sus dispositivos. Las limitaciones del mecanismo de protección contra copia la convertían en una solución que
no era óptima para la protección de aplicaciones.
Licencias de Google es un sustituto de este mecanismo de protección contra copia heredado. Licencias de Google
es un servicio basado en la red, seguro y flexible que las aplicaciones de Android pueden consultar para determinar
si una aplicación tiene licencia para ejecutarse en un dispositivo determinado.
Licencias de Google es flexible en el sentido de que las aplicaciones de Android tienen el control total sobre el
momento de comprobar la licencia, la frecuencia de comprobación de la licencia y la manera de controlar la
respuesta del servidor de licencias.
Licencias de Google es seguro en que cada respuesta se firma con un par de claves RSA que se comparte de
manera exclusiva entre el servidor de Google Play y la aplicación. Google Play proporciona una clave pública para
desarrolladores que está insertada dentro de la aplicación de Android y que se usa para autenticar las respuestas.
El servidor de Google Play mantiene la clave privada de manera interna.
Una aplicación que tiene Licencias de Google implementadas realiza una solicitud a un servicio hospedado
mediante la aplicación de Google Play en el dispositivo. Después, Google Play envía esta solicitud al servidor de
Licencias de Google, que responde con el estado de la licencia:

En el diagrama anterior se muestra este flujo de trabajo:


La aplicación proporciona el nombre del paquete, un nonce (un autenticador criptográfico) que se usa para
validar la respuesta del servidor y una devolución de llamada que puede controlar la respuesta de forma
asincrónica.
Google Play proporciona información como la cuenta de Google y el propio dispositivo, como el número
IMSI.
El servicio de Licencias de Google también es un componente clave de los archivos de expansión APK (que se
tratarán posteriormente en este documento). Los archivos de expansión APK usan los servicios de Licencias de
Google para obtener las direcciones URL de los archivos de expansión que se descargarán.

Requisitos
Las aplicaciones que se han adquirido a través de Google Play no recibirán ningún beneficio de los servicios de
Licencias de Google. Si Google Play no está instalado en un dispositivo, entonces las aplicaciones que usen los
Servicios de licencias seguirán funcionando normalmente en ese dispositivo.
Google Play necesita acceso a Internet para realizar esta función. Una aplicación puede almacenar en caché la
licencia para incluir escenarios en los que el dispositivo no tenga acceso a los servidores de licencias de Google
Play.
Las aplicaciones gratuitas solo necesitan Licencias de Google cuando la aplicación usa archivos de expansión APK.
Archivos de expansión de APK
11/07/2019 • 14 minutes to read • Edit Online

Algunas aplicaciones, como es el caso de algunos juegos, por ejemplo, requieren más recursos y activos de los que
se pueden proporcionar en el límite del tamaño máximo de la aplicación Android que impone Google Play. Este
límite depende de la versión de Android para la que esté destinado el APK:
100 MB para APK destinadas a Android 4.0 o versiones posteriores (nivel de API 14 o superior).
50 MB para APK destinadas a Android 3.2 o versiones anteriores (nivel de API 13 o superior).
Para superar esta limitación, Google Play hospeda y distribuye dos archivos de expansión que acompañan a un
APK, con lo cual una aplicación puede superar indirectamente este límite.
En la mayoría de los dispositivos, cuando se instala una aplicación, los archivos de expansión se descargan junto
con el APK y se guardan en la ubicación de almacenamiento compartido (la tarjeta SD o la partición que se puede
montar en un USB ) del dispositivo. En algunos dispositivos antiguos, los archivos de expansión no pueden
instalarse automáticamente con el APK. En este caso, es necesario que la aplicación contenga el código que permite
descargar los archivos de expansión cuando el usuario ejecute por primera vez las aplicaciones.
Los archivos de expansión se tratan como blobs binarios opacos (obb ) que pueden tener un tamaño de hasta 2 GB.
Android no realiza ningún procesamiento especial en estos archivos tras su descarga, y estos pueden estar en
cualquier formato que sea adecuado para la aplicación. Desde el punto de vista conceptual, el enfoque
recomendado para los archivos de expansión es el siguiente:
Expansión principal: este es el archivo de expansión principal para recursos y activos que no tienen cabida en
el límite de tamaño del APK. El archivo de expansión principal debe contener los activos principales que necesita
una aplicación y rara vez debe actualizarse.
Expansión de revisión: este está diseñado para pequeñas actualizaciones del archivo de expansión principal.
Este archivo se puede actualizar. La aplicación se encarga de realizar las revisiones o actualizaciones necesarias
desde este archivo.
Los archivos de expansión deben cargarse al mismo tiempo que el APK. Google Play no permite que se descargue
un archivo de expansión en un APK existente ni para APK existentes que deban actualizarse. Si es necesario
actualizar un archivo de expansión, se debe cargar un APK nuevo con versionCode actualizado.

Almacenamiento de archivos de expansión


Cuando se descargan los archivos en un dispositivo, se almacenan en shared-store/Android/obb/package-
name:
shared-store: es el directorio especificado por Android.OS.Environment.ExternalStorageDirectory .
package-name: es el nombre del paquete de estilo Java de la aplicación.
Una vez descargados, los archivos de expansión no se deben mover, modificar, cambiar de nombre ni eliminar de
su ubicación en el dispositivo. Si no se respeta esta directriz, los archivos de expansión se descargarán de nuevo y
se eliminarán los archivos antiguos. Además, el directorio del archivo de expansión solo debe contener los archivos
del paquete de expansión.
Los archivos de expansión no ofrecen seguridad ni protección alguna de su contenido, es decir, otras aplicaciones u
otros usuarios pueden tener acceso a los archivos guardados en el almacenamiento compartido.
Si es necesario desempaquetar un archivo de expansión, se deben almacenar archivos desempaquetados en un
directorio independiente, como por ejemplo uno en Android.OS.Environment.ExternalStorageDirectory .
Como alternativa a la extracción de archivos desde un archivo de expansión, se pueden leer los activos o recursos
directamente desde el archivo de expansión. El archivo de expansión tan solo es un archivo .zip que se puede usar
con un ContentProvider adecuado. Android.Play.ExpansionLibrary contiene un ensamblado,
System.IO.Compression.Zip, que incluye un ContentProvider que permitirá a algunos archivos multimedia tener
acceso directo a los archivos. Si los archivos multimedia se empaquetan en un archivo .zip, las llamadas de
reproducción multimedia pueden utilizar directamente los archivos del archivo .zip sin tener que desempaquetarlo.
Al agregar los archivos multimedia al .zip, estos no deben comprimirse.
Formato de nombre de archivo
Tras descargar los archivos de expansión, Google Play utiliza el siguiente esquema para asignar un nombre a la
expansión:

[main|patch].<expansion-version>.<package-name>.obb

Los tres componentes de este esquema son:


main o patch : especifica si este es el archivo de expansión principal o de revisiones. Solo puede ser uno de los
dos.
<expansion-version> : entero que coincide con el versionCode del APK con el que se ha asociado el archivo en
primer lugar.
<package-name> : nombre del paquete de estilo Java de la aplicación.
Por ejemplo, si la versión del APK es la 21 y el nombre del paquete es mono.samples.helloworld , el archivo de
expansión principal se llamará main.21.mono.samples.helloworld.

Proceso de descarga
Cuando se instala una aplicación desde Google Play, los archivos de expansión deben descargarse y guardarse
junto con el APK. En determinadas situaciones es posible que esto no sea así o bien que se eliminen los archivos de
expansión. Para resolver esta incidencia, una aplicación debe comprobar si existen los archivos de expansión y,
luego, descargarlos, si es necesario. El siguiente diagrama muestra el flujo de trabajo recomendado para este
proceso:
Cuando se inicia una aplicación, debe comprobar si existen los archivos de expansión adecuados en el dispositivo
actual. En caso contrario, la aplicación debe realizar una solicitud desde la Administración de licencias de
aplicaciones de Google Play. Esta comprobación se realiza mediante la License Verification Library (LVL ) (Biblioteca
de comprobación de licencias (BCL )) y debe efectuarse en el caso de las aplicaciones gratuitas y las que necesiten
licencia. La BCL la utilizan principalmente aplicaciones de pago para aplicar restricciones de licencias. Sin embargo,
Google ha ampliado la BCL de tal manera que pueda utilizarse también con las bibliotecas de expansión. Las
aplicaciones gratuitas tienen que realizar la comprobación de la BCL, pero pueden ignorar las restricciones de
licencias. La solicitud de la BCL se encarga de proporcionar la siguiente información sobre los archivos de
expansión que necesita la aplicación:
Tamaño del archivo: los tamaños de archivo de los archivos de expansión se utilizan como parte de la
comprobación que determina si ya se han descargado o no los archivos de expansión correctos.
Nombres de archivo: nombre de archivo, en el dispositivo actual, en que deben guardarse los paquetes de
expansión.
URL de descarga: dirección URL que se debe utilizar para descargar los paquetes de expansión. Es única para
cada descarga y expirará poco después de haberse proporcionado.
Una vez realizada la comprobación de la BCL, la aplicación debe descargar los archivos de expansión, teniendo en
cuenta los puntos siguientes como parte de la descarga:
Es posible que el dispositivo no tenga espacio suficiente para almacenar los archivos de expansión.
Si no está disponible la Wi-Fi, el usuario debe poder pausar o cancelar la descarga para evitar cargos de datos
no deseados.
Los archivos de expansión se descargan en segundo plano para evitar el bloqueo de las interacciones del
usuario.
Mientras la descarga se realiza en segundo plano, se debe mostrar un indicador de progreso.
Los errores que se produzcan durante la descarga se procesan correctamente y esta se puede recuperar.
Información general sobre la arquitectura
Cuando se inicia la actividad principal, comprueba si se descargan los archivos de expansión. Si se descargan los
archivos, debe comprobarse su validez.
Si no se han descargado los archivos de expansión o si los archivos actuales no son válidos, se deben descargar
nuevos archivos de expansión. Se crea un servicio entrelazado como parte de la aplicación. Cuando se inicia la
actividad principal de la aplicación, utiliza el servicio entrelazado para realizar una comprobación en los servicios
de administración de licencias de Google con el fin de averiguar los nombres de los archivos de expansión y la
dirección URL de los archivos que se deben descargar. A continuación, el servicio entrelazado descarga los archivos
en un subproceso en segundo plano.
Para simplificar la tarea de integrar los archivos de expansión en una aplicación, Google ha creado varias
bibliotecas en Java. Las bibliotecas en cuestión son las siguientes:
Biblioteca descargadora: biblioteca que simplifica la integración de los archivos de expansión en una
aplicación. La biblioteca descarga los archivos de expansión en un servicio en segundo plano, muestra las
notificaciones de usuario, trata los problemas de conectividad de red, reanuda las descargas, etc.
Biblioteca de comprobación de licencias (BCL ): biblioteca para realizar y procesar las llamadas a los
servicios de administración de licencias de aplicaciones. También puede utilizarse para realizar comprobaciones
de licencias y, así, ver si la aplicación está autorizada para su uso en el dispositivo.
Biblioteca del archivo .zip de expansión de APK (opcional): si los archivos de expansión están en un
archivo .zip, esta biblioteca actúa como proveedor de contenido y permite que una aplicación lea los recursos y
activos directamente desde el archivo .zip sin tener que expandirlo.
Estas bibliotecas se han trasladado a C# y están disponibles bajo la licencia de Apache 2.0. Para integrar
rápidamente los archivos de expansión en una aplicación existente, estas bibliotecas se pueden agregar a una
aplicación existente de Xamarin.Android. El código está disponible en Android.Play.ExpansionLibrary, en GitHub.
Carga manual del APK
11/07/2019 • 16 minutes to read • Edit Online

La primera vez que se envía un APK a Google Play (o si se usa una versión antigua de Xamarin.Android), se debe
cargar manualmente el APK mediante Google Play Developer Console. En esta guía se explican los pasos
necesarios para este proceso.

Google Play Developer Console


Una vez que se ha compilado el APK y se han preparado los activos promocionales, la aplicación debe cargarse
en Google Play. Para ello, inicie sesión en Google Play Developer Console, que se muestra a continuación. Haga
clic en el botón Publish an Android App on Google Play (Publicar una aplicación de Android en Google
Play) para inicializar el proceso de distribución de una aplicación.

Si ya tiene una aplicación registrada con Google Play, haga clic en el botón Add new application (Agregar
nueva aplicación):

Cuando aparece el cuadro de diálogo ADD NEW APPLICATION (AGREGAR NUEVA APLICACIÓN ), escriba
el nombre de la aplicación y haga clic en Upload APK (Cargar APK):
La pantalla siguiente permite publicar la aplicación para pruebas alfa, pruebas beta o producción. En el ejemplo
siguiente, la pestaña ALPHA TESTING (PRUEBAS ALFA ) está seleccionada. Dado que MyApp no usa
servicios de licencias, no hay que hacer clic en el botón Get license key (Obtener clave de licencia) para este
ejemplo. En este caso, se hace clic en el botón Upload your first APK to Alpha (Cargar el primer APK en
alfa) para publicar en el canal alfa:

Aparece el cuadro de diálogo UPLOAD NEW APK TO ALPHA (CARGAR NUEVO APK EN ALFA ). El APK se
puede cargar haciendo clic en Browse files (Examinar archivos) o arrastrando y soltando el APK:
Asegúrese de cargar el APK listo para publicar que se va a distribuir. El siguiente cuadro de diálogo indica el
progreso de la carga del APK:

Una vez cargado el APK, es posible seleccionar un método de prueba:


Para más información sobre las pruebas de una aplicación, vea la guía de Google Configurar pruebas alpha o
beta.
Una vez cargado el APK, se guarda como un borrador. No se puede publicar hasta que se proporcionan más
detalles a Google Play, como se explica a continuación.

Descripción de la tienda
Haga clic en Store Listing (Descripción de la tienda) en Google Play Developer Console para especificar la
información que Google Play mostrará a los usuarios potenciales de la aplicación:

Activos gráficos
Desplácese hacia abajo hasta la sección GRAPHICS ASSETS (ACTIVOS GRÁFICOS ) de la página Store
Listing (Descripción de la tienda):
Todos los activos promocionales que se prepararon anteriormente se cargan en esta sección. Se ofrece
orientación sobre los activos promocionales que se deben proporcionar y el formato que deben tener.
Categorización
Después de la sección GRAPHICS ASSETS (ACTIVOS GRÁFICOS ) hay una sección CATEGORIZATION
(CATEGORIZACIÓN ) donde se selecciona el tipo de aplicación y la categoría:

La clasificación de contenido se trata después de la sección siguiente.


Detalles de contacto
La sección final de esta página es una sección CONTACT DETAILS (DETALLES DE CONTACTO ). Se usa para
recopilar información de contacto sobre el desarrollador de la aplicación:

Es posible proporcionar una dirección URL para la directiva de privacidad de la aplicación en la sección
PRIVACY POLICY (DIRECTIVA DE PRIVACIDAD ), como se ha indicado arriba.
Clasificación de contenido
Haga clic en Content Rating (Clasificación de contenido) en Google Play Developer Console. En esta
página, especifique la clasificación de contenido de la aplicación. Google Play exige que todas las aplicaciones
especifiquen una clasificación de contenido. Haga clic en el botón Continuar para completar el cuestionario de
clasificación de contenido:

Todas las aplicaciones de Google Play deben clasificarse según el sistema de clasificación de Google Play.
Además de la clasificación de contenido, todas las aplicaciones deben cumplir las Políticas del Programa para
Desarrolladores de Google.
A continuación se muestran los cuatro niveles del sistema de clasificación de Google Play y se proporcionan
algunas directrices como características o contenido que exigirían o forzarían el nivel de clasificación:
Apto para todo el público – No debe publicar, compartir o tener acceso a los datos de ubicación. No
debe incluir ningún contenido generado por el usuario. No debe permitir la comunicación entre los
usuarios.
Nivel de madurez bajo – Aplicaciones que acceden a datos de ubicación pero no los comparten.
Representaciones de violencia animada o moderada.
Nivel de madurez mediano – Referencias a alcohol, tabaco o drogas. Temas de juegos de apuestas o
juegos de apuestas simulados. Contenido provocativo. Blasfemias y humor grosero. Referencias sexuales o
provocativas. Violencia ficticia intensa. Violencia realista. Se permite que los usuarios se busquen entre
ellos. Se permite que los usuarios se comuniquen entre ellos. Uso compartido de los datos de la ubicación
de un usuario.
Nivel de madurez alto – Se centra en el consumo o la venta de alcohol, tabaco o drogas. Se centra en
referencias sexuales o provocativas. Violencia explícita.
Los elementos de la lista de nivel de madurez mediano son subjetivos, ya que puede darse el caso de que una
directriz que aparentemente indica una clasificación de nivel de madurez mediano sea lo suficientemente intensa
para justificar una clasificación de nivel de madurez alto.

Precios y distribución
Haga clic en Pricing and Distribution (Precios y distribución) en Google Play Developer Console. En esta
página, establezca un precio si la aplicación es de pago. La aplicación también se puede distribuir gratuitamente a
todos los usuarios. Una vez que una aplicación se especifica como gratuita, debe seguir siéndolo. Google Play no
permite que una aplicación gratuita pase a ser de pago (aunque es posible vender contenido con facturación
integrada en la aplicación con una aplicación gratuita). Google Play permite que una aplicación de pago pase a
ser gratuita en cualquier momento.
Para publicar una aplicación de pago se necesita una cuenta de comerciante. Para ello, haga clic en Set up a
merchant account (Configurar una cuenta de comerciante) y siga las instrucciones.

Administrar países
La siguiente sección, Administrar países, proporciona control sobre los países en los que se puede distribuir una
aplicación:

Otra información
Desplácese más hacia abajo para especificar si la aplicación contiene publicidad. Además, la sección DEVICE
CATEGORIES (CATEGORÍAS DE DISPOSITIVOS ) proporciona opciones para distribuir opcionalmente la
aplicación para Android Wear, Android TV o Android Auto:

Después de esta sección hay opciones adicionales que se pueden seleccionar, como suscribirse a Designed for
Families (Diseñado para familias) y distribuir la aplicación a través de Google Play for Education.
Consentimiento
En la parte inferior de la página Pricing & Distribution (Precios y distribución) está la sección CONSENT
(CONSENTIMIENTO ). Es una sección obligatoria que se usa para declarar que la aplicación se ajusta a las
directrices de contenido de Android y que cumple las leyes de exportación de los Estados Unidos:
Hay muchos más aspectos de la publicación de una aplicación de Xamarin.Android que pueden tratarse en esta
guía. Para más información sobre cómo publicar la aplicación en Google Play, vea Welcome to the Google Play
Developer Console Help Center (Bienvenido al centro de ayuda de Google Play Developer Console).

Filtros de Google Play


Cuando los usuarios exploran el sitio web de Google Play para aplicaciones, pueden buscar todas las aplicaciones
publicadas. Cuando los usuarios exploran Google Play desde un dispositivo Android, los resultados son
ligeramente diferentes. Los resultados se filtrarán según la compatibilidad con el dispositivo que se usa. Por
ejemplo, si una aplicación debe enviar mensajes SMS, Google Play no mostrará esa aplicación a ningún
dispositivo que no pueda enviar mensajes SMS. Los filtros que se aplican a una búsqueda se crean a partir de lo
siguiente:
1. La configuración de hardware del dispositivo.
2. Las declaraciones del archivo de manifiesto de las aplicaciones.
3. El operador que se usa (si lo hubiera).
4. La ubicación del dispositivo.
Es posible agregar elementos al manifiesto de la aplicación para ayudar a controlar cómo se filtra la aplicación en
Google Play Store. A continuación se recogen los elementos del manifiesto y los atributos que se pueden usar
para filtrar aplicaciones:
supports-screen: Google Play usa los atributos para determinar si se puede implementar una aplicación en
un dispositivo en función del tamaño de la pantalla. Google Play supondrá que Android puede adaptar un
diseño más pequeño en pantallas más grandes, pero no a la inversa. Así pues, una aplicación que declare
su compatibilidad con pantallas normales aparecerá en las búsquedas para pantallas grandes, pero no para
pantallas pequeñas. Si una determinada aplicación Xamarin.Android no proporciona un elemento
<supports-screen> en el archivo de manifiesto, Google Play supondrá que todos los atributos tienen el
valor true y que la aplicación admite todos los tamaños de pantalla. Este elemento se debe agregar
manualmente a AndroidManifest.xml.
uses-configuration: este elemento del manifiesto se usa para solicitar determinadas características de
hardware, como el tipo de teclado, los dispositivos de navegación, una pantalla táctil, etc. Este elemento se
debe agregar manualmente a AndroidManifest.xml.
uses-feature: este elemento del manifiesto declara características de hardware o de software con las que
debe contar un dispositivo para que la aplicación funcione. Este atributo es solo informativo. Google Play
no mostrará la aplicación en los dispositivos que no cumplan este filtro. Aun así, la aplicación se puede
instalar de otras maneras (manualmente o bien descargándola). Este elemento se debe agregar
manualmente a AndroidManifest.xml.
uses-library: este elemento especifica que ciertas bibliotecas compartidas deben estar presentes en el
dispositivo (por ejemplo, Google Maps). Este elemento también se puede especificar con
Android.App.UsesLibraryAttribute . Por ejemplo:

[assembly: UsesLibrary("com.google.android.maps", true)]

uses-permission: este elemento se usa para deducir ciertas características de hardware necesarias para
ejecutar la aplicación que tal vez no se declararon correctamente con un elemento <uses-feature> . Por
ejemplo, si una aplicación solicita permiso para usar la cámara, Google Play presupone que los
dispositivos deben tener una cámara, aunque no haya ningún elemento <uses-feature> que declare la
cámara. Este elemento se puede establecer con Android.App.UsesPermissionsAttribute . Por ejemplo:

[assembly: UsesPermission(Manifest.Permission.Camera)]

uses-sdk: este elemento se usa para declarar el nivel mínimo de la API de Android necesario para la
aplicación. Este elemento se puede establecer en las opciones de Xamarin.Android de un proyecto de
Xamarin.Android.
compatible-screens: este elemento se usa para filtrar las aplicaciones que no coinciden con el tamaño de
pantalla y la densidad especificados por este elemento. La mayoría de las aplicaciones no deben usar este
filtro. Está diseñado para juegos o aplicaciones de alto rendimiento que precisan controles estrictos sobre
la distribución de las aplicaciones. Se recomienda el uso del atributo <support-screen> mencionado
anteriormente.
supports-gl-texture: este elemento se usa para declarar formaciones de compresión de textura GL
necesarias para la aplicación. La mayoría de las aplicaciones no deben usar este filtro. Está diseñado para
juegos o aplicaciones de alto rendimiento que precisan controles estrictos sobre la distribución de las
aplicaciones.
Para más información sobre cómo configurar el manifiesto de la aplicación, vea el tema de Android Manifiesto de
la aplicación.
Publicación en Amazon Appstore
11/07/2019 • 2 minutes to read • Edit Online

Amazon Mobile App Distribution Program permite a los desarrolladores de aplicaciones móviles publicar sus
aplicaciones en Amazon. Esta sección describe brevemente la Tienda Apps de Amazon para Android.
Amazon no limita el tamaño de los APK. En cambio, si un APK supera los 30 MB, usará FTP para la distribución en
lugar de Amazon Mobile App Distribution Portal.

Envío de aplicaciones: información binaria


Enviar una aplicación a la Tienda Apps de Amazon es un proceso similar al de enviar una aplicación a Google Play.
Las aplicaciones distribuidas mediante Amazon requieren los siguientes recursos:
Icono – Es un archivo .png de 114 x 114 con un fondo transparente. Es obligatorio.
Miniatura – Es una versión más grande del icono anterior. Es de 512 x 512 píxeles con un fondo transparente.
Este icono también es obligatorio.
Capturas de pantalla – Amazon requiere un mínimo de tres y un máximo de 10 capturas de pantalla. Las
capturas de pantalla deben ser de 1024 píxeles de ancho x 600 píxeles de alto u 800 píxeles de ancho x 480
píxeles de alto. Se admiten los formatos .png y .jpg.
Imagen promocional – Para que una aplicación aparezca destacada en ubicaciones promocionales (como la
página principal), se puede enviar de forma opcional una imagen promocional. Debe ser un archivo .png o .jpg
de 1024 píxeles de ancho x 500 píxeles de alto, con orientación horizontal. No puede tener ninguna animación.
Se pueden proporcionar actualizaciones a cinco vídeos.

Proceso de aprobación
Una vez que se ha enviado una aplicación, pasa por un proceso de aprobación. Amazon revisará la aplicación para
asegurarse de que funciona como se detalla en la descripción del producto, no pone los datos de los clientes en
riesgo y no afectará al funcionamiento del dispositivo. Una vez completado el proceso de aprobación, Amazon
enviará una notificación y distribuirá la aplicación.
Publicación de forma independiente
11/07/2019 • 6 minutes to read • Edit Online

Es posible publicar una aplicación sin usar ninguno de los mercados de Android existentes. En esta sección se
explican estos métodos de publicación alternativos y los niveles de licencia de Xamarin.Android.

Licencias de Xamarin
Existen varias licencias para el desarrollo, la implementación y la distribución de aplicaciones de Xamarin.Android:
Visual Studio Community – Para estudiantes, equipos pequeños y desarrolladores de OSS que usan
Windows.
Visual Studio Professional – Para desarrolladores individuales o equipos pequeños (solo Windows). Esta
licencia ofrece una suscripción estándar o en la nube y no tiene restricciones de uso.
Visual Studio Enterprise – Para equipos de cualquier tamaño (solo Windows). Esta licencia incluye
funcionalidades empresariales, una suscripción estándar o en la nube.
Visite la visualstudio.com para descargar las ediciones Community o para obtener más información sobre la
compra de las ediciones Professional y Enterprise.

Permitir la instalación desde orígenes desconocidos


De forma predeterminada, Android impide que los usuarios descarguen e instalen aplicaciones desde ubicaciones
distintas de Google Play. Para permitir la instalación desde otros orígenes, el usuario debe habilitar la opción
Fuentes desconocidas en el dispositivo antes de intentar instalar una aplicación. Esta opción se encuentra en
Ajustes > Seguridad, como se muestra en la imagen siguiente:
IMPORTANT
Algunos proveedores de red podrían impedir la instalación de aplicaciones desde orígenes desconocidos,
independientemente de esta configuración.

Publicar por correo electrónico


Una forma rápida y fácil de distribuir una aplicación a los usuarios consiste en adjuntar el APK de lanzamiento a
un correo electrónico. Cuando el usuario abra el correo electrónico en un dispositivo Android, Android reconocerá
el APK adjunto y mostrará el botón Instalar, como se muestra en la siguiente imagen:

Aunque la distribución por correo electrónico es sencilla, incluye algunas protecciones contra la piratería o la
distribución no autorizada. Es mejor que la reserve para los casos en que los destinatarios de la aplicación son
pocos y confía en que no la distribuyan.

Publicar por web


Es posible distribuir una aplicación a través de un servidor web. Para ello, cargue la aplicación en el servidor web y,
después, proporcione a los usuarios un vínculo de descarga. Cuando un dispositivo Android examina un vínculo y,
después, descarga la aplicación, esta se instalará automáticamente una vez que se complete la descarga.

Instalar un APK de forma manual


La instalación manual es la tercera opción para instalar aplicaciones. Para llevar a cabo la instalación manual de
una aplicación:
1. Distribuya una copia del APK al usuario – Por ejemplo, esta copia se puede distribuir en un CD o en una
unidad flash USB.
2. El usuario instala la aplicación en un dispositivo Android – Use la herramienta de línea de comandos
Android Debug Bridge (adb). adb es una herramienta de línea de comandos versátil que permite la
comunicación con una instancia del emulador o con un dispositivo Android. adb está incluido en Android SDK;
lo encontrará en el directorio /platform -tools/.
El dispositivo Android debe estar conectado con un cable USB al equipo. Los equipos Windows también pueden
requerir controladores USB adicionales del proveedor del teléfono para que adb los pueda reconocer. Las
instrucciones de instalación de estos controladores USB adicionales no se tratan en este documento.
Antes de emitir un comando adb, es útil saber si hay dispositivos o instancias del emulador conectados y, en ese
caso, cuáles son. Puede ver una lista de todo lo que está conectado mediante el comando devices , como se
muestra en el siguiente fragmento de código:

$ adb devices
List of devices attached
0149B2EC03012005device

Una vez que se hayan confirmado los dispositivos conectados, puede instalar la aplicación mediante la emisión del
comando install con adb:

$ adb install <path-to-apk>

El fragmento de código siguiente es un ejemplo de cómo instalar una aplicación en un dispositivo conectado:

$ adb install helloworld.apk


3772 KB/s (3013594 bytes in 0.780s)
pkg: /data/local/tmp/helloworld.apk
Success

Si la aplicación ya está instalada, adb install no podrá instalar el APK y notificará un error, como se muestra en el
ejemplo siguiente:

$ adb install helloworld.apk


4037 KB/s (3013594 bytes in 0.728s)
pkg: /data/local/tmp/helloworld.apk
Failure [INSTALL_FAILED_ALREADY_EXISTS]

Será necesario desinstalar la aplicación del dispositivo. Primero, ejecute el comando adb uninstall :

adb uninstall <package_name>

El fragmento siguiente es un ejemplo de cómo desinstalar una aplicación:

$ adb uninstall mono.samples.helloworld


Success
Instalar Xamarin.Android como una aplicación del
sistema
11/07/2019 • 6 minutes to read • Edit Online

En esta guía se analizan las diferencias entre una aplicación del sistema y una aplicación de usuario, y se describe
cómo instalar una aplicación Xamarin.Android como una aplicación del sistema. Esta guía se aplica a los autores
de imágenes ROM personalizadas de Android. No se explica cómo crear una ROM personalizada.

Aplicación del sistema


Los autores de imágenes ROM de Android personalizadas o los fabricantes de dispositivos Android pueden querer
incluir una aplicación Xamarin.Android como una aplicación del sistema al distribuir una ROM o un dispositivo.
Una aplicación del sistema es una aplicación que se considera importante para el funcionamiento del dispositivo o
que proporciona funcionalidad que el autor de la ROM personalizada siempre desea que esté disponible.
Las aplicaciones del sistema se instalan en la carpeta /system/app/ (un directorio de solo lectura en el sistema de
archivos) y el usuario no puede eliminarla ni moverla a menos que el usuario tenga acceso a la raíz. En cambio, una
aplicación que instala el usuario (normalmente desde Google Play o al transferir localmente la aplicación) se
conoce como una aplicación de usuario. Las aplicaciones de usuario pueden ser eliminadas por el usuario y, en
muchos casos, pueden moverse a una ubicación diferente del dispositivo (por ejemplo, algún tipo de
almacenamiento externo).
Las aplicaciones del sistema se comportan exactamente igual que las aplicaciones de usuario, pero tienen las
siguientes notables excepciones:
Las aplicaciones del sistema son actualizables igual que una aplicación de usuario normal. Sin embargo,
como siempre existe una copia de la aplicación en /system/app/, siempre es posible revertir la aplicación a
la versión original.
Las aplicaciones del sistema pueden tener concedidos determinados permisos solo del sistema que no están
disponibles para una aplicación de usuario. Un ejemplo de un permiso solo del sistema es
BLUETOOTH_PRIVILEGED , que permite que las aplicaciones se emparejen con dispositivos Bluetooth sin
ninguna interacción del usuario.
Una aplicación Xamarin.Android se puede distribuir como una aplicación del sistema. Además de proporcionar un
APK a la ROM personalizada, hay dos bibliotecas compartidas, libmonodroid.so y libmonosgen 2.0.so que
deben copiarse manualmente del APK en el sistema de archivos de la imagen ROM. En esta guía se explican los
pasos implicados.

Restricciones
Esta guía se aplica a los autores de imágenes ROM personalizadas de Android. No se explica cómo crear una ROM
personalizada.
En esta guía se supone que está familiarizado con el empaquetado de un APK de lanzamiento de una aplicación
Xamarin.Android y que conoce las arquitecturas de CPU de las aplicaciones Android.

Instalar una aplicación Xamarin.Android como una aplicación del


sistema
En los pasos siguientes se describe cómo instalar una aplicación Xamarin.Android como una aplicación del
sistema.
1. Empaquete un APK de lanzamiento de la aplicación Xamarin.Android: este paso se describe con más
detalle en la guía Publicar una aplicación.
2. Extraiga las bibliotecas compartidas del APK: mediante cualquier utilidad de compresión, abra el
archivo APK y examine el contenido de la carpeta /lib/. Esta carpeta tendrá un subdirectorio para cada
interfaz binaria de aplicación (ABI) que sea compatible con la aplicación; el contenido de esta carpeta
incluirá todas las bibliotecas compartidas que requiere la aplicación en esa ABI en particular:

En la captura de pantalla anterior, solo hay una ABI admitida (armeabi-v7a) que contiene dos archivos .so
que requiere la aplicación. Tenga en cuenta que solo es necesario extraer los archivos de ABI que son
adecuados para el dispositivo o la arquitectura de destino de la ROM del dispositivo; es decir, no copie los
archivos .so de la carpeta x86 a un dispositivo o ROM armeabi-v7a.
3. Copie los archivos .so en /system/lib: copie los archivos .so que se extrajeron del APK en el paso
anterior en la carpeta /system/lib/ de la ROM personalizada.
4. Copie el archivo APK en /system/app: el paso final consiste en copiar el archivo APK en la carpeta
/system/app en la ROM.

Resumen
En esta guía se describe la diferencia entre una aplicación del sistema y una aplicación de usuario, y se explica
cómo instalar una aplicación Xamarin.Android como una aplicación del sistema.

Vínculos relacionados
Publicar una aplicación
Arquitecturas de CPU
BLUETOOTH_PRIVILEGED
ABI Management
Conceptos avanzados y funcionamiento interno
13/07/2019 • 2 minutes to read • Edit Online

Esta sección contiene temas que explican la arquitectura, diseño de API y las limitaciones de Xamarin.Android.
Además, incluye temas que explican su implementación de la colección de elementos no utilizados y los
ensamblados que están disponibles en Xamarin.Android. Dado que es Xamarin.Android abierto, también es posible
comprender el funcionamiento interno de Xamarin.Android mediante el examen de su código fuente.

Arquitectura
En este artículo se explica la arquitectura subyacente de una aplicación de Xamarin.Android. Explica cómo ejecutan
las aplicaciones de Xamarin.Android dentro de un entorno de ejecución Mono junto con el tiempo de ejecución
Android Máquina Virtual y se explican conceptos claves como Android contenedores RCW y contenedores
administrados.

Diseño de API
El núcleo de bibliotecas de clases Base que forman parte de Mono, además de Xamarin.Android se suministra con
enlaces para distintas API de Android permitir a los desarrolladores crear aplicaciones nativas de Android con
Mono.
En el núcleo de Xamarin.Android existe es un motor de interoperabilidad ese mundo puentes de C# con el mundo
de Java y ofrece a los desarrolladores con acceso a las API de Java desde C# o en otros lenguajes. NET.

Ensamblados
Xamarin.Android se suministra con varios ensamblados. Como Silverlight es un subconjunto de los ensamblados
de .NET de escritorio extendido, Xamarin.Android también es un subconjunto de las distintas Silverlight y
ensamblados de .NET de escritorio extendido.
Arquitectura
16/08/2019 • 19 minutes to read • Edit Online

Las aplicaciones de Xamarin. Android se ejecutan en el entorno de ejecución de mono. Este entorno de ejecución
se ejecuta en paralelo con la máquina virtual en tiempo de ejecución (ART) de Android. Ambos entornos en
tiempo de ejecución se ejecutan sobre el kernel de Linux y exponen varias API al código de usuario que permite a
los desarrolladores tener acceso al sistema subyacente. El entorno de ejecución mono se escribe en el lenguaje C.
Puede usar el sistema, System.IO, System.net y el resto de las bibliotecas de clases .net para tener acceso a las
instalaciones subyacentes del sistema operativo Linux.
En Android, la mayoría de los recursos del sistema como audio, gráficos, OpenGL y telefonía no están disponibles
directamente en las aplicaciones nativas, solo se exponen a través de las API de Java en tiempo de ejecución de
Android que residen en uno de los espacios de nombres Java. * o Android . * espacios de nombres. La
arquitectura es aproximadamente similar a la siguiente:

Los desarrolladores de Xamarin. Android acceden a las distintas características del sistema operativo mediante
una llamada a las API de .NET que conocen (para el acceso de bajo nivel) o mediante las clases expuestas en los
espacios de nombres de Android, que proporcionan un puente a las API de Java que expone el tiempo de
ejecución de Android.
Para obtener más información sobre cómo se comunican las clases de Android con las clases en tiempo de
ejecución de Android, consulte el documento de diseño de la API .

Paquetes de aplicación
Los paquetes de aplicación de Android son contenedores ZIP con una extensión de archivo . apk . Los paquetes
de aplicación de Xamarin. Android tienen la misma estructura y el mismo diseño que los paquetes de Android
normales, con las siguientes adiciones:
Los ensamblados de aplicación (que contienen Il) se almacenan sin comprimir en la carpeta de
ensamblados . Durante el inicio del proceso en la versión, la . apk es mmap () Ed en el proceso y los
ensamblados se cargan desde la memoria. Esto permite el inicio de la aplicación más rápido, ya que no es
necesario extraer los ensamblados antes de la ejecución.
Nota: No se puede confiar en la información de ubicación del ensamblado como Assembly. Location y
Assembly. codebase en compilaciones de versión. No existen como entradas de sistema de archivos
distintas y no tienen ninguna ubicación utilizable.
Las bibliotecas nativas que contienen el entorno de ejecución mono están presentes dentro de . apk . Una
aplicación de Xamarin. Android debe contener bibliotecas nativas para las arquitecturas de Android
deseadas o de destino, por ejemplo, armeabi , armeabi-v7a , x86 . Las aplicaciones de Xamarin. Android no
se pueden ejecutar en una plataforma a menos que contenga las bibliotecas en tiempo de ejecución
adecuadas.
Las aplicaciones de Xamarin. Android también contienen contenedores de Android a los que se puede llamar para
permitir que Android llame a código administrado.

Contenedores que se pueden llamar de Android


Los contenedores a los que se puede llamar de Android son un puente JNI que se usan cada vez que el
entorno de tiempo de ejecución de Android necesita invocar código administrado. Los contenedores a los que
se puede llamar de Android son cómo se pueden invalidar los métodos virtuales y se pueden implementar
interfaces de Java. Vea el documento información general sobre la integración de Java para obtener más
información.

Contenedores a los que se puede llamar administrados


Los contenedores a los que se puede llamar administrados son un puente de JNI que se usa siempre que el
código administrado necesita invocar código de Android y proporcionar compatibilidad para invalidar los
métodos virtuales e implementar interfaces de Java. Todos los espacios de nombres de Android. * y relacionados
son contenedores a los que se puede llamar y que se generan mediante el enlace. jar. Los contenedores a los que
se puede llamar administrados son responsables de la conversión entre los tipos administrados y Android, e
invocando los métodos de la plataforma Android subyacentes a través de JNI.
Cada contenedor administrado al que se puede llamar contiene una referencia global de Java, a la que se puede
tener acceso a través de la propiedad Android. Runtime. IJavaObject. Handle . Las referencias globales se utilizan
para proporcionar la asignación entre las instancias de Java y las instancias administradas. Las referencias
globales son un recurso limitado: los emuladores permiten que solo existan referencias globales 2000 a la vez,
mientras que la mayoría del hardware permite que existan más de 52.000 referencias globales a la vez.
Para hacer un seguimiento de Cuándo se crean y destruyen referencias globales, puede establecer la propiedad
del sistema Debug. mono. log en contenga Gref.
Las referencias globales se pueden liberar explícitamente mediante una llamada a java. lang. Object. Dispose () en
el contenedor al que se puede llamar administrado. Esto eliminará la asignación entre la instancia de Java y la
instancia administrada y permitirá la recopilación de la instancia de Java. Si se vuelve a tener acceso a la instancia
de Java desde el código administrado, se creará un nuevo contenedor al que se puede llamar administrado.
Se debe tener cuidado al desechar los contenedores que se pueden llamar administrados si la instancia se puede
compartir accidentalmente entre subprocesos, ya que si se elimina la instancia, afectará a las referencias de otros
subprocesos. Para obtener la máxima seguridad Dispose() , solo las instancias que se han new asignado a través
de los métodos o desde los métodos que sabe que siempre asignan nuevas instancias y no las instancias
almacenadas en caché, lo que puede provocar un uso compartido accidental de instancias entre ThreadPool.

Subclases de contenedor con llamadas administradas


Las subclases de contenedor a las que se puede llamar administradas son el lugar en el que puede residir toda la
lógica específica de la aplicación "interesante". Entre ellas se incluyen las subclases de Android. app. Activity
personalizadas (por ejemplo, el tipo Activity1 en la plantilla de proyecto predeterminada). (Concretamente, se
trata de subclases java. lang. Object que no contienen un atributo personalizado RegisterAttribute o
RegisterAttribute. DoNotGenerateAcw es false, que es el valor predeterminado).
Como los contenedores a los que se puede llamar administrados, las subclases de contenedor a las que se puede
llamar administradas también contienen una referencia global, accesible a través de la propiedad java. lang.
Object. Handle . Al igual que con los contenedores a los que se puede llamar administrados, las referencias
globales se pueden liberar explícitamente llamando a java. lang. Object. Dispose (). A diferencia de los
contenedores a los que se puede llamar administrados, se debe tener especial cuidado antes de desechar dichas
instancias, ya que la toma de Dispose () de la instancia interrumpirá la asignación entre la instancia de Java (una
instancia de un contenedor de Android al que se puede llamar) y la administrada repetición.
Activación de Java
Cuando se crea un contenedor de Android Callable (ACW ) a partir de Java, el constructor de C# ACW hará que se
invoque el constructor correspondiente. Por ejemplo, ACW para MainActivity contendrá un constructor
predeterminado que invocará el constructor predeterminado de MainActivity. (Esto se hace a través de la llamada
a TypeManager. Activate () dentro de los constructores ACW ).
Hay otra signatura de constructor de consecuencia: el constructor (IntPtr, JniHandleOwnership ) . El constructor
(IntPtr, JniHandleOwnership ) se invoca cada vez que un objeto de Java se expone a código administrado y es
necesario construir un contenedor administrado al que se puede llamar para administrar el identificador de JNI.
Normalmente, esto se hace automáticamente.
Hay dos escenarios en los que el constructor (IntPtr, JniHandleOwnership ) se debe proporcionar manualmente en
una subclase de contenedor invocable administrada:
1. Se ha subclase de Android. app. Application . La aplicación es especial; nunca se invocará el constructor de
la configuración predeterminada y, en su lugar, se debe proporcionar el constructor (IntPtr,
JniHandleOwnership).
2. Invocación de método virtual de un constructor de clase base.
Tenga en cuenta que (2) es una abstracción de fugas. En Java, como en C#, las llamadas a métodos virtuales
desde un constructor siempre invocan la implementación de método más derivada. Por ejemplo, el constructor
TextView (Context, AttributeSet, int) invoca el método virtual TextView. getDefaultMovementMethod (), que está
enlazado como la propiedad TextView. DefaultMovementMethod. Por lo tanto, si un tipo LogTextBox se tratara de
(1) TextViewde la subclase, (2) invalida TextView. DefaultMovementMethody (3) activa una instancia de esa clase a
través de XML, la propiedad DefaultMovementMethod reemplazada sería se invoca antes de que el constructor
de ACW tuviera la oportunidad de ejecutarse y se produciría C# antes de que el constructor tuviera la
oportunidad de ejecutarse.
Esto se admite creando instancias de una instancia de LogTextBox a través del constructor LogTextView (IntPtr,
JniHandleOwnership) cuando la instancia de ACW LogTextBox escribe primero código administrado y, a
continuación, invocando el LogTextBox (Context, IAttributeSet, int) en la misma instancia cuando se ejecuta el
constructor ACW.
Orden de eventos:
1. El XML de diseño se carga en un ContentView.
2. Android crea instancias del gráfico de objetos de diseño y crea una instancia de monodroid. apidemo.
LogTextBox , ACW para LogTextBox .
3. El constructor monodroid. apidemo. LogTextBox ejecuta el constructor Android. widget. TextView .
4. El constructor TextView invoca monodroid. apidemo. LogTextBox. getDefaultMovementMethod () .
5. monodroid. apidemo. LogTextBox. getDefaultMovementMethod () invoca LogTextBox.
n_getDefaultMovementMethod () , que invoca TextView. n_getDefaultMovementMethod () , que invoca
java. lang. Object. GetObject< TextView> (Handle, JniHandleOwnership. DoNotTransfer) .
6. Java. lang. Object. GetObject<TextView>() comprueba si ya existe una instancia correspondiente C# para
el identificador . Si existe, se devuelve. En este escenario, no existe, por lo que Object<.>GetObject t () debe
crear uno.
7. Object. GetObject<T>() busca el constructor LogTextBox (IntPtr, JniHandleOwneship ) , lo invoca, crea una
asignación entre el identificador y la instancia creada, y devuelve la instancia creada.
8. TextView. n_GetDefaultMovementMethod () invoca el captador de la propiedad LogTextBox.
DefaultMovementMethod .
9. El control vuelve al constructor de Android. widget. TextView , que finaliza la ejecución.
10. Se ejecuta el constructor monodroid. apidemo. LogTextBox , invocando TypeManager. Activate () .
11. El constructor LogTextBox (Context, IAttributeSet, int) se ejecuta en la misma instancia creada en (7 ) .
12. Si no se encuentra el constructor (IntPtr, JniHandleOwnership), se producirá una excepción System.
MissingMethodException] (XREF: System. MissingMethodException).
Llamadas a Dispose () prematuras
Hay una asignación entre un identificador de JNI y la instancia C# correspondiente. Java. lang. Object. Dispose ()
interrumpe esta asignación. Si un identificador de JNI entra en el código administrado una vez que se ha
interrumpido la asignación, se parece a la activación de Java y el constructor (IntPtr, JniHandleOwnership ) se
comprobará y se invocará. Si el constructor no existe, se producirá una excepción.
Por ejemplo, dada la siguiente subclase de Ajustador invocable administrada:

class ManagedValue : Java.Lang.Object {

public string Value {get; private set;}

public ManagedValue (string value)


{
Value = value;
}

public override string ToString ()


{
return string.Format ("[Managed: Value={0}]", Value);
}
}

Si creamos una instancia de, Dispose () y hace que se vuelva a crear el contenedor al que se puede llamar:

var list = new JavaList<IJavaObject>();


list.Add (new ManagedValue ("value"));
list [0].Dispose ();
Console.WriteLine (list [0].ToString ());

El programa se determinará:
E/mono ( 2906): Unhandled Exception: System.NotSupportedException: Unable to activate instance of type
Scratch.PrematureDispose.ManagedValue from native handle 4051c8c8 --->
System.MissingMethodException: No constructor found for
Scratch.PrematureDispose.ManagedValue::.ctor(System.IntPtr, Android.Runtime.JniHandleOwnership)
E/mono ( 2906): at Java.Interop.TypeManager.CreateProxy (System.Type type, IntPtr handle,
JniHandleOwnership transfer) [0x00000] in <filename unknown>:0
E/mono ( 2906): at Java.Interop.TypeManager.CreateInstance (IntPtr handle, JniHandleOwnership transfer,
System.Type targetType) [0x00000] in <filename unknown>:0
E/mono ( 2906): --- End of inner exception stack trace ---
E/mono ( 2906): at Java.Interop.TypeManager.CreateInstance (IntPtr handle, JniHandleOwnership transfer,
System.Type targetType) [0x00000] in <filename unknown>:0
E/mono ( 2906): at Java.Lang.Object.GetObject (IntPtr handle, JniHandleOwnership transfer, System.Type
type) [0x00000] in <filename unknown>:0
E/mono ( 2906): at Java.Lang.Object._GetObject[IJavaObject] (IntPtr handle, JniHandleOwnership transfer)
[0x00000

Si la subclase contiene un constructor (IntPtr, JniHandleOwnership ) , se creará una nueva instancia del tipo. Como
resultado, la instancia parecerá "perder" todos los datos de instancia, ya que es una nueva instancia. (Tenga en
cuenta que el valor es null).

I/mono-stdout( 2993): [Managed: Value=]

Solo Dispose () de las subclases de contenedor a las que se puede llamar administradas cuando sepa que el objeto
de Java ya no se va a usar o la subclase no contiene datos de instancia y se ha proporcionado un constructor
(IntPtr, JniHandleOwnership ) .

Inicio de la aplicación
Cuando se inicia una actividad, servicio, etc., Android comprobará primero si ya existe un proceso en ejecución
para hospedar la actividad/servicio, etc. Si no existe tal proceso, se creará un nuevo proceso, se leerá archivo
AndroidManifest. XML y se cargará y se creará una /manifest/application/@android:name instancia del tipo
especificado en el atributo. A continuación, se crea una instancia /manifest/application/provider/@android:name
de todos los tipos especificados por los valores de atributo y se invoca el método ContentProvider. attachInfo%
28) . Xamarin. Android se enlaza en esto agregando un mono. MonoRuntimeProvider ContentProvider archivo
AndroidManifest. XML durante el proceso de compilación. Mono. El método MonoRuntimeProvider. attachInfo ()
es responsable de cargar el tiempo de ejecución de mono en el proceso. Cualquier intento de usar mono antes de
este punto producirá un error. ( Nota: Este es el motivo por el que los tipos de la subclase Android. app.
Application deben proporcionar un constructor (IntPtr, JniHandleOwnership), ya que la instancia de la aplicación
se crea antes de que se pueda inicializar mono.
Una vez completada la inicialización del proceso, se consulta para encontrar el nombre de clase de la
actividad/servicio, AndroidManifest.xml etc. para iniciar. Por ejemplo, el
/manifest/application/activity/@android:name atributo se usa para determinar el nombre de una actividad que se
va a cargar. En el caso de las actividades, este tipo debe heredar Android. app. Activity. El tipo especificado se
carga a través de Class. forName () (que requiere que el tipo sea un tipo de Java, por lo tanto, los contenedores a
los que se puede llamar de Android) y, después, se cree una instancia de él. La creación de una instancia de
contenedor de Android al que se puede llamar desencadenará C# la creación de una instancia del tipo
correspondiente. Después, Android invocará Activity. Create (bundle) , lo que provocará que se invoque la
actividad correspondiente. Create (bundle) y está fuera de las carreras.
Ensamblados disponibles
11/07/2019 • 5 minutes to read • Edit Online

Xamarin.iOS, Xamarin.Android y Xamarin.Mac todos se distribuyen con más de una docena de ensamblados.
Como Silverlight es un subconjunto de los ensamblados de .NET de escritorio extendido, las plataformas
Xamarin también es un subconjunto de las distintas Silverlight y ensamblados de .NET de escritorio extendido.
Las plataformas de Xamarin no son ABI compatible con existentes de los ensamblados compilados para un perfil
diferente. Debe volver a compilar el código fuente para generar ensamblados de destino es el perfil correcto
(igual que es necesario volver a compilar el código fuente para tener como destino Silverlight y 3.5 de .NET por
separado).
Se pueden compilar aplicaciones de Xamarin.Mac en tres modos: uno que usa Xamarin de curah perfil móvil,
Xamarin.Mac .NET Framework 4.5 que permite tener como destino los ensamblados de escritorio completa
existentes y uno compatible que usa la API de .NET se encuentra en un sistema de Mono instalación. Para
obtener más información, consulte nuestra plataformas de destino documentación.

Bibliotecas estándar de .NET


Además de iOS, Android y Mac, enlaces, pueden consumir los proyectos de Xamarin bibliotecas de .NET
Standard.

Bibliotecas de clases portables


También pueden usar los proyectos de Xamarin bibliotecas de clases portables de .NET, aunque esta tecnología
está en desuso en favor de .NET Standard.

Ensamblados admitidos
Estos son los ensamblados disponibles en el Administrador de referencias > ensamblados > Framework
(Visual Studio 2017) y editar referencias > paquetes (Visual Studio para Mac) y su compatibilidad con las
plataformas Xamarin.

COMPATIBILIDAD CON
ENSAMBLADO LA API XAMARIN IOS XAMARIN ANDROID XAMARIN MAC

FSharp.Core.dll ✓ ✓ ✓

l18N.dll Incluye CJK, Oriente, ✓ ✓ ✓


otros, es poco
habitual, oeste

Microsoft.CSharp.dll ✓ ✓ ✓

Mono.CSharp.dll ✓ ✓ ✓

Mono.Data.Sqlite.dll Proveedor de ✓ ✓ ✓
ADO.NET para
SQLite; vea las
limitaciones.
COMPATIBILIDAD CON
ENSAMBLADO LA API XAMARIN IOS XAMARIN ANDROID XAMARIN MAC

Mono.Data.Tds.dll Compatibilidad de ✓ ✓ ✓
protocolo TDS;
utilizado para
System.Data.SqlClient
soporte técnico en
System.Data.

Mono.Dynamic. ✓
Interpreter.dll

Mono.Security.dll API criptográficas. ✓ ✓ ✓

monotouch.dll Este ensamblado ✓


contiene el enlace a la
API CocoaTouch de
C#. Esto solo está
disponible en
proyectos Classic de
iOS.

MonoTouch.Dialog- ✓
1.dll

MonoTouch. ✓
NUnitLite.dll

mscorlib.dll Silverlight ✓ ✓ ✓

OpenTK-1.0.dll El objeto de ✓ ✓ ✓
OpenGL/OpenAL
orientada a servicios
de API, ampliadas
para proporcionar
compatibilidad con
dispositivos de
iPhone.
COMPATIBILIDAD CON
ENSAMBLADO LA API XAMARIN IOS XAMARIN ANDROID XAMARIN MAC

System.dll Silverlight, además de ✓ ✓ ✓


los tipos de los
espacios de nombres
siguientes:
System.Collections.Sp
ecialized
System.
ComponentModel
System.ComponentM
odel.Design
System.Diagnostics
System.IO
System.IO.Compressi
on
System.IO.Compressi
on.FileSystem
System.Net
System.Net.Cache
System.Net.Mail
System.Net.Mime
System.Net.
NetworkInformation
System.Net.Security
System.Net.Sockets
System.Runtime.
InteropServices
System.Runtime.Versi
oning
System.Security.
AccessControl
System.Security.Auth
entication
System.Security.
Cryptography
System.Security.Permi
ssions
System.Threading
System.Timers

System. ✓ ✓ ✓
ComponentModel.
Composition.dll

System. ✓ ✓ ✓
ComponentModel.
DataAnnotations.dll

System.Core.dll Silverlight ✓ ✓ ✓

System.Data.dll .NET 3.5 , con alguna ✓ ✓ ✓


funcionalidad
eliminado.

System.Data.Services. Cliente de oData ✓ ✓ ✓


Client.dll completa.

System.IO. ✓ ✓ ✓
Compression
COMPATIBILIDAD CON
ENSAMBLADO LA API XAMARIN IOS XAMARIN ANDROID XAMARIN MAC

System.IO. ✓ ✓ ✓
Compression.
FileSystem

System.Json.dll Silverlight ✓ ✓ ✓

System.Net.Http.dll ✓ ✓ ✓

System.Numerics.dll ✓ ✓ ✓

System.Runtime. Silverlight ✓ ✓ ✓
Serialization.dll

System. Pila de WCF tal como ✓ ✓ ✓


ServiceModel.dll está presente en
Silverlight

System.ServiceModel. ✓ ✓ ✓
Internals.dll

System.ServiceModel. Silverlight, además de ✓ ✓ ✓


Web.dll los tipos de los
espacios de nombres
siguientes:
Sistema
System.ServiceModel.
Channels
System.ServiceModel.
Description
System.ServiceModel.
Web

System. .NET 3.5; forma parte ✓ ✓ ✓


Transactions.dll de System.Data
admite.

System.Web. Servicios Web básicos ✓ ✓ ✓


Services.dll del perfil de .NET 3.5,
con las características
de servidor quitado.

System.Windows.dll ✓ ✓ ✓

System.Xml.dll .NET 3.5 ✓ ✓ ✓

System.Xml.Linq.dll .NET 3.5 ✓ ✓ ✓

System.Xml.Serializati ✓ ✓ ✓
on.dll
COMPATIBILIDAD CON
ENSAMBLADO LA API XAMARIN IOS XAMARIN ANDROID XAMARIN MAC

Xamarin.iOS.dll Este ensamblado ✓


contiene el enlace a la
API CocoaTouch de
C#. Esto solo se usa
en proyectos de iOS
unificado.

Java.Interop.dll ✓

Mono.Android.dll ✓

Mono.Android. ✓
Export.dll

Mono.Posix.dll ✓

System. ✓
EnterpriseServices.dll

Xamarin.Android. ✓
NUnitLite.dll

Mono.CompilerServic Los programadores ✓


es.SymbolWriter.dll de compiladores.

Xamarin.Mac.dll ✓

System.Drawing.dll System.Drawing no ✓ ✓
se admite en la API
unificadas de
Xamarin.Mac, .NET
4.5 o marcos de
trabajo móviles.
Puede agregarse
compatibilidad de
System.Drawing para
iOS y macOS usando
el sysdrawing
coregraphics
biblioteca
Principios de diseño de la API de Xamarin. Android
19/08/2019 • 24 minutes to read • Edit Online

Además de las bibliotecas de clases base básicas que forman parte de mono, Xamarin. Android incluye enlaces
para varias API de Android que permiten a los desarrolladores crear aplicaciones nativas de Android con mono.
En el núcleo de Xamarin. Android hay un motor de interoperabilidad que C# une el mundo con el mundo de Java
y ofrece a los desarrolladores acceso a C# las API de Java desde u otros lenguajes de .net.

Principios de diseño
Estos son algunos de los principios de diseño para el enlace de Xamarin. Android
Se ajusta a las directrices de diseño de .NET Framework.
Permite a los desarrolladores subclases de clases de Java.
La subclase debe funcionar C# con construcciones estándar.
Derivar de una clase existente.
Llame al constructor base para encadenar.
Los métodos de invalidación deben realizarse con C#el sistema de invalidación de.
Facilite las tareas comunes de Java y las tareas de Java difíciles.
Exponga las propiedades de C# JavaBean como propiedades.
Exponga una API fuertemente tipada:
Aumentar la seguridad de tipos.
Minimice los errores en tiempo de ejecución.
Obtiene el IDE de IntelliSense en los tipos de valor devuelto.
Permite la documentación del menú emergente del IDE.
Anime la exploración en el IDE de las API:
Use alternativas de marco para minimizar la exposición de Classlib de Java.
Exponga C# los delegados (expresiones lambda, métodos anónimos y System. Delegate) en lugar
de las interfaces de un solo método cuando sea adecuado y aplicable.
Proporcionar un mecanismo para llamar a bibliotecas de Java arbitrarias ( Android. Runtime.
JNIEnv).

Ensamblados
Xamarin. Android incluye una serie de ensamblados que constituyen el perfilde monomobile. La página
ensamblados tiene más información.
Los enlaces a la plataforma Android se encuentran en el Mono.Android.dll ensamblado. Este ensamblado
contiene todo el enlace para consumir las API de Android y comunicarse con la máquina virtual en tiempo de
ejecución de Android.
Diseño de enlace
Colecciones
Las API de Android usan las colecciones Java. util exhaustivamente para proporcionar listas, conjuntos y
asignaciones. Estos elementos se exponen mediante las interfaces System. Collections. Generic en nuestro enlace.
Las asignaciones fundamentales son:
Java. util. set<E > se asigna al tipo de sistema <ICollection T >, clase auxiliar Android. Runtime.<JavaSet T
>.
Java. util. List<E > asigna al tipo de sistema<IList T >, clase auxiliar Android. Runtime. JavaList<T >.
java. util. Map < K, V > se asigna al tipo de sistema IDictionary < TKey, TValue >, clase auxiliar Android.
Runtime. JavaDictionary < K, V >.
Java. util. Collection<E > se asigna al tipo de sistema <ICollection T >, clase auxiliar Android. Runtime.
<JavaCollection T >.
Hemos proporcionado clases de aplicación auxiliar para facilitar la serialización de estos tipos de forma más
rápida. Cuando sea posible, se recomienda usar estas colecciones proporcionadas en lugar de la implementación
proporcionada por List<T> el Dictionary<TKey, TValue> marco, como o. Las implementaciones de Android.
Runtime usan internamente una colección de Java nativa y, por lo tanto, no requieren la copia a y desde una
colección nativa al pasar a un miembro de la API de Android.
Puede pasar cualquier implementación de interfaz a un método Android que acepte esa interfaz; por ejemplo,
List<int> pasar un al constructor int>( Context, int<,>IList<int) de ArrayAdapter . Sin embargo, para todas las
implementaciones excepto las implementaciones de Android. Runtime, esto implica copiar la lista de la máquina
virtual mono en la máquina virtual en tiempo de ejecución de Android. Si la lista se cambia más adelante en el
tiempo de ejecución de Android (por ejemplo, mediante la invocación de <ArrayAdapter T>. Add (T) Method),
esos cambios no estarán visibles en el código administrado. JavaList<int> Si se usara, los cambios serían
visibles.
Rephrase, las implementaciones de interfaz de colecciones que no son una de las clases auxiliaresenumeradas
anteriormente solo serializan [in]:

// This fails:
var badSource = new List<int> { 1, 2, 3 };
var badAdapter = new ArrayAdapter<int>(context, textViewResourceId, badSource);
badAdapter.Add (4);
if (badSource.Count != 4) // true
throw new InvalidOperationException ("this is thrown");

// this works:
var goodSource = new JavaList<int> { 1, 2, 3 };
var goodAdapter = new ArrayAdapter<int> (context, textViewResourceId, goodSource);
goodAdapter.Add (4);
if (goodSource.Count != 4) // false
throw new InvalidOperationException ("should not be reached.");

Properties (Propiedades)
Los métodos de Java se transforman en propiedades, si es necesario:
El par T getFoo() de métodos de void setFoo(T) Java y se transforman en la Foo propiedad. Ejemplo:
Activity. Intent.
El método getFoo() Java se transforma en la propiedad foo de solo lectura. Ejemplo: Context.
packagename.
No se generan propiedades de solo establecimiento.
No se generan propiedades si el tipo de propiedad sería una matriz.
Eventos y agentes de escucha
Las API de Android se basan en Java y sus componentes siguen el patrón de Java para enlazar agentes de
escucha de eventos. Este patrón tiende a ser engorroso, ya que requiere que el usuario cree una clase anónima y
declare los métodos que se van a invalidar; por ejemplo, esto es lo que se haría en Android con Java:

final android.widget.Button button = new android.widget.Button(context);

button.setText(this.count + " clicks!");


button.setOnClickListener (new View.OnClickListener() {
public void onClick (View v) {
button.setText(++this.count + " clicks!");
}
});

El código equivalente en C# el uso de eventos sería:

var button = new Android.Widget.Button (context) {


Text = string.Format ("{0} clicks!", this.count),
};
button.Click += (sender, e) => {
button.Text = string.Format ("{0} clicks!", ++this.count);
};

Tenga en cuenta que los dos mecanismos anteriores están disponibles con Xamarin. Android. Puede implementar
una interfaz de escucha y asociarla a View. SetOnClickListener, o puede adjuntar un delegado creado a través de
cualquiera de C# los paradigmas habituales al evento click.
Cuando el método de devolución de llamada del agente de escucha tiene un valor devuelto void, se crean
elementos de API basados en un delegado EventHandler<TEventArgs> . Generamos un evento como el ejemplo
anterior para estos tipos de agente de escucha. Sin embargo, si la devolución de llamada del agente de escucha
devuelve un valor distinto de void y no booleano , no se usan eventos ni EventHandlers. En su lugar, se genera
un delegado específico para la firma de la devolución de llamada y se agregan propiedades en lugar de eventos.
La razón es tratar con el orden de invocación de delegado y el control de devolución. Este enfoque refleja lo que
se hace con la API de Xamarin. iOS.
C#los eventos o propiedades solo se generan automáticamente si el método de registro de eventos de Android:
1. Tiene un set prefijo, por ejemplo, setOnClickListener.
2. Tiene un void tipo de valor devuelto.
3. Acepta solo un parámetro, el tipo de parámetro es una interfaz, la interfaz solo tiene un método y el
nombre de la interfaz Listener termina en, por ejemplo, el agente de escuchaView. OnClick.

Además, si el método de interfaz del agente de escucha tiene un tipo de valor devuelto booleano en lugar de
void, la subclase EventArgs generada contendrá una propiedad controlada . El valor de la propiedad Handled se
utiliza como valor devuelto para el método Listener y su valor true predeterminado es.
Por ejemplo, el método Android View. setOnKeyListener () acepta la interfaz View. OnKeyListener y el método
View. OnKeyListener. onKey (View, int, KeyEvent) tiene un tipo de valor devuelto booleano. Xamarin. Android
genera un evento View. KeyPress correspondiente, que es una vista<EventHandler. KeyEventArgs>. A su vez, la
clase KeyEventArgs tiene una propiedad View. KeyEventArgs. Handled , que se utiliza como valor devuelto para el
método View. OnKeyListener. onKey () .
Tenemos previsto agregar sobrecargas para otros métodos y constructores para exponer la conexión basada en el
delegado. Además, los agentes de escucha con varias devoluciones de llamada requieren una inspección adicional
para determinar si la implementación de devoluciones de llamada individuales es razonable, por lo que se
convierten a medida que se identifican. Si no hay ningún evento correspondiente, los agentes de escucha deben
usarse en, pero traiga el que cree podría tener el uso del C#delegado en nuestra atención. También hemos
realizado algunas conversiones de interfaces sin el sufijo "Listener" cuando estaba claro que se beneficiarían de
una alternativa de delegado.
Todas las interfaces de agentes de escucha implementan el Android.Runtime.IJavaObject interfaz, debido a los
detalles de implementación del enlace, por lo que las clases de agente de escucha deben implementar esta
interfaz. Esto se puede hacer implementando la interfaz del agente de escucha en una subclase de java. lang.
Object o cualquier otro objeto de Java ajustado, como una actividad de Android.
Runnables
Java emplea la interfaz java. lang. Runnable para proporcionar un mecanismo de delegación. La clase java. lang.
Thread es un consumidor destacado de esta interfaz. Android también ha empleado la interfaz en la API. Activity.
runOnUiThread () y View.post () son ejemplos importantes.
La Runnable interfaz contiene un único método void, Run (). Por lo tanto, se presta a enlazar C# como un
delegado System. Action . Hemos proporcionado sobrecargas en el enlace Action que aceptan un parámetro
para todos los miembros de la API que consumen un Runnable en la API nativa, por ejemplo, Activity.
RunOnUiThread () y View.post ().
Hemos dejado las sobrecargas de IRunnable en lugar de reemplazarlas, ya que varios tipos implementan la
interfaz y, por tanto, se pueden pasar como runnables directamente.
Clases internas
Java tiene dos tipos diferentes de clases anidadas: clases anidadas estáticas y clases no estáticas.
Las clases anidadas estáticas de Java C# son idénticas a los tipos anidados.
Las clases anidadas no estáticas, también denominadas clases internas, son significativamente diferentes.
Contienen una referencia implícita a una instancia de su tipo envolvente y no pueden contener miembros
estáticos (entre otras diferencias fuera del ámbito de esta información general).
Cuando se trata de un enlace C# y uso, las clases anidadas estáticas se tratan como tipos anidados normales.
Mientras tanto, las clases internas tienen dos diferencias importantes:
1. La referencia implícita al tipo contenedor se debe proporcionar explícitamente como un parámetro de
constructor.
2. Al heredar de una clase interna, la clase interna debe estar anidada dentro de un tipo que herede del tipo
contenedor de la clase interna base y el tipo derivado debe proporcionar un constructor del mismo tipo
que el C# tipo contenedor.
Por ejemplo, considere la clase interna Android. Service. Wallpaper. WallpaperService. Engine . Dado que es una
clase interna, el constructor WallpaperService. Engine () toma una referencia a una instancia de WallpaperService
(Compare y contrasta con el constructor Java WallpaperService. Engine (), que no toma ningún parámetro).
Una derivación de ejemplo de una clase interna es CubeWallpaper. CubeEngine:
class CubeWallpaper : WallpaperService {
public override WallpaperService.Engine OnCreateEngine ()
{
return new CubeEngine (this);
}

class CubeEngine : WallpaperService.Engine {


public CubeEngine (CubeWallpaper s)
: base (s)
{
}
}
}

Observe cómo CubeWallpaper.CubeEngine está anidado dentro CubeWallpaper de CubeWallpaper , hereda de la


clase contenedora WallpaperService.Engine de y CubeWallpaper.CubeEngine tiene un constructor que toma el tipo
CubeWallpaper declarativo, en este caso, todo tal como se especificó anteriormente.

Interfaces
Las interfaces Java pueden contener tres conjuntos de miembros, dos de los cuales causan C#problemas de:
1. Métodos
2. Tipos
3. Fields
Las interfaces de Java se traducen en dos tipos:
1. Una interfaz (opcional) que contiene declaraciones de método. Esta interfaz tiene el mismo nombre que la
interfaz Java, con la excepción de que también tiene un prefijo ' I '.
2. Una clase estática (opcional) que contiene los campos declarados dentro de la interfaz java.
Los tipos anidados se "reubican" para ser elementos del mismo nivel de la interfaz envolvente en lugar de tipos
anidados, con el nombre de la interfaz envolvente como prefijo.
Por ejemplo, considere la interfaz Android. os. comparable. La interfaz empaquetable contiene métodos, tipos
anidados y constantes. Los métodos de interfaz que se pueden empaquetar se colocan en la interfaz de Android.
os. IParcelable . Las constantes de interfaz que se pueden empaquetar se colocan en el tipo Android. os.
ParcelableConsts . Los tipos anidados Android. os. subClassLoaderCreators<. T > y Android. os. Parcel.<Creator t
> no están enlazados actualmente debido a las limitaciones de nuestra compatibilidad con genéricos; si se
admiten, debería estar presente como las interfaces Android. os. IParcelableClassLoaderCreator y Android. os.
IParcelableCreator . Por ejemplo, la interfaz anidada Android. os. IBinder. DeathRecipient está enlazada como la
interfaz Android. os. IBinderDeathRecipient .

NOTE
A partir de Xamarin. Android 1,9, las constantes de la interfaz de Java se duplican en un esfuerzo por simplificar el traslado
de código Java. Esto ayuda a mejorar el traslado del código Java que se basa en las constantes de la interfaz del proveedor
de Android .

Además de los tipos anteriores, hay cuatro cambios más:


1. Se genera un tipo con el mismo nombre que la interfaz de Java para contener constantes.
2. Los tipos que contienen constantes de interfaz también contienen todas las constantes que proceden de las
interfaces Java implementadas.
3. Todas las clases que implementan una interfaz de Java que contiene constantes obtienen un nuevo tipo
InterfaceConsts anidado que contiene constantes de todas las interfaces implementadas.
4. El tipo de desventajas es ahora obsoleto.
En el caso de la interfaz Android. os. recreable, esto significa que ahora habrá un tipo Android. os. que se puede
empaquetar para contener las constantes. Por ejemplo, la constante parcelable. CONTENTS_FILE_DESCRIPTOR
se enlazará como la constante Parcel. ContentsFileDescriptor , en lugar de como la constante ParcelableConsts.
ContentsFileDescriptor .
En el caso de las interfaces que contienen constantes que implementan otras interfaces que contienen todavía
más constantes, ahora se genera la Unión de todas las constantes. Por ejemplo, la interfaz Android. Provider.
mediastore. video. videocolumns implementa la interfaz Android. Provider. mediastore. MediaColumns . Sin
embargo, antes de 1,9, el tipo Android. Provider. mediastore. video. VideoColumnsConsts no tiene forma de
acceder a las constantes declaradas en Android. Provider. mediastore. MediaColumnsConsts. Como resultado, la
expresión Java mediastore. video. Videocolumns. title debe estar enlazada a la C# expresión mediastore. video.
MediaColumnsConsts. title , que es difícil de detectar sin leer una gran cantidad de documentación de Java. En
1,9, la expresión C# equivalente será mediastore. video. videocolumns. title.
Además, tenga en cuenta el tipo Android. os. bundle , que implementa la interfaz que se puede empaquetar de
Java. Puesto que implementa la interfaz, se puede obtener acceso a todas las constantes de esa interfaz "a" a
través del tipo de agrupación, por ejemplo, bundle. CONTENTS_FILE_DESCRIPTOR es una expresión Java
perfectamente válida. Anteriormente, para migrar esta expresión C# a, sería necesario examinar todas las
interfaces que se implementan para ver de qué tipo procede CONTENTS_FILE_DESCRIPTOR . A partir de
Xamarin. Android 1,9, las clases que implementan interfaces de Java que contienen constantes tendrán un tipo
InterfaceConsts anidado, que contendrá todas las constantes de interfaz heredadas. Esto permitirá convertir
bundle. CONTENTS_FILE_DESCRIPTOR en bundle. InterfaceConsts. ContentsFileDescriptor.
Por último, los tipos con un sufijo de inconvenientes como Android. os. ParcelableConsts ahora están obsoletos,
además de los tipos anidados de InterfaceConsts recién incorporados. Se quitarán en Xamarin. Android 3,0.

Recursos
Las imágenes, las descripciones de diseño, los blobs binarios y los diccionarios de cadenas se pueden incluir en la
aplicación como archivos de recursos. Varias API de Android están diseñadas para funcionar en los
identificadores de recursos en lugar de tratar directamente con imágenes, cadenas o blobs binarios.
Por ejemplo, una aplicación de Android de ejemplo que contiene un diseño de main.axml la interfaz de usuario (),
una strings.xml cadena de tabla de internacionalización () y algunos iconos ( drawable-*/icon.png ) mantendrían
sus recursos en el directorio "Resources" de la aplicación:

Resources/
drawable-hdpi/
icon.png

drawable-ldpi/
icon.png

drawable-mdpi/
icon.png

layout/
main.axml

values/
strings.xml

Las API nativas de Android no funcionan directamente con los nombres de archivo, sino que operan en los
identificadores de recursos. Al compilar una aplicación de Android que usa recursos, el sistema de compilación
empaquetará los recursos para su distribución y Resource generará una clase denominada que contiene los
tokens para cada uno de los recursos incluidos. Por ejemplo, para el diseño de recursos anterior, esto es lo que
expondría la clase de R:

public class Resource {


public class Drawable {
public const int icon = 0x123;
}

public class Layout {


public const int main = 0x456;
}

public class String {


public const int first_string = 0xabc;
public const int second_string = 0xbcd;
}
}

A continuación, usaría Resource.Drawable.icon para drawable/icon.png hacer referencia al archivo


Resource.Layout.main o para hacer layout/main.xml referencia al archivo Resource.String.first_string , o para
hacer referencia a la primera cadena values/strings.xml en el archivo del diccionario.

Constantes y enumeraciones
Las API nativas de Android tienen muchos métodos que toman o devuelven un valor int que se debe asignar a un
campo constante para determinar lo que significa int. Para usar estos métodos, el usuario debe consultar la
documentación para ver qué constantes son valores adecuados, lo que es menor que el ideal.
Por ejemplo, considere Activity. requestWindowFeature (int featureID ).
En estos casos, se desea agrupar las constantes relacionadas en una enumeración de .NET y volver a asignar el
método para tomar la enumeración en su lugar. Al hacerlo, podemos ofrecer una selección de IntelliSense de los
valores posibles.
El ejemplo anterior se convierte en: Activity. RequestWindowFeature (WindowFeatures featureId).
Tenga en cuenta que se trata de un proceso muy manual para averiguar qué constantes pertenecen juntas y qué
API consumen estas constantes. Registre los errores de las constantes usadas en la API que se expresen mejor
como una enumeración.
recolección de elementos no utilizados
19/08/2019 • 31 minutes to read • Edit Online

Xamarin. Android usa el recolector de elementos no utilizados simplede mono. Se trata de un recolector de
elementos no utilizados de marca y barrido con dos generaciones y un espacio de objetos grande, con dos tipos
de colecciones:
Colecciones secundarias (recopila el montón Gen0)
Colecciones principales (recopila GEN1 y montones de espacio de objetos grandes).

NOTE
En ausencia de una colección explícita a través de GC. Las colecciones collect () están a petición, en función de las
asignaciones del montón. No se trata de un sistema de recuento de referencias; los objetos no se recopilarán en cuanto no
haya referencias pendienteso cuando se haya salido de un ámbito. El GC se ejecutará cuando el montón secundario se
quede sin memoria para nuevas asignaciones. Si no hay ninguna asignación, no se ejecutará.

Las colecciones secundarias son baratas y frecuentes, y se usan para recopilar objetos inactivos y asignados
recientemente. Las colecciones secundarias se realizan después de cada pocos MB de objetos asignados. Las
colecciones secundarias se pueden realizar manualmente mediante una llamada a GC. Collect (0)
Las colecciones principales son costosas y menos frecuentes, y se usan para recuperar todos los objetos inactivos.
Las colecciones principales se realizan una vez que se ha agotado la memoria para el tamaño actual del montón
(antes de cambiar el tamaño del montón). Las colecciones principales se pueden realizar manualmente mediante
una llamada a GC. Collect () o mediante una llamada a GC. Collect (int) con el argumento GC. MaxGeneration.

Colecciones de objetos entre máquinas virtuales


Hay tres categorías de tipos de objeto.
Objetos administrados: tipos que no heredan de java. lang. Object , por ejemplo, System. String. Estos se
recopilan normalmente por el GC.
Objetos de Java: Tipos de Java que están presentes en la máquina virtual en tiempo de ejecución de
Android, pero no se exponen a la máquina virtual mono. Estas son aburridas y no se tratarán más adelante.
Estos se recopilan normalmente con la máquina virtual en tiempo de ejecución de Android.
Objetos del mismo nivel: tipos que implementan IJavaObject , por ejemplo, todas las subclases java. lang.
Object y java. lang. Throwable . Las instancias de estos tipos tienen dos "mitades" de un elemento
administrado del mismo nivel y un elemento nativo del mismo nivel. El elemento administrado del mismo
nivel es una C# instancia de la clase. El elemento nativo del mismo nivel es una instancia de una clase de
Java dentro de la máquina C# virtual en tiempo de ejecución de Android y la propiedad IJavaObject.
Handle contiene una referencia global de JNI al elemento nativo del mismo nivel.
Hay dos tipos de elementos del mismo nivel nativos:
Entornos del mismo nivel : Tipos de Java "normales" que no saben nada de Xamarin. Android, por
ejemplo, Android. Content. Context.
Elementos del mismo nivel de usuario : Los contenedores a los que se puede llamar de Android , que se
generan en tiempo de compilación para cada subclase Java. lang. Object presente dentro de la aplicación.
Como hay dos máquinas virtuales dentro de un proceso de Xamarin. Android, hay dos tipos de recolecciones de
elementos no utilizados:
Recopilaciones en tiempo de ejecución de Android
Colecciones mono
Las recopilaciones en tiempo de ejecución de Android funcionan con normalidad, pero con una advertencia: una
referencia global de JNI se trata como una raíz de GC. Por consiguiente, si hay una referencia global de JNI que
contiene un objeto de máquina virtual en tiempo de ejecución de Android, no se puede recopilar el objeto, aunque
de lo contrario se pueda seleccionar para la colección.
Las colecciones mono son donde ocurre la diversión. Los objetos administrados se recopilan normalmente. Los
objetos del mismo nivel se recopilan realizando el proceso siguiente:
1. Todos los objetos del mismo nivel válidos para la colección mono tienen su referencia global de JNI
reemplazada por una referencia global débil de JNI.
2. Se invoca un GC de VM en tiempo de ejecución de Android. Se puede recopilar cualquier instancia nativa
del mismo nivel.
3. Se comprueban las referencias globales de JNI creadas en (1). Si se ha recopilado la referencia débil, se
recopila el objeto del mismo nivel. Si no se ha recopilado la referencia débil, la referencia débil se
reemplaza con una referencia global de JNI y el objeto del mismo nivel no se recopila. Nota: en la API 14 +,
esto significa que el valor devuelto de IJavaObject.Handle puede cambiar después de un GC.

El resultado final de todo esto es que una instancia de un objeto del mismo nivel se activará siempre que el código
administrado (por ejemplo, almacenado en una static variable) haga referencia a él o que el código de Java
haga referencia a él. Además, la duración de los elementos del mismo nivel nativos se ampliará más allá de lo que
de otro modo activaría, ya que el elemento nativo del mismo nivel no se recopilará hasta que el elemento nativo
del mismo nivel y el del mismo nivel administrados sean recopilables.

Ciclos de objeto
Los objetos del mismo nivel están lógicamente presentes en el tiempo de ejecución de Android y en las máquinas
virtuales mono. Por ejemplo, una instancia administrada del mismo nivel de Android. app. Activity tendrá una
instancia de Java de Android. app. Activity Framework correspondiente. Se espera que todos los objetos que
heredan de java. lang. Object tengan representaciones en ambas máquinas virtuales.
Todos los objetos que tienen una representación en ambas máquinas virtuales tendrán duraciones extendidas en
comparación con los objetos que solo están presentes en una sola máquina virtual
System.Collections.Generic.List<int> (por ejemplo, un). Llamando a GC. Collect no recopilará necesariamente
estos objetos, ya que el GC de Xamarin. Android debe asegurarse de que ninguna máquina virtual haga referencia
al objeto antes de recopilarlo.
Para acortar la duración del objeto, se debe invocar java. lang. Object. Dispose () . Esto hará que la conexión se
haga manualmente "servidor" en el objeto entre las dos máquinas virtuales liberando la referencia global, lo que
permite recopilar los objetos más rápidamente.

Colecciones automáticas
A partir de la versión 4.1.0, Xamarin. Android realiza automáticamente un GC completo cuando se cruza un
umbral de Gref. Este umbral es el 90% del Grefs máximo conocido de la plataforma: 1800 Grefs en el emulador
(2000 máx.) y 46800 Grefs en hardware (máximo 52000). Nota: Xamarin. Android solo cuenta el Grefs creado por
Android. Runtime. JNIEnvy no conocerá ningún otro Grefs creado en el proceso. Esta es solouna heurística.
Cuando se realiza una recopilación automática, se imprime un mensaje similar al siguiente en el registro de
depuración:

I/monodroid-gc(PID): 46800 outstanding GREFs. Performing a full GC!

La aparición de esto no es determinista y puede ocurrir en momentos inoportunos (por ejemplo, en el medio de la
representación de gráficos). Si ve este mensaje, es posible que desee realizar una colección explícita en otro lugar
o que desee intentar reducir la duración de los objetos del mismo nivel.

Opciones del puente GC


Xamarin. Android ofrece administración de memoria transparente con Android y el tiempo de ejecución de
Android. Se implementa como una extensión del recolector de elementos no utilizados mono denominado puente
GC.
El puente de GC funciona durante una recolección de elementos no utilizados mono y averigua qué objetos del
mismo nivel necesitan su "vida" verificado con el montón de tiempo de ejecución de Android. El puente de GC
realiza esta determinación realizando los pasos siguientes (en orden):
1. Inducir el gráfico de referencia mono de objetos del mismo nivel inalcanzables a los objetos de Java que
representan.
2. Realice un GC de Java.
3. Compruebe qué objetos están realmente inactivos.
Este complejo proceso es lo que permite a las subclases de hacer referencia a cualquier objeto de forma gratuita;
quita todas las restricciones a Java.Lang.Object C#las que se pueden enlazar los objetos de Java. Debido a esta
complejidad, el proceso del puente puede resultar muy caro y puede causar pausas perceptibles en una aplicación.
Si la aplicación experimenta pausas significativas, merece la pena investigar una de las tres implementaciones de
puente de GC siguientes:
Tarjan : un diseño completamente nuevo del puente de GC basado en el algoritmo de Robert Tarjan y la
propagación de referencias hacia atrás. Tiene el mejor rendimiento en nuestras cargas de trabajo
simuladas, pero también tiene la mayor parte del código experimental.
New : una revisión importante del código original, corrigiendo dos instancias de comportamiento
cuadrático pero manteniendo el algoritmo principal (basado en el algoritmo de Kosaraju para buscar
componentes fuertemente conectados).
Antigua : la implementación original (considerada la más estable de los tres). Este es el puente que una
aplicación debe usar si las GC_BRIDGE pausas son aceptables.
La única manera de averiguar qué puente de GC funciona mejor es experimentar en una aplicación y analizar la
salida. Hay dos maneras de recopilar los datos de pruebas comparativas:
Habilitar registro : habilite el registro (como se describe en la sección de configuración ) para cada opción
de puente de GC y, a continuación, Capture y compare los resultados del registro de cada configuración.
Inspeccione GC los mensajes para cada opción; en concreto, GC_BRIDGE los mensajes. Pausar hasta 150MS
para las aplicaciones no interactivas son tolerable, pero las pausas anteriores a 60 ms para aplicaciones
muy interactivas (como los juegos) son un problema.
Habilitar cuentas de puente : las cuentas de puente muestran el costo medio de los objetos a los que
apunta cada objeto implicado en el proceso del puente. Al ordenar esta información por tamaño, se
proporcionarán sugerencias sobre lo que contiene la mayor cantidad de objetos adicionales.
Para especificar la GC_BRIDGE opción que una aplicación debe hacer, bridge-implementation=old
bridge-implementation=new pasar o bridge-implementation=tarjan a la MONO_GC_PARAMS variable de entorno, por
ejemplo:

MONO_GC_PARAMS=bridge-implementation=tarjan

La configuración predeterminada es Tarjan. Si encuentra una regresión, puede que sea necesario establecer esta
opción en Old. Además, puede optar por usar la opción antigua más estable si Tarjan no produce una mejora en
el rendimiento.

Ayuda al GC
Hay varias maneras de ayudar al GC a reducir el uso de memoria y los tiempos de recopilación.
Desechar instancias del mismo nivel
El GC tiene una vista incompleta del proceso y puede no ejecutarse cuando la memoria es baja, ya que el GC no
sabe que la memoria es baja.
Por ejemplo, una instancia de un tipo de objeto Java. lang. Object o un tipo derivado tiene al menos 20 bytes de
tamaño (sujeto a cambios sin previo aviso, etc., etc.). Los contenedores a los que se puede llamar administrados no
agregan miembros de instancia adicionales, por lo que, si tiene una instancia de Android. Graphics. Bitmap que
hace referencia a un BLOB – de memoria de 10 MB, el GC de Xamarin. Android no sabrá que el GC verá un objeto
de 20 bytes y no podrá determinar si está vinculado a los objetos asignados en tiempo de ejecución de Android
que mantienen 10 MB de memoria activo.
A menudo es necesario ayudar al GC. Desafortunadamente, GC. AddMemoryPressure () y GC. No se admite
RemoveMemoryPressure () , por lo que si sabe que acaba de liberar un gráfico de objetos asignados a Java de
gran tamaño, es posible que tenga que llamar manualmente a GC. Collect () para solicitar a un GC que libere la
memoria del lado de la Java, o puede desechar explícitamente las subclases java. lang. Object , interrumpiendo la
asignación entre el contenedor al que se puede llamar y la instancia de Java. Por ejemplo, vea el error 1084.

NOTE
Debe ser extremadamente cuidadoso al desechar instancias Java.Lang.Object de subclases.

Para minimizar la posibilidad de daños en la memoria, observe las siguientes directrices Dispose() al llamar a.
Compartir entre varios subprocesos
Si el Java o la instancia administrada se pueden compartir entre varios subprocesos, no debería Dispose() ser d,
nunca. Por ejemplo, Typeface.Create() puede devolver una instancia almacenada en caché. Si varios
subprocesos proporcionan los mismos argumentos, obtendrán la misma instancia. Por consiguiente, Dispose() la
Typeface operación de una instancia de un subproceso puede invalidar otros subprocesos ArgumentException , lo
que JNIEnv.CallVoidMethod() puede dar lugar a s desde (entre otros) porque la instancia se eliminó de otro
subproceso.
Eliminación de tipos de Java enlazados
Si la instancia es de un tipo de Java enlazado, la instancia se puede eliminar siempre que la instancia no se vuelva
a usar desde el código administrado y no se pueda compartir la instancia de Java entre los subprocesos (vea la
explicación anterior Typeface.Create() ). (Tomar esta determinación puede ser difícil). La próxima vez que la
instancia de Java Escriba código administrado, se creará un nuevo contenedor.
Esto suele ser útil cuando se trata de Drawables y de otras instancias de recursos pesados:

using (var d = Drawable.CreateFromPath ("path/to/filename"))


imageView.SetImageDrawable (d);
Lo anterior es seguro porque el elemento del mismo nivel que drawable. CreateFromPath () hará referencia a un
elemento de marco de trabajo del mismo nivel, no a un usuario del mismo nivel. La llamada Dispose() al final del
bloque using interrumpirá la relación entre las instancias Dibujables administrables y de marco Dibujables, lo
que permite que la instancia de Java se recopile en cuanto sea necesario el Runtime de Android. Esto no sería
seguro si la instancia del mismo nivel hacía referencia a un usuario del mismo nivel; Aquí vamos a usar
información "externa" para saber que el Drawable no puede hacer referencia a un usuario del mismo nivel
Dispose() y, por lo tanto, la llamada es segura.

Desechar otros tipos


Si la instancia hace referencia a un tipo que no es un enlace de un tipo de Java (como Activity un personalizado),
no llame Dispose() a a menos que sepa que ningún código Java llamará a los métodos invalidados en esa
instancia. Si no lo hace, se NotSupportedException producirán.
Por ejemplo, si tiene un agente de escucha de clic personalizado:

partial class MyClickListener : Java.Lang.Object, View.IOnClickListener {


// ...
}

No debe eliminar esta instancia, ya que Java intentará invocar métodos en ella en el futuro:

// BAD CODE; DO NOT USE


Button b = FindViewById<Button> (Resource.Id.myButton);
using (var listener = new MyClickListener ())
b.SetOnClickListener (listener);

Usar comprobaciones explícitas para evitar excepciones


Si ha implementado un método de sobrecarga java. lang. Object. Dispose , evite el toque de objetos que impliquen
JNI. Si lo hace, puede crear una situación de doble eliminación que permita que el código intente (de manera
irrecuperable) intentar tener acceso a un objeto Java subyacente que ya se ha recolectado como elemento no
utilizado. Si lo hace, se produce una excepción similar a la siguiente:

System.ArgumentException: 'jobject' must not be IntPtr.Zero.


Parameter name: jobject
at Android.Runtime.JNIEnv.CallVoidMethod

Esta situación se suele producir cuando el primer Dispose de un objeto hace que un miembro se convierta en
NULL y, a continuación, un intento de acceso posterior en este miembro null provoca que se produzca una
excepción. En concreto, el del Handle objeto (que vincula una instancia administrada a su instancia de Java
subyacente) se invalida en el primer Dispose, pero el código administrado sigue intentando tener acceso a esta
instancia subyacente de Java aunque ya no esté disponible (consulte Contenedores RCW administrados para
obtener más información sobre la asignación entre las instancias de Java y las instancias administradas).
Una buena manera de evitar esta excepción es comprobar explícitamente en el Dispose método que la asignación
entre la instancia administrada y la instancia de Java subyacente sigue siendo válida; es decir, comprobar si el valor
del Handle objeto es null IntPtr.Zero () antes de tener acceso a sus miembros. Por ejemplo, el método Dispose
siguiente tiene acceso a childViews un objeto:
class MyClass : Java.Lang.Object, ISomeInterface
{
protected override void Dispose (bool disposing)
{
base.Dispose (disposing);
for (int i = 0; i < this.childViews.Count; ++i)
{
// ...
}
}
}

Si un paso de eliminación inicial childViews hace que tenga un Handle no válido for , el acceso al bucle
ArgumentException producirá una excepción. Al agregar una comprobación Handle nula explícita antes del primer
childViews acceso, el método Dispose siguiente evita que se produzca la excepción:

class MyClass : Java.Lang.Object, ISomeInterface


{
protected override void Dispose (bool disposing)
{
base.Dispose (disposing);

// Check for a null handle:


if (this.childViews.Handle == IntPtr.Zero)
return;

for (int i = 0; i < this.childViews.Count; ++i)


{
// ...
}
}
}

Reducir las instancias a las que se hace referencia


Siempre que se examina una Java.Lang.Object instancia de un tipo o una subclase durante el GC, también se
debe examinar todo el gráfico de objetos al que hace referencia la instancia. El gráfico de objetos es el conjunto de
instancias de objeto al que hace referencia la "instancia raíz", además de todo lo al que hace referencia la instancia
raíz, de forma recursiva.
Considere la siguiente clase:

class BadActivity : Activity {

private List<string> strings;

protected override void OnCreate (Bundle bundle)


{
base.OnCreate (bundle);

strings.Value = new List<string> (


Enumerable.Range (0, 10000)
.Select(v => new string ('x', v % 1000)));
}
}

Cuando BadActivityse construye, el gráfico de objetos contendrá 10004 instancias ( BadActivity 1x, strings 1x,
string[] 1x retenidas por strings , instancias de cadena 10000x), todas ellas deberán examinarse cada vez que
el valorde BadActivity se analiza la instancia.
Esto puede tener efectos perjudiciales en los tiempos de colección, lo que aumenta el tiempo de pausa de GC.
Puede ayudar al GC reduciendo el tamaño de los gráficos de objetos que tienen la raíz de las instancias del mismo
nivel de usuario. En el ejemplo anterior, esto se puede hacer pasando BadActivity.strings a una clase
independiente que no se hereda de Java. lang. Object:

class HiddenReference<T> {

static Dictionary<int, T> table = new Dictionary<int, T> ();


static int idgen = 0;

int id;

public HiddenReference ()
{
lock (table) {
id = idgen ++;
}
}

~HiddenReference ()
{
lock (table) {
table.Remove (id);
}
}

public T Value {
get { lock (table) { return table [id]; } }
set { lock (table) { table [id] = value; } }
}
}

class BetterActivity : Activity {

HiddenReference<List<string>> strings = new HiddenReference<List<string>>();

protected override void OnCreate (Bundle bundle)


{
base.OnCreate (bundle);

strings.Value = new List<string> (


Enumerable.Range (0, 10000)
.Select(v => new string ('x', v % 1000)));
}
}

Colecciones secundarias
Las colecciones secundarias se pueden realizar manualmente mediante una llamada a GC. Collect (0). Las
colecciones secundarias son baratas (cuando se comparan con las colecciones principales), pero tienen un costo
fijo significativo, por lo que no desea activarlas con demasiada frecuencia y deben tener un tiempo de pausa de
unos milisegundos.
Si la aplicación tiene un "ciclo de aranceles" en el que la misma cosa se realiza una y otra vez, puede ser
aconsejable realizar manualmente una colección secundaria una vez que haya finalizado el ciclo de servicio. Los
ciclos de servicio de ejemplo incluyen:
El ciclo de representación de una sola trama de juego.
Toda la interacción con un cuadro de diálogo de aplicación determinado (abrir, rellenar, cerrar)
Un grupo de solicitudes de red para actualizar o sincronizar los datos de la aplicación.
Colecciones principales
Las colecciones principales se pueden realizar manualmente mediante una llamada a GC. Collect () o
GC.Collect(GC.MaxGeneration) .

Deben realizarse con poca frecuencia y pueden tener un tiempo de pausa de un segundo en un dispositivo de
estilo Android al recopilar un montón de 512 MB.
Las colecciones principales solo se deben invocar manualmente, si alguna vez:
Al final de los ciclos de servicio largos y cuando una pausa larga no presente ningún problema al usuario.
Dentro de un método Android. app. Activity. OnLowMemory () invalidado.

Diagnóstico
Para realizar un seguimiento de Cuándo se crean y destruyen referencias globales, puede establecer la propiedad
del sistema Debug. mono. log para que contenga Gref y/o GC.

Configuración
El recolector de elementos no utilizados de Xamarin. Android se MONO_GC_PARAMS puede configurar estableciendo
la variable de entorno. Las variables de entorno se pueden establecer con una acción de compilación de
AndroidEnvironment.
La MONO_GC_PARAMS variable de entorno es una lista separada por comas de los parámetros siguientes:
nursery-size = tamaño : Establece el tamaño de la enfermera. El tamaño se especifica en bytes y debe ser
una potencia de dos. Los k sufijos m y g se pueden usar para especificar kilo-, mega-and gigabytes,
respectivamente. La enfermera es la primera generación (de dos). Una enfermera más grande
normalmente acelerará el programa, pero evidentemente usará más memoria. El tamaño de enfermeras
predeterminado es de 512 KB.
soft-heap-limit = tamaño : El consumo máximo de memoria administrada de destino para la aplicación.
Cuando el uso de memoria está por debajo del valor especificado, el GC está optimizado para el tiempo de
ejecución (menos colecciones). Por encima de este límite, el GC está optimizado para el uso de memoria
(más colecciones).
evacuation-threshold = umbral : Establece el umbral de evacuación en porcentaje. El valor debe ser un
entero comprendido en el intervalo comprendido entre 0 y 100. El valor predeterminado es 66. Si la fase de
barrido de la colección encuentra que el grupo de un tipo de bloque de montón específico es inferior a este
porcentaje, se realizará una recolección de copia para ese tipo de bloque en la siguiente colección principal,
con lo que se restaurará la ocupación para que se acerque al 100 por ciento. Un valor de 0 desactiva la
evacuación.
bridge-implementation = implementación de puente : Esto establecerá la opción puente de GC para
solucionar los problemas de rendimiento de GC. Hay tres valores posibles: Old , New , Tarjan.
bridge-require-precise-merge : El puente Tarjan contiene una optimización que, en raras ocasiones, puede
hacer que se recopile un objeto en un GC después de que se convierta en un elemento no utilizado. Al
incluir esta opción, se deshabilita la optimización, lo que permite que los GC sean más predecibles, pero
potencialmente más lentos.
Por ejemplo, para configurar el GC para que tenga un límite de tamaño de montón de 128 MB, agregue un nuevo
archivo al proyecto con una AndroidEnvironment acción de compilación de con el contenido:
MONO_GC_PARAMS=soft-heap-limit=128m
Limitaciones
16/08/2019 • 6 minutes to read • Edit Online

Dado que las aplicaciones de Android requieren la generación de tipos de proxy de Java durante el proceso de
compilación, no es posible generar todo el código en tiempo de ejecución.
Estas son las limitaciones de Xamarin. Android en comparación con el escritorio mono:

Compatibilidad limitada con los lenguajes dinámicos


Los contenedores a los que se puede llamar de Android son necesarios cada vez que el tiempo de ejecución de
Android necesita invocar código administrado. Los contenedores a los que se puede llamar de Android se generan
en tiempo de compilación, en función del análisis estático de IL. El resultado neto de esto: no puede usar lenguajes
dinámicos (IronPython, IronRuby, etc.) en cualquier escenario en el que se requiera la subclase de tipos de Java
(incluida la subclase indirecta), ya que no hay forma de extraer estos tipos dinámicos en tiempo de compilación a
genere los contenedores de Android a los que se puede llamar necesarios.

Compatibilidad con la generación limitada de Java


Los contenedores a los que se puede llamar de Android deben generarse para que el código Java llame a código
administrado. De forma predeterminada, los contenedores a los que se puede llamar de Android solo contendrán
(ciertos) métodos y constructores declarados que RegisterAttribute invalidan un método Java Virtual (es decir,
Attribute tiene) o implementan un método de interfaz Java (la interfaz también tiene).

Antes de la versión 4,1, no se podía declarar ningún método adicional. Con la versión 4,1, se Export pueden
ExportField usar los atributos personalizados y para declarar métodos y campos de Java en el contenedor de
Android al que se puede llamar.
Faltan constructores
Los constructores siguen siendo complicados ExportAttribute , a menos que se use. El algoritmo para generar
constructores de contenedor a los que se puede llamar de Android es que se emitirá un constructor de Java si:
1. Hay una asignación de Java para todos los tipos de parámetro
2. La clase base declara el mismo constructor – esto es necesario porque el contenedor de Android al que se
puede llamar debe invocar el constructor de clase base correspondiente; no se pueden usar argumentos
predeterminados (ya que no hay ninguna manera fácil de determinar qué valores debe usarse en Java).
Por ejemplo, considere la siguiente clase:

[Service]
class MyIntentService : IntentService {
public MyIntentService (): base ("value")
{
}
}

Aunque parece perfectamente lógico, el contenedor de Android al que se puede llamar resultante en las
compilaciones de versión no contendrá un constructor predeterminado. Por lo tanto, si intenta iniciar este servicio
(por ejemplo Context.StartService , se producirá un error:
E/AndroidRuntime(31766): FATAL EXCEPTION: main
E/AndroidRuntime(31766): java.lang.RuntimeException: Unable to instantiate service example.MyIntentService:
java.lang.InstantiationException: can't instantiate class example.MyIntentService; no empty constructor
E/AndroidRuntime(31766): at android.app.ActivityThread.handleCreateService(ActivityThread.java:2347)
E/AndroidRuntime(31766): at android.app.ActivityThread.access$1600(ActivityThread.java:130)
E/AndroidRuntime(31766): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1277)
E/AndroidRuntime(31766): at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime(31766): at android.os.Looper.loop(Looper.java:137)
E/AndroidRuntime(31766): at android.app.ActivityThread.main(ActivityThread.java:4745)
E/AndroidRuntime(31766): at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime(31766): at java.lang.reflect.Method.invoke(Method.java:511)
E/AndroidRuntime(31766): at
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
E/AndroidRuntime(31766): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
E/AndroidRuntime(31766): at dalvik.system.NativeStart.main(Native Method)
E/AndroidRuntime(31766): Caused by: java.lang.InstantiationException: can't instantiate class
example.MyIntentService; no empty constructor
E/AndroidRuntime(31766): at java.lang.Class.newInstanceImpl(Native Method)
E/AndroidRuntime(31766): at java.lang.Class.newInstance(Class.java:1319)
E/AndroidRuntime(31766): at android.app.ActivityThread.handleCreateService(ActivityThread.java:2344)
E/AndroidRuntime(31766): ... 10 more

La solución consiste en declarar un constructor predeterminado, adornarlo con ExportAttribute y


ExportAttribute.SuperStringArgument establecer:

[Service]
class MyIntentService : IntentService {
[Export (SuperArgumentsString = "\"value\"")]
public MyIntentService (): base("value")
{
}

// ...
}

Clases C# genéricas
Las C# clases genéricas solo se admiten parcialmente. Existen las siguientes limitaciones:
Los tipos genéricos no [Export] pueden [ExportField usar o]. Si intenta hacerlo, se generará un XA4207
error.

public abstract class Parcelable<T> : Java.Lang.Object, IParcelable


{
// Invalid; generates XA4207
[ExportField ("CREATOR")]
public static IParcelableCreator CreateCreator ()
{
...
}

Los métodos genéricos no [Export] pueden [ExportField] usar ni:


public class Example : Java.Lang.Object
{

// Invalid; generates XA4207


[Export]
public static void Method<T>(T value)
{
...
}
}

[ExportField] no se puede usar en métodos que devuelven void :

public class Example : Java.Lang.Object


{
// Invalid; generates XA4208
[ExportField ("CREATOR")]
public static void CreateSomething ()
{
}
}

No se deben crear instancias de tipos genéricos a partir del código de Java. Solo se pueden crear de forma
segura a partir de código administrado:

[Activity (Label="Die!", MainLauncher=true)]


public class BadGenericActivity<T> : Activity
{
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
}
}

Compatibilidad parcial con Java genéricos


La compatibilidad con enlaces de genéricos de Java es limitada. En particular, los miembros de una clase de
instancia genérica que se deriva de otra clase genérica (sin instancias) se dejan expuestos como Java. lang. Object.
Por ejemplo, el método Android. Content. Intent. GetParcelableExtra devuelve Java. lang. Object. Esto se debe a
que se han borrado los genéricos de Java. Tenemos algunas clases que no aplican esta limitación, pero se ajustan
de forma manual.

Vínculos relacionados
Contenedores que se pueden llamar de Android
Trabajar con JNI
ExportAttribute
SuperString
RegisterAttribute
Solución de problemas
11/07/2019 • 2 minutes to read • Edit Online

Documentos de esta sección tratan características específicas de solución de problemas con Android.

Sugerencias para la solución de problemas


Solución de problemas de sugerencias y trucos.

Preguntas más frecuentes


Xamarin.Android solución de problemas de las preguntas más frecuentes.

Resolución de errores de instalación de biblioteca


Esta guía proporciona soluciones para algunos errores comunes que pueden ocurrir al que hacen referencia a y
se descarguen automáticamente Android Support Libraries o Google Play services.

Cambios en las Herramientas de Android SDK


A partir de 26.0.1 del Android SDK Tools, Google ha quitado los administradores de AVD y SDK existentes en
favor de las nuevas herramientas de línea de comandos.

Referencia de errores de Xamarin.Android


Una guía de referencia de errores, que muestra los errores más comunes que es posible que experimente al usar
Xamarin.Android en Xamarin Studio
Sugerencias para la solución de problemas
19/08/2019 • 42 minutes to read • Edit Online

Obtención de información de diagnóstico


Xamarin. Android tiene algunos lugares en los que buscar cuando se realiza un seguimiento de varios errores.
Entre ellas se incluyen las siguientes:
1. Salida de MSBuild de diagnóstico.
2. Registros de implementación de dispositivos.
3. Salida del registro de depuración de Android.

Salida de MSBuild de diagnóstico


El diagnóstico de MSBuild puede contener información adicional relacionada con la generación de paquetes y
puede contener información de implementación de paquetes.
Para habilitar el resultado de diagnóstico de MSBuild en Visual Studio:
1. Haga clic en herramientas > opciones...
2. En la vista de árbol del lado izquierdo, seleccione proyectos y soluciones > compilar y ejecutar .
3. En el panel derecho, establezca la lista desplegable detalle de salida de compilación de MSBuild en diagnóstico.
4. Haga clic en Aceptar.
5. Limpie y recompile el paquete.
6. La salida de diagnóstico es visible en el panel de salida.
Para habilitar la salida del diagnóstico de MSBuild en Visual Studio para Mac/OS X:
1. Haga clic en Visual Studio para Mac preferencias de >...
2. En la vista de árbol del lado izquierdo, seleccione proyectos > compilación .
3. En el panel derecho, establezca la lista desplegable de nivel de detalle del registro en diagnóstico.
4. Haga clic en Aceptar.
5. Reinicie Visual Studio para Mac.
6. Limpie y recompile el paquete.
7. La salida de diagnóstico es visible en el panel de errores (ver > paneles > errores ), haciendo clic en el botón
generar resultado.

Registros de implementación de dispositivos


Para habilitar el registro de implementación de dispositivos en Visual Studio:
1. Herramientas > opciones... >
2. En la vista de árbol del lado izquierdo, seleccione Xamarin > Android Settings .
3. En el panel derecho, active la casilla [X] registro de depuración de la extensión (escribe monodroid. log en
el escritorio) .
4. Los mensajes de registro se escriben en el archivo monodroid. log en el escritorio.
Visual Studio para Mac escribe siempre los registros de implementación del dispositivo. Buscarlos es algo más
difícil. se crea un archivo de registro de AndroidUtils para cada día + hora en que se produce una implementación,
por ejemplo: AndroidTools-2012-10-24_12-35-45.log.
En Windows, los archivos de registro se %LOCALAPPDATA%\XamarinStudio-{VERSION}\Logs escriben en.
En OS X, los archivos de registro se $HOME/Library/Logs/XamarinStudio-{VERSION} escriben en.

Salida del registro de depuración de Android


Android escribirá muchos mensajes en el registrode depuración de Android. Xamarin. Android usa las propiedades
del sistema de Android para controlar la generación de mensajes adicionales en el registro de depuración de
Android. Las propiedades del sistema de Android se pueden establecer mediante el comando setprop en el
Android Debug Bridge (ADB ):

adb shell setprop PROPERTY_NAME PROPERTY_VALUE

Las propiedades del sistema se leen durante el inicio del proceso y, por tanto, se deben establecer antes de que se
inicie la aplicación o se debe reiniciar la aplicación después de cambiar las propiedades del sistema.
Propiedades del sistema de Xamarin.Android
Xamarin. Android admite las siguientes propiedades del sistema:
debug.mono.debug: Si es una cadena no vacía, es equivalente a *mono-debug* .
debug.mono.env: Una lista de variables de entorno | separadas por canalización (' ') que se van a exportar
durante el inicio de la aplicación, antes de que se haya inicializado mono. Esto permite establecer variables
de entorno que controlan el registro de mono.
Nota: Dado que el valor está | separado por "", el valor debe tener un nivel adicional de cotización, ya
`que el comando de Shell ` ADB quitará un conjunto de Comillas.
Nota: Los valores de propiedad del sistema Android no pueden tener más de 92 caracteres de
longitud.
Ejemplo:

adb shell setprop debug.mono.env "'MONO_LOG_LEVEL=info|MONO_LOG_MASK=asm'"

debug.mono.log: Una lista separada por comas (' , ') de los componentes que deben imprimir mensajes
adicionales en el registro de depuración de Android. De forma predeterminada, no se establece nada. Los
componentes incluyen:
all: Imprimir todos los mensajes
gc: Imprime mensajes relacionados con GC.
gref: Mensajes de asignación y desasignación de referencia de impresión (débil, global).
lref: Imprimir mensajes de asignación y desasignación de referencia local.
Nota: Estos son muy detallados. No habilite a menos que realmente sea necesario.
debug.mono.trace: Permite establecer la configuración de seguimiento =PROPERTY_VALUE mono.

bin Eliminar y obj


Xamarin. Android ha sufrido en el pasado desde una situación como:
Se produce un error de compilación o en tiempo de ejecución extraño.
Usted Clean bin obj , Rebuild o elimina manualmente los directorios y.
El problema desaparece.
Hemos invertido mucho en solucionar problemas como estos debido a su impacto en la productividad de los
desarrolladores.
Si se produce un problema como este:
1. Cree una nota mental. ¿Cuál fue la última acción que obtuvo el proyecto en este estado?
2. Guarde el registro de compilación actual. Intente compilar de nuevo y grabe un registro de compilación de
diagnóstico.
3. Enviar un Informe de errores.
Antes de eliminar los bin directorios obj y, cópielos y guárdelos para su posterior diagnóstico, si es necesario.
Probablemente, puede simplemente Clean usar el proyecto de aplicación de Xamarin. Android para que
funcionen de nuevo.

Xamarin. Android no puede resolver System. ValueTuple


Este error se produce debido a una incompatibilidad con Visual Studio.
Visual Studio 2017 Update 1 (versión 15,1 o anterior) solo es compatible con el sistema. ValueTuple
NuGet 4.3.0 (o anterior).
Visual Studio 2017 Update 2 (la versión 15,2 o posterior) solo es compatible con el sistema. ValueTuple
NuGet 4.3.1 (o posterior).
Elija el NuGet System. ValueTuple correcto que se corresponda con la instalación de Visual Studio 2017.

Mensajes GC
Los mensajes del componente GC se pueden ver estableciendo la propiedad del sistema Debug. mono. log en un
valor que contenga GC.
Los mensajes GC se generan cada vez que se ejecuta el GC y proporciona información acerca de la cantidad de
trabajo que hizo el GC:

I/monodroid-gc(12331): GC cleanup summary: 81 objects tested - resurrecting 21.

Se puede generar información adicional de GC, como la información de tiempo MONO_LOG_LEVEL , si se debug
establece la variable de entorno en:

adb shell setprop debug.mono.env MONO_LOG_LEVEL=debug

Esto producirá (muchos) mensajes mono adicionales, incluidos estos tres de consecuencia:

D/Mono (15723): GC_BRIDGE num-objects 1 num_hash_entries 81226 sccs size 81223 init 0.00ms df1 285.36ms sort
38.56ms dfs2 50.04ms setup-cb 9.95ms free-data 106.54ms user-cb 20.12ms clenanup 0.05ms links
5523436/5523436/5523096/1 dfs passes 1104 6883/11046605
D/Mono (15723): GC_MINOR: (Nursery full) pause 2.01ms, total 287.45ms, bridge 225.60 promoted 0K major 325184K
los 1816K
D/Mono ( 2073): GC_MAJOR: (user request) pause 2.17ms, total 2.47ms, bridge 28.77 major 576K/576K los 0K/16K

En el mensaje, num-objects es el número de objetos de puente que este paso está considerando
GC_BRIDGE
num_hash_entries y es el número de objetos procesados durante esta invocación del código del puente.

En los GC_MINOR mensajes GC_MAJOR y, total es la cantidad de tiempo durante el que el mundo se pausa (no se
ejecuta ningún subproceso) bridge , mientras que es la cantidad de tiempo que se tarda en el código de
procesamiento del puente (que se encarga de la máquina virtual Java). El mundo no está en pausa mientras se
produce el procesamiento del puente.
En general, cuanto mayor sea el valor num_hash_entries de, más tiempo tardarán bridge las colecciones y más
grande será el total tiempo dedicado a la recopilación.

Mensajes de referencia global


Para habilitar el registro de loggig de referencia global (GREF ), la propiedad del sistema Debug. mono. log debe
contener Gref, por ejemplo:

adb shell setprop debug.mono.log gref

Xamarin. Android usa referencias globales de Android para proporcionar asignaciones entre instancias de Java y
las instancias administradas asociadas, como cuando se invoca un método Java, es necesario proporcionar una
instancia de Java a Java.
Desafortunadamente, los emuladores de Android solo permiten la existencia de 2000 referencias globales a la vez.
El hardware tiene un límite mucho más alto de 52000 referencias globales. El límite inferior puede ser
problemático al ejecutar aplicaciones en el emulador, por lo que saber de dónde procede la instancia puede ser
muy útil.
Nota: el recuento de referencias globales es interno a Xamarin. Android y no (y no puede) incluir referencias
globales tomadas por otras bibliotecas nativas cargadas en el proceso. Usar el recuento de referencias globales
como una estimación.

I/monodroid-gref(12405): +g+ grefc 108 gwrefc 0 obj-handle 0x40517468/L -> new-handle 0x40517468/L from at
Java.Lang.Object.RegisterInstance(IJavaObject instance, IntPtr value, JniHandleOwnership transfer)
I/monodroid-gref(12405): at Java.Lang.Object.SetHandle(IntPtr value, JniHandleOwnership transfer)
I/monodroid-gref(12405): at Java.Lang.Object..ctor(IntPtr handle, JniHandleOwnership transfer)
I/monodroid-gref(12405): at Java.Lang.Thread+RunnableImplementor..ctor(System.Action handler, Boolean
removable)
I/monodroid-gref(12405): at Java.Lang.Thread+RunnableImplementor..ctor(System.Action handler)
I/monodroid-gref(12405): at Android.App.Activity.RunOnUiThread(System.Action action)
I/monodroid-gref(12405): at Mono.Samples.Hello.HelloActivity.UseLotsOfMemory(Android.Widget.TextView
textview)
I/monodroid-gref(12405): at Mono.Samples.Hello.HelloActivity.<OnCreate>m__3(System.Object o)
I/monodroid-gref(12405): handle 0x40517468; key_handle 0x40517468: Java Type:
`mono/java/lang/RunnableImplementor`; MCW type: `Java.Lang.Thread+RunnableImplementor`
I/monodroid-gref(12405): Disposing handle 0x40517468
I/monodroid-gref(12405): -g- grefc 107 gwrefc 0 handle 0x40517468/L from at
Java.Lang.Object.Dispose(System.Object instance, IntPtr handle, IntPtr key_handle, JObjectRefType handle_type)
I/monodroid-gref(12405): at Java.Lang.Object.Dispose()
I/monodroid-gref(12405): at Java.Lang.Thread+RunnableImplementor.Run()
I/monodroid-gref(12405): at Java.Lang.IRunnableInvoker.n_Run(IntPtr jnienv, IntPtr native__this)
I/monodroid-gref(12405): at System.Object.c200fe6f-ac33-441b-a3a0-47659e3f6750(IntPtr , IntPtr )
I/monodroid-gref(27679): +w+ grefc 1916 gwrefc 296 obj-handle 0x406b2b98/G -> new-handle 0xde68f4bf/W from
take_weak_global_ref_jni
I/monodroid-gref(27679): -w- grefc 1915 gwrefc 294 handle 0xde691aaf/W from take_global_ref_jni

Hay cuatro mensajes de consecuencia:


Creación de referencia global: son las líneas que comienzan por + g + y proporcionarán un seguimiento de la
pila para la ruta de acceso del código de creación.
Destrucción de referencia global: son las líneas que comienzan con -g - y pueden proporcionar un seguimiento
de la pila para la ruta de código que elimina la referencia global. Si el GC está desechando el Gref, no se
proporcionará ningún seguimiento de la pila.
Creación de referencia global débil: estas son las líneas que comienzan con + w + .
Destrucción de referencia global débil: son líneas que comienzan por -w - .
En todos los mensajes, el valor de grefc es el recuento de referencias globales que ha creado Xamarin. Android,
mientras que el valor de grefwc es el recuento de referencias globales débiles que ha creado Xamarin. Android. El
identificador o el valor de identificador de obj es el valor de identificador de JNI y el carácter / que aparece
después de ' ' es el tipo de valor de identificador: /l para la referencia local, /g para las referencias globales y /w
para las referencias globales débiles.
Como parte del proceso de GC, las referencias globales (+ g +) se convierten en referencias globales débiles (lo
que produce + w + y-g-), se inicia un GC de Java y, a continuación, se comprueba la referencia global débil para
ver si se recopiló. Si todavía está activo, se crea un nuevo Gref en torno a la referencia débil (+ g +,-w -); en caso
contrario, se destruye la referencia débil (-w ).

Una instancia de Java se crea y se encapsula mediante un MCW


I/monodroid-gref(27679): +g+ grefc 2211 gwrefc 0 obj-handle 0x4066df10/L -> new-handle 0x4066df10/L from ...
I/monodroid-gref(27679): handle 0x4066df10; key_handle 0x4066df10: Java Type:
`android/graphics/drawable/TransitionDrawable`; MCW type: `Android.Graphics.Drawables.TransitionDrawable`

Se está realizando un GC...


I/monodroid-gref(27679): +w+ grefc 1953 gwrefc 259 obj-handle 0x4066df10/G -> new-handle 0xde68f95f/W from
take_weak_global_ref_jni
I/monodroid-gref(27679): -g- grefc 1952 gwrefc 259 handle 0x4066df10/G from take_weak_global_ref_jni

El objeto sigue estando activo, como handle! = null


Wref se vuelve a convertir en Gref
I/monodroid-gref(27679): *try_take_global obj=0x4976f080 -> wref=0xde68f95f handle=0x4066df10
I/monodroid-gref(27679): +g+ grefc 1930 gwrefc 39 obj-handle 0xde68f95f/W -> new-handle 0x4066df10/G from
take_global_ref_jni
I/monodroid-gref(27679): -w- grefc 1930 gwrefc 38 handle 0xde68f95f/W from take_global_ref_jni

El objeto está inactivo, como identificador = = null


Wref se libera, no se crea ningún nuevo Gref
I/monodroid-gref(27679): *try_take_global obj=0x4976f080 -> wref=0xde68f95f handle=0x0
I/monodroid-gref(27679): -w- grefc 1914 gwrefc 296 handle 0xde68f95f/W from take_global_ref_jni

Aquí hay una arruga "interesante": en los destinos que ejecutan Android anteriores a 4,0, el valor de Gref es igual a
la dirección del objeto Java en la memoria del Runtime de Android. (Es decir, el GC es un recopilador sin
movimiento y conservador, y está entregando referencias directas a esos objetos). Por lo tanto, después de a + g +,
+ w +,-g-, + g +,-w -Sequence, el Gref resultante tendrá el mismo valor que el valor de Gref original. Esto hace que
grepping a través de los registros sea bastante sencillo.
Sin embargo, Android 4,0 tiene un recolector en movimiento y ya no entrega referencias directas a objetos de
máquina virtual en tiempo de ejecución de Android. Por consiguiente, después de a + g +, + w +,-g-, + g +,-w -
Sequence, el valor de Gref será diferente. Si el objeto sobrevive a varios catálogos globales, irá entre varios valores
de Gref, lo que dificultará la determinación del lugar desde el que se asignó realmente una instancia.
Consultar mediante programación
Puede consultar los recuentos Gref y WREF consultando el JniRuntime objeto.
Java.Interop.JniRuntime.CurrentRuntime.GlobalReferenceCount -Recuento de referencias globales
Java.Interop.JniRuntime.CurrentRuntime.WeakGlobalReferenceCount -Recuento de referencias débiles

Registros de depuración de Android


Los registros de depuración de Android pueden proporcionar contexto adicional respecto a los errores en tiempo
de ejecución que se ven.

El rendimiento del punto flotante es terrible.


Como alternativa, "mi aplicación se ejecuta 10 veces más rápido con la compilación de depuración que con la
compilación de versión"
Xamarin. Android admite varios dispositivos Abi: armeabi, armeabi-v7ay x86. Los dispositivos Abi se pueden
especificar en las propiedades del proyecto > pestaña aplicación > arquitecturas admitidas.
Las compilaciones de depuración usan un paquete de Android que proporciona todas Abi y, por tanto, usará la ABI
más rápida para el dispositivo de destino.
Las compilaciones de versión solo incluirán el Abi seleccionado en la pestaña propiedades del proyecto. Se puede
seleccionar más de uno.
armeabi es la ABI predeterminada y tiene la compatibilidad más amplia del dispositivo. Sin embargo, armeabi no
es compatible con los dispositivos de varias CPU y el punto flotante de hardware, Amont otras cosas. Por
consiguiente, las aplicaciones que usan el tiempo de ejecución de la versión armeabi se asociarán a un solo núcleo
y usarán una implementación de punto flotante. Ambos pueden contribuir a un rendimiento considerablemente
más lento de la aplicación.
Si su aplicación requiere un rendimiento de punto flotante aceptable (por ejemplo, juegos), debe habilitar la ABI
armeabi-v7a . Es posible que quiera admitir solo el tiempo de ejecución de armeabi-v7a , aunque esto significa
que los dispositivos más antiguos que solo admiten armeabi no podrán ejecutar la aplicación.

No se pudo encontrar Android SDK


Hay 2 descargas disponibles de Google para el Android SDK para Windows. Si elige el instalador. exe, escribirá las
claves del registro que indican a Xamarin. Android dónde se instaló. Si elige el archivo. zip y lo descomprime,
Xamarin. Android no sabe dónde buscar el SDK. Puede indicar a Xamarin. Android Dónde está el SDK en Visual
Studio; para ello, vaya a herramientas > opciones > Xamarin > configuración de Android:
El IDE no muestra el dispositivo de destino
A veces, intentará implementar la aplicación en un dispositivo, pero el dispositivo en el que desea realizar la
implementación no se muestra en el cuadro de diálogo Seleccionar dispositivo. Esto puede ocurrir cuando el
Android Debug Bridge decide entrar en vacaciones.
Para diagnosticar este problema, busque el programa ADBy luego ejecute:

adb devices

Si el dispositivo no está presente, deberá reiniciar el servidor de Android Debug Bridge para poder encontrar el
dispositivo:

adb kill-server
adb start-server

El software de sincronización HTC puede evitar que ADB Start-Server funcione correctamente. Si el comando
ADB Start-Server no imprime en qué puerto comienza, salga del software de sincronización HTC e intente
reiniciar el servidor ADB.

No se pudo ejecutar el ejecutable de tarea especificado "keytool"


Esto significa que la ruta de acceso no contiene el directorio donde se encuentra el directorio bin del SDK de Java.
Compruebe que ha seguido los pasos de la guía de instalación .

monodroid. exe o aresgen. exe se cerró con el código 1


Para ayudarle a depurar este problema, vaya a Visual Studio y cambie el nivel de detalle de MSBuild; para ello,
seleccione: Herramientas > opciones > proyectos y soluciones > compilar y Ejecutar > el detalle de la salida
de la compilación del proyecto de MSBuild y establecer este valor en normal.
Vuelva a generar y compruebe el panel de resultados de Visual Studio, que debe contener el error completo.

No hay suficiente espacio de almacenamiento en el dispositivo para


implementar el paquete
Esto sucede cuando no se inicia el emulador desde dentro de Visual Studio. Al iniciar el emulador fuera de Visual
Studio, debe pasar las -partition-size 512 opciones, por ejemplo,

emulator -partition-size 512 -avd MonoDroid

Asegúrese de usar el nombre correcto del simulador, es decir,el nombre que usó al configurar el simulador.

_Error_deinstalación_de APK no válido al instalar un paquete


Los nombres de paquete de Android deben contener un punto (' . '). Edite el nombre del paquete para que
contenga un punto.
En Visual Studio:
Haga clic con el botón derecho en el proyecto > propiedades
Haga clic en la pestaña manifiesto de Android de la izquierda.
Actualice el campo Nombre del paquete.
Si ve el mensaje “no se encontró archivo AndroidManifest. Xml. Haga clic para agregar uno. ”,
haga clic en el vínculo y, a continuación, actualice el campo Nombre del paquete.
Dentro de Visual Studio para Mac:
Haga clic con el botón derecho en el proyecto > opciones.
Vaya a la sección compilación/aplicación Android.
Cambie el campo Nombre del paquete para que contenga un '. '.

No_se_pudo_instalar_la biblioteca compartida que faltaba al instalar un


paquete
En este contexto, una "biblioteca compartida" no es un archivo de biblioteca compartida nativa ( libfoo.so); en su
lugar, es una biblioteca que se debe instalar por separado en el dispositivo de destino, como Google Maps.
El paquete de Android especifica qué bibliotecas compartidas son <uses-library/> necesarias con el elemento. Si
una biblioteca requerida no está presente en el dispositivo de destino (por //uses-library/@android:required
ejemplo, es true, que es el valor predeterminado), la instalación del paquete producirá un error con la instalación
con errores__de instalación_que falta compartido_ Biblioteca.
Para determinar qué bibliotecas compartidas son necesarias, vea el archivoarchivo AndroidManifest. XML
generado (p. ej., \obj Debug\Android\archivo AndroidManifest. XML ) y busque el <uses-library/>
elementos. <uses-library/> los elementos se pueden agregar manualmente en el archivo archivo
AndroidManifest\. XML de las propiedades del proyecto y a través del atributo personalizado
UsesLibraryAttribute.
Por ejemplo, al agregar una referencia de ensamblado a mono. Android. GoogleMaps. dll , se <uses-library/>
agregará implícitamente un para la biblioteca compartida de Google Maps.

No_se_pudo_instalar la actualización no compatible al instalar un


paquete
Los paquetes de Android tienen tres requisitos:
Deben contener un '. ' (vea la entrada anterior)
Deben tener un nombre de paquete de cadena único (por lo tanto, la Convención inverso-TLD que se ha
detectado en los nombres de aplicaciones Android, por ejemplo, com. Android. Chrome para la aplicación
Chrome).
Al actualizar los paquetes, el paquete debe tener la misma clave de firma.
Por lo tanto, Imagínese este escenario:
1. Compilar & implementar la aplicación como una aplicación de depuración
2. Puede cambiar la clave de firma, por ejemplo, para usarla como una aplicación de versión (o porque no le guste
la clave de firma de depuración proporcionada por el valor predeterminado).
3. La aplicación se instala sin quitarla primero, por ejemplo, depurar > iniciar sin depurar en Visual Studio
Cuando esto sucede, se producirá un error en la_instalación_del_paquete debido a un error de instalación no
compatible con la actualización, ya que el nombre del paquete no ha cambiado mientras se realizaba la clave de
firma. El registro de depuración de Android también contendrá un mensaje similar al siguiente:

E/PackageManager( 146): Package [PackageName] signatures do not match the previously installed version;
ignoring!

Para corregir este error, Quite completamente la aplicación del dispositivo antes de volver a instalar.

_Error_deinstalacióndeUIDmodificadaalinstalarunpaquete_
Cuando se instala un paquete de Android, se le asigna un identificador de usuario (UID ). A veces, por motivos
actualmente desconocidos, al instalar en una aplicación ya instalada, se producirá un error en la instalación con
INSTALL_FAILED_UID_CHANGED :

ERROR [2015-03-23 11:19:01Z]: ANDROID: Deployment failed


Mono.AndroidTools.InstallFailedException: Failure [INSTALL_FAILED_UID_CHANGED]
at Mono.AndroidTools.Internal.AdbOutputParsing.CheckInstallSuccess(String output, String packageName)
at Mono.AndroidTools.AndroidDevice.<>c__DisplayClass2c.<InstallPackage>b__2b(Task`1 t)
at System.Threading.Tasks.ContinuationTaskFromResultTask`1.InnerInvoke()
at System.Threading.Tasks.Task.Execute()

Para solucionar este problema, desinstale completamente el paquete de Android, ya sea mediante la instalación de
la aplicación desde la GUI del destino de adb Android o con:

$ adb uninstall @PACKAGE_NAME@

no usar , ya que esto conservará los datos de la aplicación y, por tanto, conservará el UID en conflicto en el
dispositivo de destino. adb uninstall -k

Las aplicaciones de versión no se pueden iniciar en el dispositivo


La salida del registro de depuración de Android contendrá un mensaje similar al siguiente:

D/AndroidRuntime( 1710): Shutting down VM


W/dalvikvm( 1710): threadid=1: thread exiting with uncaught exception (group=0xb412f180)
E/AndroidRuntime( 1710): FATAL EXCEPTION: main
E/AndroidRuntime( 1710): java.lang.UnsatisfiedLinkError: Couldn't load monodroid: findLibrary returned null
E/AndroidRuntime( 1710): at java.lang.Runtime.loadLibrary(Runtime.java:365)

Si es así, hay dos causas posibles:


1. El. apk no proporciona una ABI que el dispositivo de destino admite. Por ejemplo,. apk solo contiene
archivos binarios armeabi-v7a y el dispositivo de destino solo admite armeabi.
2. Un error de Android. En este caso, desinstale la aplicación, cruce los dedos y vuelva a instalar la aplicación.
Para corregir (1), edite las opciones y propiedades del proyecto y agregue compatibilidad para la ABI necesaria a la
lista de ABI admitidos. Para determinar qué ABI necesita agregar, ejecute el siguiente comando ADB en el
dispositivo de destino:

adb shell getprop ro.product.cpu.abi


adb shell getprop ro.product.cpu.abi2

La salida contendrá el Abi principal (y el secundario opcional).

$ adb shell getprop | grep ro.product.cpu


[ro.product.cpu.abi2]: [armeabi]
[ro.product.cpu.abi]: [armeabi-v7a]

La propiedad outpath no está establecida para el “proyecto MyApp.


csproj”
Por lo general, esto significa que tiene un equipo HP y “la” plataforma variable de entorno se ha establecido en
algo como MCD o HPD. Esto entra en conflicto con la propiedad de la plataforma MSBuild que “normalmente se”
establece en”cualquier CPU o “x86. Tendrá que quitar esta variable de entorno de la máquina para que MSBuild
pueda funcionar:
Panel de control > variables de entorno avanzadas del sistema > >
Reinicie Visual Studio o Visual Studio para Mac e intente volver a compilar. Ahora, las cosas deberían funcionar
según lo previsto.

Java. lang. ClassCastException: mono. Android. Runtime. JavaObject no


se puede convertir en...
Xamarin. Android 4. x no calcula correctamente las referencias de tipos genéricos anidados. Por ejemplo, considere
el siguiente código# de C mediante SimpleExpandableListAdapter:
// BAD CODE; DO NOT USE
var groupData = new List<IDictionary<string, object>> () {
new Dictionary<string, object> {
{ "NAME", "Group 1" },
{ "IS_EVEN", "This group is odd" },
},
};
var childData = new List<IList<IDictionary<string, object>>> () {
new List<IDictionary<string, object>> {
new Dictionary<string, object> {
{ "NAME", "Child 1" },
{ "IS_EVEN", "This group is odd" },
},
},
};
mAdapter = new SimpleExpandableListAdapter (
this,
groupData,
Android.Resource.Layout.SimpleExpandableListItem1,
new string[] { "NAME", "IS_EVEN" },
new int[] { Android.Resource.Id.Text1, Android.Resource.Id.Text2 },
childData,
Android.Resource.Layout.SimpleExpandableListItem2,
new string[] { "NAME", "IS_EVEN" },
new int[] { Android.Resource.Id.Text1, Android.Resource.Id.Text2 }
);

El problema es que Xamarin. Android serializa incorrectamente tipos genéricos anidados.


List<IDictionary<string, object>> se está serializando en java.lang.ArrrayList, pero ArrayList contiene instancias
mono.android.runtime.JavaObject (que hacen referencia a las instancias Dictionary<string, object> ) en lugar de
algo que implementa java.util.Map, por lo que se produce la siguiente excepción:

E/AndroidRuntime( 2991): FATAL EXCEPTION: main


E/AndroidRuntime( 2991): java.lang.ClassCastException: mono.android.runtime.JavaObject cannot be cast to
java.util.Map
E/AndroidRuntime( 2991): at
android.widget.SimpleExpandableListAdapter.getGroupView(SimpleExpandableListAdapter.java:278)
E/AndroidRuntime( 2991): at
android.widget.ExpandableListConnector.getView(ExpandableListConnector.java:446)
E/AndroidRuntime( 2991): at android.widget.AbsListView.obtainView(AbsListView.java:2271)
E/AndroidRuntime( 2991): at android.widget.ListView.makeAndAddView(ListView.java:1769)
E/AndroidRuntime( 2991): at android.widget.ListView.fillDown(ListView.java:672)
E/AndroidRuntime( 2991): at android.widget.ListView.fillFromTop(ListView.java:733)
E/AndroidRuntime( 2991): at android.widget.ListView.layoutChildren(ListView.java:1622)

La solución consiste en usar los tipos de colección de Java proporcionados en System.Collections.Generic lugar de
los “tipos” para los tipos internos. Esto producirá los tipos de Java adecuados al calcular las referencias de las
instancias. (El código siguiente es más complicado de lo necesario para reducir la duración de Gref. Se puede
simplificar para modificar el código original a través s/List/JavaList/g de s/Dictionary/JavaDictionary/g y si las
duraciones de Gref no son preocupadas).
// insert good code here
using (var groupData = new JavaList<IDictionary<string, object>> ()) {
using (var groupEntry = new JavaDictionary<string, object> ()) {
groupEntry.Add ("NAME", "Group 1");
groupEntry.Add ("IS_EVEN", "This group is odd");
groupData.Add (groupEntry);
}
using (var childData = new JavaList<IList<IDictionary<string, object>>> ()) {
using (var childEntry = new JavaList<IDictionary<string, object>> ())
using (var childEntryDict = new JavaDictionary<string, object> ()) {
childEntryDict.Add ("NAME", "Child 1");
childEntryDict.Add ("IS_EVEN", "This child is odd.");
childEntry.Add (childEntryDict);
childData.Add (childEntry);
}
mAdapter = new SimpleExpandableListAdapter (
this,
groupData,
Android.Resource.Layout.SimpleExpandableListItem1,
new string[] { "NAME", "IS_EVEN" },
new int[] { Android.Resource.Id.Text1, Android.Resource.Id.Text2 },
childData,
Android.Resource.Layout.SimpleExpandableListItem2,
new string[] { "NAME", "IS_EVEN" },
new int[] { Android.Resource.Id.Text1, Android.Resource.Id.Text2 }
);
}
}

Esto se corregirá en una versión futura.

Excepciones NullReferenceException inesperado


En ocasiones, el registro de depuración de Android mencionará excepciones NullReferenceException que “no se
pueden producir” o que provienen de mono para el código en tiempo de ejecución de Android justo antes de que
la aplicación sufra un problema:

E/mono(15202): Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of


an object
E/mono(15202): at Java.Lang.Object.GetObject (IntPtr handle, System.Type type, Boolean owned)
E/mono(15202): at Java.Lang.Object._GetObject[IOnTouchListener] (IntPtr handle, Boolean owned)
E/mono(15202): at Java.Lang.Object.GetObject[IOnTouchListener] (IntPtr handle, Boolean owned)
E/mono(15202): at
Android.Views.View+IOnTouchListenerAdapter.n_OnTouch_Landroid_view_View_Landroid_view_MotionEvent_(IntPtr
jnienv, IntPtr native__this, IntPtr native_v, IntPtr native_e)
E/mono(15202): at (wrapper dynamic-method) object:b039cbb0-15e9-4f47-87ce-442060701362
(intptr,intptr,intptr,intptr)

E/mono ( 4176): Unhandled Exception:


E/mono ( 4176): System.NullReferenceException: Object reference not set to an instance of an object
E/mono ( 4176): at Android.Runtime.JNIEnv.NewString (string)
E/mono ( 4176): at Android.Util.Log.Info (string,string)

Esto puede ocurrir cuando el tiempo de ejecución de Android decide anular el proceso, lo que puede ocurrir por
diversos motivos, como alcanzar el límite de Gref de destino “o” realizar algún error con JNI.
Para ver si este es el caso, compruebe en el registro de depuración de Android si hay un mensaje de su proceso
similar al siguiente:
E/dalvikvm( 123): VM aborting

Anular debido a agotamiento de referencia global


La capa de JNI del Runtime de Android solo admite un número limitado de referencias de objeto JNI para ser
válidas en un momento dado. Cuando se supera este límite, se interrumpen las cosas.
El límite de GREF (referencia global) es 2000 referencias en el emulador y ~ 52000 referencias en el hardware.
Sabe que va a empezar a crear demasiadas GREFs cuando vea mensajes como este en el registro de depuración
de Android:

D/dalvikvm( 602): GREF has increased to 1801

Cuando se alcanza el límite de GREF, se imprime un mensaje como el siguiente:


D/dalvikvm( 602): GREF has increased to 2001
W/dalvikvm( 602): Last 10 entries in JNI global reference table:
W/dalvikvm( 602): 1991: 0x4057eff8 cls=Landroid/graphics/Point; (20 bytes)
W/dalvikvm( 602): 1992: 0x4057f010 cls=Landroid/graphics/Point; (28 bytes)
W/dalvikvm( 602): 1993: 0x40698e70 cls=Landroid/graphics/Point; (20 bytes)
W/dalvikvm( 602): 1994: 0x40698e88 cls=Landroid/graphics/Point; (20 bytes)
W/dalvikvm( 602): 1995: 0x40698ea0 cls=Landroid/graphics/Point; (28 bytes)
W/dalvikvm( 602): 1996: 0x406981f0 cls=Landroid/graphics/Point; (20 bytes)
W/dalvikvm( 602): 1997: 0x40698208 cls=Landroid/graphics/Point; (20 bytes)
W/dalvikvm( 602): 1998: 0x40698220 cls=Landroid/graphics/Point; (28 bytes)
W/dalvikvm( 602): 1999: 0x406956a8 cls=Landroid/graphics/Point; (20 bytes)
W/dalvikvm( 602): 2000: 0x406956c0 cls=Landroid/graphics/Point; (20 bytes)
W/dalvikvm( 602): JNI global reference table summary (2001 entries):
W/dalvikvm( 602): 51 of Ljava/lang/Class; 164B (41 unique)
W/dalvikvm( 602): 46 of Ljava/lang/Class; 188B (17 unique)
W/dalvikvm( 602): 6 of Ljava/lang/Class; 212B (6 unique)
W/dalvikvm( 602): 11 of Ljava/lang/Class; 236B (7 unique)
W/dalvikvm( 602): 3 of Ljava/lang/Class; 260B (3 unique)
W/dalvikvm( 602): 4 of Ljava/lang/Class; 284B (2 unique)
W/dalvikvm( 602): 8 of Ljava/lang/Class; 308B (6 unique)
W/dalvikvm( 602): 1 of Ljava/lang/Class; 316B
W/dalvikvm( 602): 4 of Ljava/lang/Class; 332B (3 unique)
W/dalvikvm( 602): 1 of Ljava/lang/Class; 356B
W/dalvikvm( 602): 2 of Ljava/lang/Class; 380B (1 unique)
W/dalvikvm( 602): 1 of Ljava/lang/Class; 428B
W/dalvikvm( 602): 1 of Ljava/lang/Class; 452B
W/dalvikvm( 602): 1 of Ljava/lang/Class; 476B
W/dalvikvm( 602): 2 of Ljava/lang/Class; 500B (1 unique)
W/dalvikvm( 602): 1 of Ljava/lang/Class; 548B
W/dalvikvm( 602): 1 of Ljava/lang/Class; 572B
W/dalvikvm( 602): 2 of Ljava/lang/Class; 596B (2 unique)
W/dalvikvm( 602): 1 of Ljava/lang/Class; 692B
W/dalvikvm( 602): 1 of Ljava/lang/Class; 956B
W/dalvikvm( 602): 1 of Ljava/lang/Class; 1004B
W/dalvikvm( 602): 1 of Ljava/lang/Class; 1148B
W/dalvikvm( 602): 2 of Ljava/lang/Class; 1172B (1 unique)
W/dalvikvm( 602): 1 of Ljava/lang/Class; 1316B
W/dalvikvm( 602): 1 of Ljava/lang/Class; 3428B
W/dalvikvm( 602): 1 of Ljava/lang/Class; 3452B
W/dalvikvm( 602): 1 of Ljava/lang/String; 28B
W/dalvikvm( 602): 2 of Ldalvik/system/VMRuntime; 12B (1 unique)
W/dalvikvm( 602): 10 of Ljava/lang/ref/WeakReference; 28B (10 unique)
W/dalvikvm( 602): 1 of Ldalvik/system/PathClassLoader; 44B
W/dalvikvm( 602): 1553 of Landroid/graphics/Point; 20B (1553 unique)
W/dalvikvm( 602): 261 of Landroid/graphics/Point; 28B (261 unique)
W/dalvikvm( 602): 1 of Landroid/view/MotionEvent; 100B
W/dalvikvm( 602): 1 of Landroid/app/ActivityThread$ApplicationThread; 28B
W/dalvikvm( 602): 1 of Landroid/content/ContentProvider$Transport; 28B
W/dalvikvm( 602): 1 of Landroid/view/Surface$CompatibleCanvas; 44B
W/dalvikvm( 602): 1 of Landroid/view/inputmethod/InputMethodManager$ControlledInputConnectionWrapper; 36B
W/dalvikvm( 602): 1 of Landroid/view/ViewRoot$1; 12B
W/dalvikvm( 602): 1 of Landroid/view/ViewRoot$W; 28B
W/dalvikvm( 602): 1 of Landroid/view/inputmethod/InputMethodManager$1; 28B
W/dalvikvm( 602): 1 of Landroid/view/accessibility/AccessibilityManager$1; 28B
W/dalvikvm( 602): 1 of Landroid/widget/LinearLayout$LayoutParams; 44B
W/dalvikvm( 602): 1 of Landroid/widget/LinearLayout; 332B
W/dalvikvm( 602): 2 of Lorg/apache/harmony/xnet/provider/jsse/TrustManagerImpl; 28B (1 unique)
W/dalvikvm( 602): 1 of Landroid/view/SurfaceView$MyWindow; 36B
W/dalvikvm( 602): 1 of Ltouchtest/RenderThread; 92B
W/dalvikvm( 602): 1 of Landroid/view/SurfaceView$3; 12B
W/dalvikvm( 602): 1 of Ltouchtest/DrawingView; 412B
W/dalvikvm( 602): 1 of Ltouchtest/Activity1; 180B
W/dalvikvm( 602): Memory held directly by tracked refs is 75624 bytes
E/dalvikvm( 602): Excessive JNI global references (2001)
E/dalvikvm( 602): VM aborting
En el ejemplo anterior (que, casualmente, proviene del error 685215), el problema es que se están creando
demasiadas instancias de Android. Graphics. Point; vea el #comentario 2 para obtener una lista de las correcciones
de este error concreto.
Normalmente, una solución útil es encontrar el tipo que tiene demasiadas instancias asignadas – Android.
Graphics. Point en el volcado – anterior y, a continuación, buscar el lugar en el que se crearon en el código fuente y
desecharlos de forma adecuada (de modo que su La duración de los objetos de Java se acorta). Esto no siempre es
adecuado (#685215 es multiproceso, por lo que la solución trivial evita la llamada a Dispose), pero es lo primero
que hay que tener en cuenta.
Puede habilitar el registro de Gref para ver cuándo se crean GREFs y cuántos existen.

Anular debido a que el tipo de JNI no coincide


Si realiza la entrega manual de código JNI, es posible que los tipos no coincidan correctamente, por ejemplo, si
intenta invocar java.lang.Runnable.run en un tipo que no implementa. java.lang.Runnable Cuando esto suceda,
habrá un mensaje similar al siguiente en el registro de depuración de Android:

W/dalvikvm( 123): JNI WARNING: can't call Ljava/Type;;.method on instance of Lanother/java/Type;


W/dalvikvm( 123): in Lmono/java/lang/RunnableImplementor;.n_run:()V (CallVoidMethodA)
...
E/dalvikvm( 123): VM aborting

Compatibilidad con código dinámico


El código dinámico no se compila
Para usar C# Dynamic en la aplicación o biblioteca, tiene que agregar System. Core. dll, Microsoft. CSharp. dll y
mono. CSharp. dll al proyecto.
En la compilación de versión, MissingMethodException se produce para el código dinámico en tiempo de
ejecución.
Es probable que el proyecto de aplicación no tenga referencias a System. Core. dll, Microsoft. CSharp. dll o
mono. CSharp. dll. Asegúrese de que se hace referencia a esos ensamblados.
Tenga en cuenta que el código dinámico siempre cuesta. Si necesita código eficaz, considere la
posibilidad de no usar código dinámico.
En la primera vista previa, se excluyen esos ensamblados a menos que el código de aplicación use
explícitamente los tipos de cada ensamblado. Vea lo siguiente para obtener una solución
alternativa:http://lists.ximian.com/pipermail/mo...il/009798.html

Proyectos compilados con el bloqueo de AOT + LLVM en dispositivos


x86
Al implementar una aplicación compilada con AOT + LLVM en dispositivos basados en x86, es posible que vea un
mensaje de error de excepción similar al siguiente:

Assertion: should not be reached at /Users/.../external/mono/mono/mini/tramp-x86.c:124


Fatal signal 6 (SIGABRT), code -6 in tid 4051 (amarin.bug56111)

Se trata de un problema conocido tal y como se indicó en 56111. La solución consiste en deshabilitar LLVM.
Preguntas más frecuentes de Android
11/07/2019 • 7 minutes to read • Edit Online

Instalación y configuración
¿Qué paquetes de Android SDK debo instalar?
Instalar el SDK de Android no incluye automáticamente todos los paquetes mínimos necesarios para el desarrollo.
Aunque necesitan varían para desarrolladores individuales, esta guía describe los paquetes que suele ser
necesarios para el desarrollo con Xamarin.Android.
¿Dónde puedo configurar mi ubicaciones de Android SDK?
Esta guía describe la configuración de predeterminada del SDK de Android, que debería funcionar para la mayoría
de las instalaciones; y cómo cambiar estos valores predeterminados en Visual Studio para Mac o Visual Studio si
es necesario.
¿Cómo se puede actualizar la versión del kit de desarrollo de Java (JDK )?
En este artículo muestra cómo actualizar la versión de Java Development Kit (JDK) en Windows y Mac.
¿Puedo usar Java Development Kit (JDK ) versión 9 o posterior?
Xamarin.Android requiere JDK 8 o Microsoft Mobile OpenJDK. En este artículo se enumera algunos mensajes de
error comunes que puede ver si está instalado JDK 9 o posterior, así como instrucciones para comprobar la versión
JDK.
¿Cómo instalar manualmente las bibliotecas de compatibilidad de Android que requieren los paquetes de
Xamarin.Android.Support?
Esta guía proporciona pasos de ejemplo para instalar el Xamarin.Android.Support.v4 biblioteca de soporte técnico
de Windows y Mac.
¿Qué controladores USB son necesario para depurar Android en Windows?
Para depurar en un dispositivo Android al desarrollar en Windows; deberá instalar a un controlador USB
compatible. Android SDK Manager incluye "Controlador USB de Google" de forma predeterminada, lo que agrega
compatibilidad para dispositivos Nexus. Otros dispositivos requieren controladores USB publicados por el
fabricante del dispositivo. Esta guía proporciona información sobre cómo buscar a estos controladores
alternativos, así como métodos de prueba.
¿Es posible conectarse a emuladores de Android que se ejecutan en un Mac desde una máquina virtual de
Windows?
Esta guía abarca métodos cuando se usa el emulador de Android.

Preguntas generales
¿Cómo se automatiza un proyecto de prueba de NUnit de Android?
Esta guía explica cómo configurar un proyecto de prueba NUnit de Android, no un proyecto de Xamarin.UITest.
Encontrará guías Xamarin.UITest aquí.
¿Por qué no se puede conectar la compilación de versión de Android a Internet?
La causa más común de este problema es que la INTERNET permiso se incluye automáticamente en una
compilación de depuración, pero debe establecerse manualmente para una versión de lanzamiento. Esta guía
describe cómo habilitar el permiso en las compilaciones de versión.
Paquetes NuGet más inteligentes de Xamarin Android Support v4/v13
Support-v4 y Support-v13 no pueden usarse juntos en la misma aplicación, es decir, son mutuamente excluyentes.
Esto es porque Support-v13 realmente contiene todos los tipos y la implementación de Support-v4 . Si intenta
hacer referencia tanto en el mismo proyecto, se producirán errores de tipo duplicado.
¿Cómo se puede resolver un PathTooLongException Error?
En este artículo se explica cómo resolver un PathTooLongException error que puede producirse durante la
compilación de un proyecto de Xamarin.Android.

En desuso
NOTE
Los artículos siguientes se aplican a los problemas que se han resuelto en versiones recientes de Xamarin. Sin embargo, si el
problema se produce en la versión más reciente del software, registre un nuevo error con el control de versiones completo
completa y la información de salida del registro de compilación.

¿Qué versión de Xamarin.Android agrega compatibilidad con Lollipop?


Esta guía se escribió originalmente para la versión preliminar de L Android. 4.17 Xamarin.Android agrega
compatibilidad con Android versión preliminar de L & 4.20 Xamarin.Android agregan compatibilidad de Android
Lollipop.
Android.Support.v7.AppCompat: no se encontró ningún recurso que coincida con el nombre especificado: attr
'android: actionModeShareDrawable'
Este error puede producirse en versiones anteriores de Xamarin si faltan algunos de los paquetes de Android SDK
necesarios.
Ajuste de los parámetros de memoria de Java para Android Designer
Los parámetros de memoria predeterminados que se usan al iniciar el java procesar para el Diseñador de
Android podría ser incompatible con algunas configuraciones del sistema. A partir de Xamarin Studio 5.7.2.7 y
Xamarin para Visual Studio 3.9.344 estas opciones se puede personalizar en cada proyecto.
Mi archivo Resource.designer.cs de Android no se actualizará
Un error en la versión 5.1 Xamarin.Studio había dañado previamente archivos .csproj eliminando parcial o
totalmente el código xml en el archivo .csproj. Esto provocaría que importantes del sistema (como actualizar el
Resource.designer.cs de Android) de la compilación de partes de Android para producir un error. A partir de la
5.1.4 estable de la versión del 15 de julio de, este error se ha corregido; pero en muchos casos, el archivo de
proyecto tiene que reparar manualmente, tal como se describe en esta guía.
¿Qué paquetes de Android SDK debo instalar?
11/07/2019 • 2 minutes to read • Edit Online

Instalar el SDK de Android no incluye automáticamente todos los paquetes mínimos necesarios para el desarrollo.
Aunque necesitan varían para desarrolladores individuales, suele ser necesarios para el desarrollo con
Xamarin.Android los siguientes paquetes:

Herramientas
Instale las herramientas más recientes de la carpeta de herramientas en el Administrador de SDK:
Herramientas de Android SDK
Herramientas de la plataforma Android SDK
Herramientas de compilación de Android SDK

Plataformas de Android
Instale la "plataforma de SDK" para las versiones de Android que ha establecido como mínimo y de destino.
Ejemplos:
API 23 de destino
Mínimo de API 23
Solo necesita instalar el SDK de plataforma de API 23
API 23 de destino
Mínimo de API 15
Debe instalar el SDK de plataformas para API 15 y 23. Tenga en cuenta que no es necesario instalar los niveles de
API entre los valores mínimo y de destino (incluso si son backporting para esos niveles de API).

Imágenes del sistema


Estos son solo es necesario si desea utilizar los emuladores de Android de fábrica de Google. Para obtener más
información, consulte configuración de Android Emulator

Extras
Los Extras de SDK de Android no suelen ser necesarios; pero resulta útil ser consciente de ellos, ya que pueden ser
necesarios según el caso de uso.

Información adicional
La siguiente guía cubre estas opciones y entra en más detalles sobre los paquetes del SDK manager tiene
disponible: Guía de instalación de Android SDK Manager
¿Dónde puedo configurar mi ubicaciones de Android
SDK?
11/07/2019 • 3 minutes to read • Edit Online

Visual Studio
Visual Studio para Mac
En Visual Studio, vaya a Herramientas > Opciones > Xamarin > configuración de Android para ver y
establecer la ubicación de Android SDK:

La ubicación predeterminada para cada ruta de acceso es como sigue:


Ubicación de Java Development Kit:
C:\archivos de programa\Java\jdk1.8.0_131
Ubicación de Android SDK:
C:\Archivos de programa (x86)\Android\android-sdk
Ubicación de Android NDK:
C:\ProgramData\Microsoft\AndroidNDK64\android-ndk-r13b
Tenga en cuenta que el número de versión del NDK puede variar. Por ejemplo, en lugar de android-ndk-r13b,
podría ser una versión anterior como android-ndk-r10e.
Para establecer la ubicación de Android SDK, escriba la ruta de acceso completa del directorio de Android SDK en
el ubicación de Android SDK cuadro. Puede navegar a la ubicación de Android SDK en el Explorador de
archivos, copiar la ruta de acceso de la barra de direcciones y pegue esta ruta de acceso en el ubicación de
Android SDK cuadro. Por ejemplo, si es la ubicación de Android SDK en
C:\usuarios\username\AppData\Local\Android\Sdk, desactive la antigua ruta en el Ubicación de Android
SDK cuadro, pegue en esta ruta de acceso y haga clic en Aceptar.
¿Cómo se puede actualizar la versión del kit de
desarrollo de Java (JDK)?
16/08/2019 • 2 minutes to read • Edit Online

En este artículo se muestra cómo actualizar la versión del kit de desarrollo de Java (JDK ) en Windows y Mac.

Información general
Xamarin. Android usa el kit de desarrollo de Java (JDK) para integrarlo con la Android SDK para compilar
aplicaciones de Android y ejecutar Android Designer. Las versiones más recientes del Android SDK (API 24 y
versiones posteriores) requieren JDK 8 (1,8). Como alternativa, puede instalar la versión preliminar de Microsoft
Mobile OpenJDK. Microsoft Mobile OpenJDK reemplazará finalmente JDK 8 para el desarrollo de Xamarin.
Android.
Para actualizar a Microsoft Mobile OpenJDK, consulte Microsoft Mobile OpenJDK Preview. Para actualizar a JDK
8, siga estos pasos:
Visual Studio
Visual Studio para Mac
1. Descargue JDK 8 (1,8) del sitio web de Oracle:

2. Seleccione la versión de 64 bits para permitir la representación de controles personalizados en Xamarin


Android Designer:
3. Ejecute el archivo. exe e instale las herramientas de desarrollo:

4. Abra Visual Studio y actualice la Ubicación del kit de desarrollo de Java para que apunte al nuevo JDK
en herramientas > Opciones > la configuración de Xamarin > Android > Ubicación del kit de
desarrollo de Java:

Asegúrese de reiniciar Visual Studio después de actualizar la ubicación.


Kit de desarrollo de Java 9 o posterior y
Xamarin.Android
11/07/2019 • 4 minutes to read • Edit Online

Este artículo explica cómo resolver Java Development Kit (JDK ) 9 o posterior errores en Xamarin.Android.

Información general
Xamarin.Android usa Java Development Kit (JDK) para integrar con el SDK de Android para compilar aplicaciones
de Android y ejecutar el Diseñador de Android. Las versiones más recientes de Android SDK (API 24 y versiones
posterior) requieren JDK 8 (1.8) o la versión preliminar de Microsoft Mobile OpenJDK. Dado que las
herramientas de Android SDK está disponibles en Google aún no son compatibles con JDK 9,
Xamarin.Android no funciona con JDK 9 o posterior.

Errores del JDK


Si intenta compilar un proyecto de Xamarin.Android con una versión de JDK posterior al 8 de JDK, obtendrá un
error explícito que indica que no se admite esta versión de JDK. Por ejemplo:

Building with JDK Version `9.0.4` is not supported. Please install JDK version `1.8.0`. See
https://aka.ms/xamarin/jdk9-errors

Para resolver estos errores, debe instalar JDK 8 (1.8) como se explica en ¿cómo se puede actualizar la versión de
Java Development Kit (JDK)?. Como alternativa, puede instalar el versión preliminar de Microsoft Mobile
OpenJDK OpenJDK de The Microsoft Mobile reemplazará finalmente a JDK 8 para el desarrollo de
Xamarin.Android.

Comprobación de la versión JDK


También puede comprobar qué versión de Java que se ha instalado, escriba el comando siguiente (el JDK bin
directorio debe estar en su PATH ):

java -version

Si instaló JDK 9, verá un mensaje similar al siguiente:

java version "9.0.4"


Java(TM) SE Runtime Environment (build 9.0.4+11)
Java HotSpot(TM) 64-Bit Server VM (build 9.0.4+11, mixed mode)

Si está instalado el JDK 9 o posterior, debe instalar Java JDK 8 (1.8) o la versión preliminar de Microsoft Mobile
OpenJDK. Para obtener información sobre cómo instalar JDK 8, vea ¿cómo se puede actualizar la versión de Java
Development Kit (JDK)?. Para obtener información sobre cómo instalar Microsoft Mobile OpenJDK, consulte
versión preliminar de Microsoft Mobile OpenJDK.
Tenga en cuenta que no es necesario desinstalar una versión posterior del JDK; Sin embargo, debe asegurarse de
que está utilizando Xamarin JDK 8 en lugar de una versión posterior de JDK. En Visual Studio, haga clic en
Herramientas > Opciones > Xamarin > configuración de Android. Si ubicación de Java Development Kit
no está establecida en una ubicación de JDK 8 (como C:\archivos de programa\Java\jdk1.8.0_111), haga clic en
cambio y establézcalo en la ubicación donde está instalado el JDK 8. En Visual Studio para Mac, vaya a
Preferencias > proyectos > ubicaciones de SDK > Android > SDK de Java (JDK) y haga clic en examinar
para actualizar esta ruta de acceso.

Problemas conocidos de JDK 9


apksigner
Hay un problema conocido con apksigner y JDK 9 en el que el apksigner.bat archivo invoca el apksigner.jar con
-Djava.ext.dirs en lugar de -classpath que espera JDK 9. Se recomienda usar JDK 8 (1.8 ). Para obtener
información sobre cómo instalar JDK 8, vea ¿cómo se puede actualizar la versión de Java Development Kit (JDK)?
Si ha instalado JDK 9, asegúrese de que la siguiente ruta de acceso no está establecido en su PATH variable de
entorno tal como se seguirán apuntando hacia el JDK 9: C:\ProgramData\Oracle\Java\javapath . Después de quitarla,
java-version en una línea de comandos debe mostrar JDK 8.
¿Cómo instalar manualmente las bibliotecas de
compatibilidad de Android que requieren los
paquetes de Xamarin.Android.Support?
11/07/2019 • 8 minutes to read • Edit Online

Pasos de ejemplo para Xamarin.Android.Support.v4


Visual Studio
Visual Studio para Mac
Descargue el paquete Xamarin.Android.Support NuGet deseado (por ejemplo, puede instalarlo con el
Administrador de paquetes de NuGet).
Use ildasm para comprobar qué versión de android_m2repository.zip el paquete NuGet necesita:

ildasm /caverbal /text /item:Xamarin.Android.Support.v4


packages\Xamarin.Android.Support.v4.23.4.0.1\lib\MonoAndroid403\Xamarin.Android.Support.v4.dll | findstr
SourceUrl

Salida del ejemplo:

property string 'SourceUrl' = string('https://dl-


ssl.google.com/android/repository/android_m2repository_r32.zip')
property string 'SourceUrl' = string('https://dl-
ssl.google.com/android/repository/android_m2repository_r32.zip')
property string 'SourceUrl' = string('https://dl-
ssl.google.com/android/repository/android_m2repository_r32.zip')

Descargar android_m2repository.zip de Google con la dirección URL devuelta desde ildasm. Como alternativa,
puede comprobar qué versión de la Android Support Repository actualmente instalada en Android SDK Manager:
Si la versión coincida con el que necesita para el paquete de NuGet, no debe descargar nada nuevo. Puede en su
lugar, volver a comprimir a existente m2repository directorio que se encuentra en extras\android en el ruta de
acceso del SDK (como se muestra la parte superior de Android Ventana de SDK Manager).
Calcular el hash MD5 de la dirección URL devuelta ildasm. Dar formato a la cadena resultante para utilizar todas
las letras en mayúsculas y sin espacios en blanco. Por ejemplo, ajustar el $url variable como sea necesario y, a
continuación, ejecute las siguientes 2 líneas (según original C# código de Xamarin.Android) en PowerShell:

$url = "https://dl-ssl.google.com/android/repository/android_m2repository_r32.zip"
(([System.Security.Cryptography.MD5]::Create()).ComputeHash([System.Text.Encoding]::UTF8.GetBytes($url)) | %{
$_.ToString("X02") }) -join ""

Salida del ejemplo:

F16A3455987DBAE5783F058F19F7FCDF

Copia android_m2repository.zip en el % LOCALAPPDATA %\Xamarin\zips\ carpeta. Cambie el nombre del


archivo para utilizar el hash MD5 del hash MD5 anterior paso de cálculo. Por ejemplo:
%LOCALAPPDATA%\Xamarin\zips\F16A3455987DBAE5783F058F19F7FCDF.zip
(Opcional) Descomprima el archivo en % LOCALAPPDATA
%\Xamarin\Xamarin.Android.Support.v4\23.4.0.0\contenido\ (creación de un contenido\m2repository
subdirectorio). Si omite este paso, la primera compilación que usa la biblioteca se tardará un poco más tiempo
porque necesitará completar este paso. El número de versión del subdirectorio (23.4.0.0 en este ejemplo) no es
exactamente lo mismo que la versión del paquete NuGet. Puede usar ildasm para buscar el número de versión
correcto:

ildasm /caverbal /text /item:Xamarin.Android.Support.v4


packages\Xamarin.Android.Support.v4.23.4.0.1\lib\MonoAndroid403\Xamarin.Android.Support.v4.dll | findstr
/C:"string 'Version'"

Salida del ejemplo:

property string 'Version' = string('23.4.0.0')}


property string 'Version' = string('23.4.0.0')}
property string 'Version' = string('23.4.0.0')}

Referencias adicionales
Error 43245 – inexacto "no se pudo descargar. Descargue {0} y colóquelo la {1} directorio. " y "instale el paquete:
'{0}' disponibles en el instalador del SDK de" mensajes de error relacionados con paquetes de
Xamarin.Android.Support
Pasos siguientes
Este documento describe el comportamiento actual a partir de agosto de 2016. La técnica descrita en este
documento no forma parte de la serie de pruebas estable para Xamarin, por lo que podría dejar de hacerlo en el
futuro.
Para obtener más ayuda, póngase en contacto con nosotros, o si este problema permanece incluso después de la
utilización de la información anterior, consulte la sección qué opciones de soporte técnico están disponibles para
Xamarin? para obtener información sobre las opciones de contacto, sugerencias, así como cómo archivar un error
nuevo si es necesario.
¿Qué controladores USB son necesario para depurar
Android en Windows?
11/07/2019 • 2 minutes to read • Edit Online

Buscar controladores USB


Para depurar en un dispositivo Android al desarrollar en Windows; deberá instalar a un controlador USB
compatible. Android SDK Manager incluye "Controlador USB de Google" de forma predeterminada, lo que agrega
compatibilidad para dispositivos de Nexus como se describe aquí: https://developer.android.com/sdk/win-usb.html
Otros dispositivos requieren controladores USB específicamente publicados por el fabricante del dispositivo. En
esta guía se incluyen algunos vínculos para los fabricantes más comunes:
https://developer.android.com/tools/extras/oem-usb.html

Alternativas
Según la por el fabricante, puede ser difícil de rastrear el controlador USB exacto necesitado. Desarrollan algunas
alternativas para probar aplicaciones de Android en Windows incluido mediante un emulador de Android o con
servicios externos de pruebas. Algunas de ellas son:
App Center Test : las pruebas se ejecutan en cientos de dispositivos Android reales de los servicios de nube.
Emulador de Visual Studio para Android
Depuración en Android Emulator
¿Es posible conectarse a emuladores de Android que
se ejecutan en un Mac desde una máquina virtual de
Windows?
16/08/2019 • 7 minutes to read • Edit Online

Para conectarse al Android Emulator que se ejecuta en un equipo Mac desde una máquina virtual de Windows,
siga estos pasos:
1. Inicie el emulador en el equipo Mac.
2. Eliminar el adb servidor en el equipo Mac:

adb kill-server

3. Tenga en cuenta que el emulador está escuchando en dos puertos TCP en la interfaz de red de bucle
invertido:

lsof -iTCP -sTCP:LISTEN -P | grep 'emulator\|qemu'

emulator6 94105 macuser 20u IPv4 0xa8dacfb1d4a1b51f 0t0 TCP localhost:5555 (LISTEN)
emulator6 94105 macuser 21u IPv4 0xa8dacfb1d845a51f 0t0 TCP localhost:5554 (LISTEN)

El puerto impar es el que se utiliza para conectarse a adb . Vea también


https://developer.android.com/tools/devices/emulator.html#emulatornetworking.
4. Opción 1: Realice nc para reenviar paquetes TCP entrantes recibidos externamente en el puerto 5555 (o en
cualquier otro puerto que desee) al puerto impar en la interfaz de bucle invertido (127.0.0.1 5555 en este
ejemplo) y para reenviar los paquetes salientes de otra manera:

cd /tmp
mkfifo backpipe
nc -kl 5555 0<backpipe | nc 127.0.0.1 5555 > backpipe

Siempre y cuando los nc comandos sigan ejecutándose en una ventana de terminal, los paquetes se
reenviarán según lo previsto. Puede escribir control-C en la ventana de terminal para salir de nc los
comandos una vez que haya terminado de usar el emulador.
(La opción 1 suele ser más fácil que la opción 2, especialmente si las preferencias del sistema >
seguridad & privacidad > Firewall está activada).
Opción 2: Realice pfctl para redirigir los paquetes TCP desde el 5555 puerto (o cualquier otro puerto que
desee) de la interfaz de red compartida al puerto impar en la interfaz de bucle invertido 127.0.0.1:5555 (en
este ejemplo):

sed '/rdr-anchor/a rdr pass on vmnet8 inet proto tcp from any to any port 5555 -> 127.0.0.1 port 5555'
/etc/pf.conf | sudo pfctl -ef -

Este comando configura el reenvío de puertos mediante pf packet filter el servicio de sistema de. Los
saltos de línea son importantes. Asegúrese de mantenerlos intactos al pegarlos. También tendrá que ajustar
el nombre de la interfaz de vmnet8 si utiliza Parallels. vmnet8 es el nombre del dispositivo NAT especial para
el modo de redes compartidas en la fusión de VMware. Es probable que la interfaz de red adecuada en
Parallels sea vnic0.
5. Conéctese al emulador desde la máquina Windows:

C:\> adb connect ip-address-of-the-mac:5555

Reemplace "IP -address-of-the-Mac" por la dirección IP del equipo Mac, por ejemplo, como se
ifconfig vmnet8 | grep 'inet ' muestra en. Si es necesario, 5555 reemplace por el otro puerto que desee
del paso 4.. (Nota: una manera de obtener acceso a la línea de adb comandos a es mediante Herramientas
> el símbolo del sistema Android > Android ADB en Visual Studio).
Técnica alternativa con ssh
Si ha habilitado sesión remota en el equipo Mac, puede usar ssh el reenvío de puerto para conectarse al
emulador.
1. Instale un cliente SSH en Windows. Una opción es instalar git para Windows. El ssh comando estará
disponible en el símbolo del sistema de git Bash .
2. Siga los pasos del 1-3 de arriba para iniciar el emulador adb , eliminar el servidor en el equipo Mac e
identificar los puertos del emulador.
3. Ejecute ssh en Windows para configurar el reenvío de Puerto bidireccional entre un puerto local en
Windows ( localhost:15555 en este ejemplo) y el puerto del emulador impar en la interfaz de bucle
invertido de Mac 127.0.0.1:5555 (en este ejemplo):

C:\> ssh -L localhost:15555:127.0.0.1:5555 mac-username@ip-address-of-the-mac

Reemplace mac-username por el nombre de usuario de Mac whoami como se indica en. Reemplace
ip-address-of-the-mac por la dirección IP del equipo Mac.
4. Conéctese al emulador mediante el puerto local en Windows:

C:\> adb connect localhost:15555

(Nota: una forma sencilla de obtener acceso a la línea de adb comandos a es mediante Herramientas > el
símbolo del sistema Android > Android ADB en Visual Studio).
Una pequeña PRECAUCIÓN: Si usa el puerto 5555 para el puerto local, adb se considerará que el emulador se
ejecuta localmente en Windows. Esto no causa ningún problema en Visual Studio, pero en Visual Studio para Mac
hace que la aplicación se cierre inmediatamente después del inicio.
Todavía no se adb -H admite la técnica alternativa con
En teoría, otro enfoque sería usar adb la funcionalidad integrada de para conectarse a un adb servidor que se
ejecuta en un equipo remoto (vea por ejemplo https://stackoverflow.com/a/18551325). Sin embargo, las
extensiones IDE de Xamarin. Android no proporcionan una manera de configurar esta opción.

Información de contacto
En este documento se describe el comportamiento actual a partir de marzo de 2016. La técnica descrita en este
documento no forma parte del conjunto de pruebas estable para Xamarin, por lo que podría interrumpirse en el
futuro.
Si observa que la técnica ya no funciona o observa otros errores en el documento, no dude en agregarla a la
discusión en el siguiente subproceso del Foro: http://forums.xamarin.com/discussion/33702/android-emulator-
from-host-device-inside-windows-vm. Gracias
¿Cómo se automatiza un proyecto de prueba de
NUnit de Android?
16/08/2019 • 3 minutes to read • Edit Online

NOTE
En esta guía se explica cómo automatizar un proyecto de prueba de NUnit de Android, no un proyecto de Xamarin. UITest.
Las guías de Xamarin. UITest se pueden encontrar aquí.

Al crear un proyecto de aplicación de prueba unitaria (Android) en Visual Studio (o un proyecto de prueba
unitaria de Android en Visual Studio para Mac), este proyecto no ejecutará automáticamente las pruebas de
forma predeterminada. Para ejecutar pruebas NUnit en un dispositivo de destino, puede crear una subclase de
Android. app. Instrumentation que se inicie con el siguiente comando:

adb shell am instrument

En los pasos siguientes se explica este proceso:


1. Cree un nuevo archivo denominado TestInstrumentation.CS:

using System;
using System.Reflection;
using Android.App;
using Android.Content;
using Android.Runtime;
using Xamarin.Android.NUnitLite;

namespace App.Tests {

[Instrumentation(Name="app.tests.TestInstrumentation")]
public class TestInstrumentation : TestSuiteInstrumentation {

public TestInstrumentation (IntPtr handle, JniHandleOwnership transfer) : base (handle,


transfer)
{
}

protected override void AddTests ()


{
AddTest (Assembly.GetExecutingAssembly ());
}
}
}

En este archivo, Xamarin.Android.NUnitLite.TestSuiteInstrumentation (de Xamarin. Android. NUnitLite.


dll) se crean subclases para TestInstrumentation crear.
2. Implemente TestInstrumentation el constructor y AddTests el método. El AddTests método controla qué
pruebas se ejecutan realmente.
3. Modifique el .csproj archivo para agregar TestInstrumentation.CS. Por ejemplo:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
...
<ItemGroup>
<Compile Include="TestInstrumentation.cs" />
</ItemGroup>
<Target Name="RunTests" DependsOnTargets="_ValidateAndroidPackageProperties">
<Exec Command="&quot;$(_AndroidPlatformToolsDirectory)adb&quot; $(AdbTarget) $(AdbOptions) shell
am instrument -w $(_AndroidPackage)/app.tests.TestInstrumentation" />
</Target>
...
</Project>

4. Use el siguiente comando para ejecutar las pruebas unitarias. Reemplazar PACKAGE_NAME por el nombre del
paquete de la aplicación (el nombre del paquete se puede encontrar en /manifest/@package el atributo de la
aplicación que se encuentra en archivo AndroidManifest. XML ):

adb shell am instrument -w PACKAGE_NAME/app.tests.TestInstrumentation

5. Opcionalmente, puede modificar el .csproj archivo para agregar el RunTests destino de MSBuild. Esto
hace posible invocar las pruebas unitarias con un comando como el siguiente:

msbuild /t:RunTests Project.csproj

(Tenga en cuenta que no es necesario usar este nuevo destino; adb se puede usar el comando anterior en
msbuild lugar de).

Para obtener más información sobre el adb shell am instrument uso del comando para ejecutar pruebas unitarias,
vea el tema Android Developer Running tests with ADB .

NOTE
Con la versión Xamarin. Android 5,0 , los nombres de paquete predeterminados para los contenedores a los que se puede
llamar de Android se basarán en el md5sum del nombre calificado con el ensamblado del tipo que se va a exportar. Esto
permite proporcionar el mismo nombre completo a partir de dos ensamblados diferentes y no obtener un error de
empaquetado. Por lo tanto, asegúrese de que Name usa la propiedad Instrumentation en el atributo para generar un
nombre de clase o ACW legible.

El nombre de ACW debe usarse en adb el comando anterior. Para cambiar el nombre y la refactorización de la C#
clase, es RunTests necesario modificar el comando para que use el nombre de ACW correcto.
¿Por qué no se puede conectar la compilación de
versión de Android a Internet?
16/08/2019 • 2 minutes to read • Edit Online

Causa
La causa más común de este problema es que el permiso de Internet se incluye automáticamente en una
compilación de depuración, pero debe establecerse manualmente para una compilación de versión. Esto se debe a
que el permiso de Internet se usa para permitir que un depurador se asocie al proceso, tal como se describe
aquí"DebugSymbols".

Solución
Para resolver el problema, puede requerir el permiso de Internet en el manifiesto de Android. Esto puede hacerse a
través del editor de manifiestos o del SourceCode del manifiesto:
Corrección en el editor: En el proyecto de Android, vaya a propiedades-> archivo AndroidManifest.
XML -> permisos necesarios y compruebe Internet .
Corrección en SourceCode: Abra archivo AndroidManifest en un editor de código fuente y agregue la
etiqueta Permission dentro <Manifest> de las etiquetas:

<Manifest>
...
<uses-permission android:name="android.permission.INTERNET" />
</Manifest>
Paquetes NuGet más inteligentes de Xamarin
Android Support v4/v13
16/08/2019 • 5 minutes to read • Edit Online

Acerca de las bibliotecas de compatibilidad con Android


Google ha creado bibliotecas de compatibilidad para poner nuevas características a disposición de versiones
anteriores de Android. En general, las bibliotecas de compatibilidad reciben un número de versión en su nombre,
que es el nivel de API de Android más bajo, son compatibles con (por ejemplo: Support-V4 solo se puede usar en
el nivel de API 4 y versiones posteriores. Más información en este Stack Overflow debate).
Dos de las bibliotecas de soporte Support-v4 : Support-v13 y no se pueden usar juntas en la misma aplicación, es
decir, se excluyen mutuamente. Esto se debe Support-v13 a que realmente contiene todos los tipos y la
Support-v4 implementación de. Si intenta hacer referencia a ambos en el mismo proyecto, se producirán errores
de tipo duplicado.

Problemas con la referencia


Dado Support-v4 que ha llegado tan popular, muchas bibliotecas de terceros dependen ahora de ella. Podrían
haber elegido depender de support-v13 en su lugar, pero es más común depender de V4 , ya que proporciona a
todas las aplicaciones que usan estas bibliotecas de terceros la opción de admitir niveles de API hasta 4.
Si una biblioteca de terceros de Xamarin hace Xamarin.Android.Support.v4.dll referencia al Support-v4 enlace a,
cualquier aplicación que use esta biblioteca también Xamarin.Android.Support.v4.dll debe hacer referencia a. Esto
se convierte en un problema cuando la misma aplicación también quiere usar parte de la funcionalidad del
Xamarin.Android.Support.v13.dll enlace a Support-v13 . Si hace referencia a ambos enlaces, se producirán errores
de tipo duplicado.

Ensamblado de enlace V4 con reenvío de tipos


Para solucionar este problema, se ha creado un ensamblado Xamarin.Android.Support.v4.dll especial que no tiene
ninguna implementación, sino [assembly: TypeForwardedTo (..)] simplemente atributos que reenvían Support-v4
todos los tipos a la implementación Xamarin.Android.Support.v13.dll dentro del ensamblado.
Esto significa que un desarrollador puede hacer referencia a este ensamblado de tipo reenviado en su aplicación, lo
Xamarin.Android.Support.v4.dll que satisfará la referencia a las bibliotecas de Xamarin.Android.Support.v13.dll
terceros y, al mismo tiempo, permitirá que se use en la aplicación.

Asistencia de NuGet
Aunque un desarrollador podría agregar manualmente las referencias correctas necesarias, podemos usar NuGet
para ayudar a elegir el ensamblado correcto (el enlace V4 normal o el ensamblado V4 con reenvío de tipos)
cuando se instala el paquete NuGet.
Por lo tanto Xamarin.Android.Support.v4 , el paquete NuGet ahora contiene la lógica siguiente:
Si su aplicación tiene como destino el nivel de API 13 (Gingerbread 3,2) o una versión posterior:
Xamarin.Android.Support.v13NuGet se agregará automáticamente como una dependencia
Se Xamarin.Android.Support.v4.dll hará referencia al tipo reenviado en el proyecto.
Si su aplicación tiene como destino algo más bajo que el nivel de API 13, obtendrá el
Xamarin.Android.Support.v4.dll enlace normal al que se hace referencia en el proyecto.

¿Tengo que usar support-v13?


Si su aplicación tiene como destino el nivel de API 13 o superior y decide usar el Xamarin Android Support-v4
paquete Nuget, el Xamarin Android Support v13 paquete Nuget es una dependencia necesaria.
Creemos que el aumento muy poco importante en el tamaño de la aplicación (los dos archivos. jar difieren en
17kb) merece la pena la compatibilidad y se producen menos quebraderos de cabeza.
Si Adamant sobre el Support-v4 .nupkg uso de en una aplicación que tiene como destino el nivel de API 13 o
superior, siempre puede descargar manualmente, extraerlo y hacer referencia al ensamblado.
¿Cómo se puede resolver un error de
PathTooLongException?
11/07/2019 • 2 minutes to read • Edit Online

Motivo
Los nombres de ruta de acceso generada en un proyecto de Xamarin.Android pueden ser bastante largos. Por
ejemplo, durante una compilación se pudo generar una ruta de acceso similar al siguiente:
C:\algunos\Directory\solución\proyecto\obj\depurar\library_projects \
Xamarin.Forms.Platform.Android\library_project_imports\activos
En Windows (donde es la longitud máxima de una ruta de acceso 260 caracteres), un PathTooLongException
podría generarse durante la compilación del proyecto si una ruta de acceso generado supera la longitud máxima.

Solución
El UseShortFileNames propiedad de MSBuild está establecida en True para evitar este error de forma
predeterminada. Cuando esta propiedad se establece en True , el proceso de compilación usa nombres de ruta de
acceso más cortos para reducir la probabilidad de generar un PathTooLongException. Por ejemplo, cuando
UseShortFileNames está establecido en True , la ruta de acceso anterior se ha reducido a la ruta de acceso que es
similar al siguiente:
C:\algunos\Directory\solución\proyecto\obj\depurar\lp\1\jl\activos
Para establecer esta propiedad manualmente, agregue la siguiente propiedad de MSBuild para el proyecto .csproj
archivo:

<PropertyGroup>
<UseShortFileNames>True</UseShortFileNames>
</PropertyGroup>

Si se establece esta marca no se soluciona el PathTooLongException error, otro enfoque consiste en especificar
un raíz de salida intermedio común para proyectos de la solución estableciendo IntermediateOutputPath en el
proyecto .csproj archivo. Intente usar una ruta de acceso relativamente corto. Por ejemplo:

<PropertyGroup>
<IntermediateOutputPath>C:\Projects\MyApp</IntermediateOutputPath>
</PropertyGroup>

Para obtener más información sobre cómo establecer las propiedades de compilación, véase proceso de
compilación.
¿Qué versión de Xamarin.Android agrega
compatibilidad con Lollipop?
16/08/2019 • 3 minutes to read • Edit Online

NOTE
Esta guía se escribió originalmente para la versión preliminar de Android L.

Xamarin. Android 4,17 agregó compatibilidad con la versión preliminar de Android L.


Xamarin. Android 4,20 agregó compatibilidad con el círculo Android.
Xamarin solo admite activamente la versión estable actual de las herramientas de Xamarin. La información
siguiente se proporciona "tal cual" para las versiones anteriores de las herramientas. Para obtener la información
más reciente sobre las versiones de Xamarin, consulte aquí.

"Missing Android. jar para el nivel de API 21" en Android L Preview


Visual Studio
Visual Studio para Mac
Puede aparecer el siguiente mensaje de error (o similar):

Error 1 Could not find android.jar for API Level 21.

Este mensaje significa que la plataforma de Android SDK para el nivel de API 21 no está instalada. Instálelo en el
administrador de Android SDK (herramientas > abra Android SDK Manager... ) o cambie el proyecto de
Xamarin. Android para que tenga como destino una versión de API que esté instalada.
Existen algunas soluciones alternativas para este problema:
1. Cambie el proyecto para que tenga como destino la API 19 o una inferior.
2. Cambie el nombre de la carpeta Android-21 de Android-21 a Android-L. (Lo mejor es que solo se use como
una solución temporal y que no funcione muy bien).
% LOCALAPPDATA%\\Android Android: plataformas\\de SDK Android-21
3. Retroceder temporalmente al nivel de API de Android 21 "L" Preview [1]:
a. Elimine el % LOCALAPPDATA\%\Android Android-\SDK\Platforms Android-21
b. Extraer [1] en C:\usuarios\<nombre>de\usuario\AppDatalocal\AndroidAndroid\-SDK
plataformas para crear\ una carpeta de Android-L .
[1] - https://dl-ssl.google.com/android/repository/android-L_r04.zip
Android.Support.v7.AppCompat: no se encontró
ningún recurso que coincida con el nombre
especificado: attr 'android:
actionModeShareDrawable'
11/07/2019 • 2 minutes to read • Edit Online

1. Asegúrese de que descargue los extras más recientes, así como el Android 5.0 (API 21) mediante el
Administrador de SDK de Android SDK.
2. Asegúrese de que está compilando la aplicación con compileSdkVersion establece en 21. Opcionalmente,
puede establecer el targetSdkVersion 21 también.
3. Si necesita una versión anterior, como la API 19, descargue la versión correspondiente que se encuentra en
la página de Nuget:
https://www.nuget.org/packages/Xamarin.Android.Support.v7.AppCompat/
Nota: Si instala manualmente esto a través de la consola de administrador de paquetes, asegúrese de que instalar
también la misma versión de Xamarin.Android.Support.v4
https://www.nuget.org/packages/Xamarin.Android.Support.v4/
Referencia de desbordamiento de pila: https://stackoverflow.com/questions/26431676/appcompat-v721-0-0-no-
resource-found-that-matches-the-given-name-attr-andro

Vea también
¿Qué paquetes de Android SDK debo instalar?
Ajuste de los parámetros de memoria de Java para
Android Designer
16/08/2019 • 4 minutes to read • Edit Online

Los parámetros de memoria predeterminados que se usan java al iniciar el proceso de Android Designer pueden
ser incompatibles con algunas configuraciones del sistema.
A partir de Xamarin Studio 5.7.2.7 (y versiones posteriores, Visual Studio para Mac) y Visual Studio Tools para
Xamarin 3.9.344, esta configuración se puede personalizar en cada proyecto.

Nuevas propiedades de Android Designer y las opciones de Java


correspondientes
Los nombres de propiedad siguientes corresponden a la opción de línea de comandos de Java indicada
AndroidDesignerJavaRendererMinMemory -Xms
AndroidDesignerJavaRendererMaxMemory -Xmx
AndroidDesignerJavaRendererPermSize -XX:MaxPermSize
Visual Studio
Visual Studio para Mac
1. Abra su solución en Visual Studio.
2. Seleccione cada proyecto de Android uno por uno en el Explorador de soluciones y haga clic en Mostrar
todos los archivos dos veces en cada proyecto. Puede omitir proyectos que no contengan .axml ningún
archivo de diseño. Este paso garantizará que cada directorio del proyecto contenga un .csproj.user
archivo.
3. Salga de Visual Studio.
4. Busque el .csproj.user archivo de cada uno de los proyectos del paso 2.
5. Edite .csproj.user cada archivo en un editor de texto.
6. Agregue cualquiera de las nuevas propiedades de memoria de Android Designer o todas <PropertyGroup>
ellas dentro de un elemento. Puede usar un existente <PropertyGroup> o crear uno nuevo. Este es un archivo
de .csproj.user ejemplo completo que incluye los tres atributos establecidos en sus valores
predeterminados:

<?xml version="1.0" encoding="utf-8"?>


<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectView>ProjectFiles</ProjectView>
</PropertyGroup>
<PropertyGroup>
<AndroidDesignerJavaRendererMinMemory>128m</AndroidDesignerJavaRendererMinMemory>
<AndroidDesignerJavaRendererMaxMemory>750m</AndroidDesignerJavaRendererMaxMemory>
<AndroidDesignerJavaRendererPermSize>350m</AndroidDesignerJavaRendererPermSize>
</PropertyGroup>
</Project>
7. Guarde y cierre todos los archivos actualizados .csproj.user .
8. Reinicie Visual Studio y vuelva a abrir la solución.
Mi archivo Resource.designer.cs de Android no se
actualizará
13/07/2019 • 2 minutes to read • Edit Online

NOTE
Este problema se resolvió en Xamarin Studio 5.1.4 y versiones posteriores. Sin embargo, si el problema se produce en Visual
Studio para Mac, registre un nuevo error con el control de versiones completo completa y la información de salida del
registro de compilación.

Un error en la versión 5.1 Xamarin.Studio había dañado previamente archivos .csproj eliminando parcial o
totalmente el código xml en el archivo .csproj. Esto provocaría que importantes del sistema (como actualizar el
Resource.designer.cs de Android) de la compilación de partes de Android para producir un error. A partir de la
5.1.4 estable de la versión del 15 de julio de, este error se ha corregido; pero en muchos casos, el archivo de
proyecto tiene que reparar manualmente, tal como se describe a continuación.

Dos posibles enfoques para corregir el archivo de proyecto


Ya sea:
1. Crear un nuevo proyecto de aplicación de Xamarin.Android, establecer todas las propiedades del proyecto
para que coincida con el proyecto antiguo y agregar todos los recursos, archivos de código fuente, etc., de
nuevo en el proyecto.
O
2. Realizar una copia de seguridad del archivo de .csproj del proyecto original, ábralo en un editor de texto y
vuelven a agregar los elementos que faltan de un archivo .csproj generado correctamente.
Si esto no soluciona el problema
Después de experimentar con estos elementos, es posible que observe que después de volver a agregar los
elementos y volver a generar el proyecto, se actualizaría el archivo Resource.designer.cs, pero aún tendrá que
cerrar y volver a abrir la solución para obtener la finalización de código para reconocer los nuevos tipos de
contenido en Resource.designer.cs.
Resolución de errores de instalación de biblioteca
16/08/2019 • 12 minutes to read • Edit Online

En algunos casos, es posible que obtenga errores al instalar las bibliotecas de compatibilidad de Android. En esta
guía se proporcionan soluciones alternativas a algunos errores comunes.

Información general
Al compilar un proyecto de aplicación de Xamarin. Android, es posible que obtenga errores de compilación cuando
Visual Studio o Visual Studio para Mac intenten descargar e instalar las bibliotecas de dependencias. Muchos de
estos errores se deben a problemas de conectividad de red, archivos dañados o problemas de control de versiones.
En esta guía se describen los errores de instalación de la biblioteca de soporte técnico más comunes y se
proporcionan los pasos para solucionar estos problemas y volver a compilar el proyecto de la aplicación.

Errores al descargar m2Repository


Es posible que vea errores de m2repository al hacer referencia a un paquete NuGet de las bibliotecas de
compatibilidad de Android o los servicios de Google Play. El mensaje de error es similar al siguiente:

Download failed. Please download https://dl-ssl.google.com/android/repository/android_m2repository_r16.zip and


extract it to the C:\Users\mgm\AppData\Local\Xamarin\Android.Support.v4\22.2.1\content directory.

Este ejemplo es para Android_m2repository_R16, pero puede ver el mismo mensaje de error para una versión
diferente, como Android_m2repository_R18 o Android_ . m2repository_R25.
Recuperación automática de errores de m2repository
A menudo, este problema se puede solucionar eliminando la biblioteca problemática y volviendo a generar según
estos pasos:
1. Navegue al directorio de la biblioteca de soporte técnico del equipo:
En Windows, las bibliotecas de compatibilidad se encuentran en
C\:\usuarios\nombre\de_usuario_\AppData local Xamarin.
En Mac OS X, las bibliotecas de soporte se encuentran en /users/username/.local/share/Xamarin.
2. Busque la biblioteca y la carpeta de versión correspondientes al mensaje de error. Por ejemplo, la biblioteca
y la carpeta de la versión del mensaje de error anterior se encuentran en Android.\support. V4 22.2.1:

3. Elimine el contenido de la carpeta de la versión. Asegúrese de quitar el archivo . zip , así como el contenido
y los subdirectorios incrustados dentro de esta carpeta. Para el mensaje de error de ejemplo mostrado
anteriormente, se eliminarán los archivos y subdirectorios que se muestran en esta captura de pantalla
(contenido, incrustadoy android_m2repository_r16. zip):
Tenga en cuenta que es importante eliminar todo el contenido de esta carpeta. Aunque esta carpeta puede
contener inicialmente el archivo "Missing "_de_Android m2repository R16. zip , es posible que este
archivo se haya descargado o dañado parcialmente.
4. Volver a generar – el proyecto con esto hará que el proceso de compilación vuelva a descargar la biblioteca
que falta.
En la mayoría de los casos, estos pasos resolverán el error de compilación y podrán continuar. Si al eliminar esta
biblioteca no se resuelve el error de compilación, debe descargar e instalar manualmente el
archivo_Android_m2repository r_nn_. zip como se describe en la sección siguiente.
Descarga manual de m2repository
Si ha intentado usar los pasos de recuperación automática anteriores y sigue teniendo errores de compilación,
puede descargar manualmente el archivo_Android_m2repository r_nn_. zip (mediante un explorador Web) e
instalarlo de acuerdo con los pasos siguientes. . Este procedimiento también es útil si no tiene acceso a Internet en
el equipo de desarrollo, pero puede descargar el archivo con un equipo diferente.
1. Descargue el archivo_Android_m2repository r_nn_. zip que corresponde a los vínculos de – mensajes de
error que se proporcionan en la lista siguiente (junto con el hash MD5 correspondiente de la dirección URL
de cada vínculo):
android_m2repository_r33.zip – 5FB756A25962361D17BBE99C3B3FCC44
F16A3455987DBAE5783F058F19F7FCDF_de_Android m2repository R32. zip –
99A8907CE2324316E754A95E4C2D786E_de_Android m2repository R31. zip –
05AD180B8BDC7C21D6BCB94DDE7F2C8F_de_Android m2repository R30. zip –
android_m2repository_r29.zip – 2A3A8A6D6826EF6CC653030E7D695C41
17BE247580748F1EDB72E9F374AA0223_de_Android m2repository R28. zip –
C9FD4FCD69D7D12B1D9DF076B7BE4E1C_de_Android m2repository R27. zip –
android_m2repository_r26.zip – 8157FC1C311BB36420C1D8992AF54A4D
android_m2repository_r25.zip – 0B3F1796C97C707339FB13AE8507AF50
8E3C9EC713781EDFE1EFBC5974136BEA_de_Android m2repository R24. zip –
D5BB66B3640FD9B9C6362C9DB5AB0FE7_de_Android m2repository R23. zip –
96659D653BDE0FAEDB818170891F2BB0_de_Android m2repository R22. zip –
Android_m2repository_R21. zip – CD3223F2EFE068A26682B9E9C4B6FBB5
650E58DF02DB1A832386FA4A2DE46B1A_de_Android m2repository R20. zip –
android_m2repository_r19.zip – 263B062D6EFAA8AEE39E9460B8A5851A
25947AD38DCB4865ABEB61522FAFDA0E_de_Android m2repository R18. zip –
49054774F44AE5F35A6BA9D3C117EFD8_de_Android m2repository R17. zip –
0595E577D19D31708195A83087881EE6_de_Android m2repository R16. zip –
Si el archivo m2repository no se muestra en esta tabla, puede crear la dirección URL de descarga
anteponiendo https://dl-ssl.google.com/android/repository/ el nombre de la m2repository que se va
a descargar. Por ejemplo, use https://dl-
ssl.google.com/android/repository/android\_m2repository\_r10.z para descargar Android_
m2repository_ R10. zip.
2. Cambie el nombre del archivo por el hash MD5 correspondiente de la dirección URL de descarga, tal como
se muestra en la tabla anterior. Por ejemplo, si descargó Android_m2repository_R25. zip, cambie su
nombre a 0B3F1796C97C707339FB13AE8507AF50. zip. Si el hash MD5 de la dirección URL de descarga
del archivo descargado no se muestra en la tabla, puede usar un generador de MD5 en línea para convertir
la dirección URL a una cadena hash MD5.
3. Copie el archivo en la carpeta Xamarin mozip:
En Windows, esta carpeta se encuentra en C:\usuarios\nombre de\usuario\AppData\\local
Xamarinmozip.
En Mac OS X, esta carpeta se encuentra en /users/username/.local/share/Xamarin/Zips.
Por ejemplo, en la siguiente captura de pantalla se muestra el resultado cuando se descarga
Android_m2repository_R16. zip y se le cambia el nombre al hash MD5 de su dirección URL de descarga
en Windows:

Si este procedimiento no soluciona el error de compilación, debe descargar manualmente el archivo


m2repository__r_nn_. zip de Android , descomprimirlo e instalar su contenido tal y como se describe en la
sección siguiente.
Descarga e instalación manuales de archivos m2repository
El proceso totalmente manual para la recuperación de errores de m2repository supone descargar el
archivo_Android_m2repository r_nn_. zip (mediante un explorador Web), descomprimirlo y copiar su
contenido al soporte técnico. directorio de biblioteca del equipo. En el ejemplo siguiente, se recuperará de este
mensaje de error:

Unzipping failed. Please download https://dl-ssl.google.com/android/repository/android_m2repository_r25.zip


and extract it to the C:\Users\mgm\AppData\Local\Xamarin\Android.Support.v4\23.1.1\content directory.

Siga estos pasos para descargar m2repository e instalar su contenido:


1. Elimine el contenido de la carpeta de la biblioteca correspondiente al mensaje de error. Por ejemplo, en el
mensaje de error anterior, eliminaría el contenido de C\:\usuarios nombre\de\usuario\AppData local
Xamarin\Android. support. V423.1.1.0\ . Como se describió anteriormente, debe eliminar todo el
contenido de este directorio:
2. Descargue el archivo_Android_m2repository r_nn_. zip de Google que se corresponda con el mensaje
de error (vea la tabla de la sección anterior para obtener vínculos).
3. Extraiga este archivo . zip en cualquier ubicación (como el escritorio). Esto debe crear un directorio que se
corresponda con el nombre del archivo . zip . En este directorio, debe encontrar un subdirectorio
denominado m2repository:

4. En el directorio de la biblioteca con versión que purgó en el paso 1, vuelva a crear el contenido y los
subdirectorios incrustados . Por ejemplo, en la siguiente captura de pantalla se muestra el contenido y los
subdirectorios incrustados que se crean en la carpeta 23.1.1.0 para _Android m2repository_R25. zip:

5. Copie m2repository del archivo extraído . zip en el directorio de contenido que creó en el paso anterior:

6. En el directorio . zip extraído, vaya a\m2repository\com\Android\support support-V4 y abra la carpeta


correspondiente al número de versión creado anteriormente (en este ejemplo, 23.1.1):
7. Copie todos los archivos de esta carpeta en el directorio insertado creado en el paso 4:

8. Compruebe que se copian todos los archivos. El directorio incrustado debe contener ahora archivos como .
jar, . AARy . archivo POM.
9. Descomprima el contenido de los archivos . AAR extraídos en el directorio incrustado. En Windows, anexe
una extensión . zip al archivo . AAR , ábrala y copie el contenido en el directorio incrustado . En macOS,
descomprima el archivo . AAR con el comando Unzip del terminal (por ejemplo, Unzip File. AAR).
En este punto, ha instalado manualmente los componentes que faltan y el proyecto se debe compilar sin errores. Si
no es así, compruebe que ha descargado la versión del archivo m2repository . zip que se corresponde
exactamente con la versión del mensaje de error y compruebe que ha instalado su contenido en las ubicaciones
correctas, tal y como se describe en los pasos anteriores.

Resumen
En este artículo se explica cómo recuperarse de los errores comunes que pueden producirse durante la descarga e
instalación automáticas de las bibliotecas de dependencias. Se describe cómo eliminar la biblioteca problemática y
volver a compilar el proyecto como una manera de volver a descargar y volver a instalar la biblioteca. En él se
describe cómo descargar la biblioteca e instalarla en la carpeta mozip. También se describe un procedimiento más
implicado para descargar e instalar manualmente los archivos necesarios como una manera de solucionar
problemas que no se pueden resolver a través de medios automáticos.
Cambios en las Herramientas de Android SDK
16/08/2019 • 4 minutes to read • Edit Online

Cambios en el modo en que el Android SDK administra los niveles de API instalados y AVD.

Cambios en las herramientas de Android SDK


En las versiones recientes del SDK Tools para Android, Google ha quitado los administradores de AVD y SDK
existentes en favor de las nuevas herramientas de la CLI (interfaz de línea de comandos). Se ha quitado el
programa Android y los administradores de la GUI de Google (interfaz gráfica de usuario) de Visual Studio para
Mac y las versiones anteriores de Visual Studio Tools para Xamarin ya no funcionarán después de la versión
25.2.5 de Android SDK Tools. Por ejemplo, si se intenta usar el programa Android a través de la línea de
comandos, se producirá un mensaje de error similar al siguiente:

The "android" command is deprecated.


For manual SDK, AVD, and project management, please use Android Studio.
For command-line tools, use tools\bin\sdkmanager.bat
and tools\bin\avdmanager.bat

En las secciones siguientes se explica cómo administrar los dispositivos virtuales de Android SDK y Android con
Android SDK 25.3.0 y versiones posteriores.
Herramientas de interfaz de usuario
Visual Studio y Visual Studio para Mac ahora proporcionan reemplazos de Xamarin para los administradores
basados en la GUI de Google que no se han suspendido:
Para descargar Android SDK herramientas, plataformas y otros componentes necesarios para desarrollar
aplicaciones de Xamarin. Android, use el administrador de Android SDK de Xamarin en lugar del
administrador de SDK de Google heredado.
Para crear y configurar dispositivos virtuales Android, use el Android Device Manager en lugar del
administrador de emuladores de Google heredado.
Estas herramientas son funcionalmente equivalentes a los administradores basados en la GUI de Google que
reemplazan.
Herramientas de la CLI
Como alternativa, puede usar las herramientas de la CLI para administrar y actualizar los emuladores y Android
SDK. Los siguientes programas componen ahora la interfaz de la línea de comandos para las herramientas de
Android SDK:
sdkmanager
Agregado en: Android SDK Tools 25.2.3 (noviembre de 2016) y versiones posteriores.
Hay un nuevo programa denominado sdkmanager en la carpeta Tools/bin de la Android SDK. Esta herramienta
se utiliza para mantener el Android SDK en la línea de comandos. Para obtener más información sobre el uso de
esta herramienta, vea sdkmanager.
avdmanager
Agregado en: Android SDK Tools 25.3.0 (marzo de 2017) y versiones posteriores.
Hay un nuevo programa denominado avdmanager en la carpeta Tools/bin de la Android SDK. Esta herramienta
se usa para mantener el AVD para el Android Emulator. Para obtener más información sobre el uso de esta
herramienta, vea avdmanager.
Degradar
Puede cambiar la versión de Android SDK Tools instalando una versión anterior del Android SDK desde el sitio
web para desarrolladores de Android.
Uso de la GUI anterior
Todavía puede usar la interfaz gráfica de usuario original ejecutando el programa Android dentro de la carpeta de
herramientas , siempre que esté en Android SDK Tools versión 25.2.5 o inferior.

Vínculos relacionados
Configuración de Android SDK
Android Device Manager
Descripción de los niveles de API de Android
Notas de la versión de SDK Tools (Google)
sdkmanager
avdmanager
Matriz de errores de Xamarin.Android
11/07/2019 • 15 minutes to read • Edit Online

Referencia de errores
Este documento proporciona cierta información sobre los distintos códigos de error de Xamarin.

CATEGORÍA DESCRIPCIÓN

XA0xxx Errores de mandroid

XA1xxx Copiar el archivo o los vínculos simbólicos (proyecto


relacionado) errores

XA2xxx Errores del vinculador

XA3xxx Errores AOT

XA4xxx Errores de generación de código

XA5xxx Errores de la cadena de herramientas y GCC

XA6xxx errores de herramientas internas de mandroid

XA7xxx Reservada

XA8xxx Reservada

XA9xxx Errores de licencia

Códigos de error
XA0xxx Errors
CÓDIGO DE ERROR DESCRIPCIÓN

XA0000 Error inesperado: rellene una informe de errores.

XA0001 '-nombredisp proporcionó sin ninguna acción específica del


dispositivo.

XA0002 No se pudo analizar la variable de entorno '{0}'.

XA0003 Nombre de la aplicación '{0}.exe' entra en conflicto con un


nombre de ensamblado (.dll) de producto o SDK.

XA0004 Nueva lógica de refcounting requiere sgen habilitarse


demasiado.

XA0005 El directorio de salida '{0}' no existe.


CÓDIGO DE ERROR DESCRIPCIÓN

XA0006 No hay ninguna plataforma de desarrollo en '{0}', utilice--


plataforma = PLAT para especificar el SDK

XA0007 El ensamblado raíz '{0}' no existe.

XA0008 Debe proporcionar solo un ensamblado de raíz.

XA0009 Error al cargar los ensamblados: {0}.

XA0010 No se pudo analizar los argumentos de línea de comandos:


{0}.

XA0011 {0} se compiló un tiempo de ejecución más reciente ({1}) que


admite MonoTouch.

XA0012 Datos incompletos se proporcionan para completar '{0}'.

XA0013 Compatibilidad de generación de perfiles requiere sgen


habilitarse demasiado.

XA0014 iOS {0} no admite la creación de aplicaciones destinadas a


ARMv6.

XA0020 No se pudo determinar la ruta de acceso de mandroid.

XA0100 EmbeddedNativeLibrary '{0}' no es válido en el proyecto de


aplicación de Android. Use AndroidNativeLibrary en su lugar.

XA1xxx Errors
CÓDIGO DE ERROR DESCRIPCIÓN

XA1001 No se pudo encontrar una aplicación en el directorio


especificado.

XA1002 No se pudo crear vínculos simbólicos, se copiaron los archivos.

XA1003 No se pudo terminar la aplicación '{0}'. Es posible que deba


eliminar manualmente la aplicación.

XA1004 No se pudo obtener la lista de aplicaciones instaladas.

XA1005 No se pudo terminar la aplicación '{0}'en el dispositivo'{1}': {2}.


Es posible que deba eliminar manualmente la aplicación.

XA1006 No se pudo instalar la aplicación '{0}'en el dispositivo'{1}': {2}.

XA1007 No se pudo iniciar la aplicación '{0}'en el dispositivo'{1}': {2}.


Todavía puede iniciar manualmente la aplicación pulsando en
él.

XA1008 No se pudo iniciar el simulador: {0}.


CÓDIGO DE ERROR DESCRIPCIÓN

XA1009 No se pudo copiar el ensamblado '{0}'para'{1}': {2}.

XA1010 No se pudo cargar el ensamblado '{0}': {1}.

XA1011 No se pudo agregar el archivo de recursos que faltan: '{0}'.

XA1101 No se pudo iniciar la aplicación.

XA1102 No se pudo conectar con la aplicación (terminará): {0}.

XA1103 No se pudo desasociar.

XA1104 No se pudo enviar el paquete: {0}.

XA1105 Tipo de respuesta inesperado.

XA1106 No se pudo obtener la lista de aplicaciones en el dispositivo:


Tiempo de espera agotado para esta solicitud.

XA1107 No se pudo iniciar la aplicación.

XA1201 No se pudo cargar el simulador: {0}.

XA1301 Biblioteca nativa '{0}' ({1}) se omite porque no coincide con la


actual architecture(s) de compilación ({2}).

XA2xxx Errors
CÓDIGO DE ERROR DESCRIPCIÓN

XA2001 No se pudo vincular ensamblados.

XA2002 No se puede resolver la referencia: {0}.

XA2003 Opción '{0}' se omitirá porque se deshabilita la vinculación.

XA2004 Archivo de definiciones de enlazador adicionales '{0}' no se


pudo encontrar.

XA2005 Las definiciones de '{0}' no se pudo analizar.

XA2006 Referencia al elemento de metadatos '{0}' (definido en '{1}') de


'{2}' no se pudo resolver.

XA3xxx Errors
Estos son errores AOT.

CÓDIGO DE ERROR DESCRIPCIÓN

XA3001 Podría no AOT el ensamblado '{0}'.


CÓDIGO DE ERROR DESCRIPCIÓN

XA3002 Restricción de AOT: Método '{0}' debe ser estático, ya que está
decorado con [MonoPInvokeCallback].

XA3003 En conflicto: opciones de depuración y--llvm. Depurar con Soft


está deshabilitada.

XA4xxx Errors
Estos son errores de generación de código.

CÓDIGO DE ERROR DESCRIPCIÓN

XA4001 No se pudo expansed a la plantilla principal '{0}'.

XA4101 El registrador no puede generar una firma para el tipo '{0}'.

XA4102 El registrador encuentra un tipo no válido '{0}'en la firma de


método'{2}'. Use '{1}' en su lugar.

XA4103 El registrador encuentra un tipo no válido '{0}'en la firma de


método'{2}': El tipo implementa INativeObject, pero no tiene
un constructor que toma dos (IntPtr, bool) argumentos.

XA4104 El registrador no puede serializar el valor devuelto de tipo


'{0}'en la firma de método'{1}'.

XA4105 El registrador no puede serializar el parámetro de tipo '{0}'en


la firma de método'{1}'.

XA4106 El registrador no puede serializar el valor devuelto para la


estructura '{0}'en la firma de método'{1}'.

XA4107 El registrador no puede serializar el parámetro de tipo '{0}'en


la firma de método'{1}'.

XA4108 El registrador no puede obtener el tipo ObjectiveC de tipo


administrado '{0}'.

XA4109 No se pudo compilar el código generado del registrador.


Registre un informe de errores.

XA4110 El registrador no puede serializar el parámetro de salida de


tipo '{0}'en la firma de método'{1}'.

XA4111 El registrador no puede generar una firma para el tipo '{0}'en


el método'{1}'.

XA4200 Solo se pueden generar de ACW para los tipos 'claas'.

XA4201 No se puede determinar el nombre JNI de tipo {0}.

XA4203 El nombre del tipo especificado debe ser completo.


CÓDIGO DE ERROR DESCRIPCIÓN

XA4204 No se puede resolver el tipo de interfaz '{0}'. ¿Falta una


referencia de ensamblado?

XA4205 [ExportField] solo puede usarse en métodos con 0 parámetros.

XA4206 [Exportar] no se puede usar en un tipo genérico.

XA4207 [ExportField] no se puede usar en un tipo genérico.

XA4208 [Java.Interop.ExportFieldAttribute] no se puede usar en un


método que devuelve void.

XA4209 No se pudo crear JavaTypeInfo para la clase: {0} debido a {1}.

XA4210 Deberá agregar una referencia a Mono.Android.Export.dll al


usar ExportAttribute o ExportFieldAttribute.

XA4211 AndroidManifest.xml //uses-sdk/@android:targetSdkVersion


'{0}'es menor que $(TargetFrameworkVersion)'{1}'. El uso de
API -{1} para la compilación ACW.

XA5xxx Errors
CÓDIGO DE ERROR DESCRIPCIÓN

XA5101 Falta '{0}' compilador. Instale el NDK de Android.

XA5102 Error de conversión de ensamblados en código nativo.


Registre un informe de errores.

XA5103 No se pudo compilar el archivo '{0}'. Registre un informe de


errores.

XA5201 No se pudo vincular nativo. Revise las marcas de usuario


proporcionadas para gcc: {0}

XA5202 No se pudo vincular nativo. Revise el registro de compilación.

XA5303 Nativo vinculación advertencia: {0}.

XA5300 SDK de Android no se encuentra o no totalmente instalado.

XA5301 Herramienta 'Quitar' que falta. Instale Xcode componente


"Herramientas de línea de comandos".

XA5302 Herramienta de 'dsymutil' que falta. Instale Xcode


componente "Herramientas de línea de comandos".

XA5203 No se pudo generar los símbolos de depuración (directorio de


dSYM). Revise el registro de compilación.

XA5204 No se pudo eliminar el archivo binario final. Revise el registro


de compilación.
CÓDIGO DE ERROR DESCRIPCIÓN

XA5205 Herramienta de 'aapt' que falta. Instale el paquete de


herramientas de compilación de Android SDK.

XA5206 {0}. Directorio de recursos Android {1} no existe.

XA5207 {0}. Archivo de biblioteca de Java {1} no existe.

XA5208 Error de descarga. Descargue {0} y colóquelo la {1} directory.

XA5209 No se pudo descomprimir. Descargue {0} y extráigalo a la {1}


directory.

XA5210 {0}. Archivo de biblioteca nativa {1} no existe.

XA6xxx Errors
CÓDIGO DE ERROR DESCRIPCIÓN

XA6001 Versión en ejecución de Cecil no admite la eliminación del


ensamblado.

XA6002 No se pudo quitar el ensamblado '{0}'.

XA6003 UnauthorizedAccessException mensaje.

XA9xxx Errors
Estos códigos de error son errores de activación y licencias.
XA9000
Causa: Licencia ha expirado
Se comprueban durante: Compilar

STARTER INDIE BUSINESS(TRIAL) TRABAJO EMPRESA

WARNING WARNING WARNING WARNING WARNING

XA9001
Causa: Versión de evaluación ha expirado
Se comprueban durante: Compilar

STARTER INDIE BUSINESS(TRIAL) TRABAJO EMPRESA

WARNING WARNING WARNING WARNING WARNING

XA9002
Causa: AndroidJavaSource
Se comprueban durante: Compilar
STARTER INDIE BUSINESS(TRIAL) TRABAJO EMPRESA

ERROR Aceptar Aceptar Aceptar Aceptar

Causa: AndroidJavaLibrary
Se comprueban durante: Compilar

STARTER INDIE BUSINESS(TRIAL) TRABAJO EMPRESA

ERROR Aceptar Aceptar Aceptar Aceptar

Si un ensamblado de enlace tiene el .jar incrustado, esto se detecta en el momento de paquete, no en


tiempo de compilación.
Causa: AndroidNativeLibrary
Se comprueban durante: Compilar

STARTER INDIE BUSINESS(TRIAL) TRABAJO EMPRESA

ERROR Aceptar Aceptar Aceptar Aceptar

XA9003
Causa: System.Runtime.Serialization
Se comprueban durante: Paquete

STARTER INDIE BUSINESS(TRIAL) TRABAJO EMPRESA

ERROR ERROR Aceptar Aceptar Aceptar

Causa: System.ServiceModel.Web
Se comprueban durante: Paquete

STARTER INDIE BUSINESS(TRIAL) TRABAJO EMPRESA

ERROR ERROR Aceptar Aceptar Aceptar

Causa: Mono.Data.Tds
Se comprueban durante: Compilar

STARTER INDIE BUSINESS(TRIAL) TRABAJO EMPRESA

ERROR ERROR Aceptar Aceptar Aceptar

Esto se hace referencia a System.Data.dll, que está permitido


Causa: Mono.Android.Export
Se comprueban durante: Compilar
STARTER INDIE BUSINESS(TRIAL) TRABAJO EMPRESA

ERROR Aceptar Aceptar Aceptar Aceptar

XA9004
Causa: : generación de perfiles
Se comprueban durante: Paquete

STARTER INDIE BUSINESS(TRIAL) TRABAJO EMPRESA

ERROR ERROR Aceptar Aceptar Aceptar

XA9005
Causa: Límite de tamaño (32kb).
Se comprueban durante: Paquete

STARTER INDIE BUSINESS(TRIAL) TRABAJO EMPRESA

ERROR Aceptar - - -

XA9006
Causa: Espacio de nombres System.Data.SqlClient.
Se comprueban durante: Paquete

STARTER INDIE BUSINESS(TRIAL) TRABAJO EMPRESA

ERROR ERROR Aceptar Aceptar Aceptar

XA9008
Causa: Compilación desde la línea de comandos.
Se comprueban durante: Compilar

STARTER INDIE BUSINESS(TRIAL) TRABAJO EMPRESA

ERROR ERROR Aceptar Aceptar Aceptar

XA9009
Causa: Número de serie que faltan.
Se comprueban durante: Un-testable

STARTER INDIE BUSINESS(TRIAL) TRABAJO EMPRESA

ERROR ERROR ERROR ERROR ERROR

XA9010
Causa: ProductId no válido.
Se comprueban durante: Compilar
STARTER INDIE BUSINESS(TRIAL) TRABAJO EMPRESA

ERROR ERROR ERROR ERROR ERROR

Equivalente a XA9018.
XA9011
Causa: No se pudo actualizar el archivo de licencia (para el nuevo formato de archivo).
Se comprueban durante: Activación

STARTER INDIE BUSINESS(TRIAL) TRABAJO EMPRESA

ERROR ERROR ERROR ERROR ERROR

XA9012
Causa: Sin internet
Se comprueban durante: Activación

STARTER INDIE BUSINESS(TRIAL) TRABAJO EMPRESA

ERROR ERROR ERROR ERROR ERROR

XA9013
Causa: Error desconocido
Se comprueban durante: Activación

STARTER INDIE BUSINESS(TRIAL) TRABAJO EMPRESA

ERROR ERROR ERROR ERROR ERROR

XA9014
Causa: Código de activación no válido
Se comprueban durante: Activación

STARTER INDIE BUSINESS(TRIAL) TRABAJO EMPRESA

ERROR ERROR ERROR ERROR ERROR

XA9017
Causa: Servidor de activación no devuelve una licencia válida.
Se comprueban durante: Activación

STARTER INDIE BUSINESS(TRIAL) TRABAJO EMPRESA

ERROR ERROR ERROR ERROR ERROR

XA9018
Causa: Licencia no válida
Se comprueban durante: Compilar
STARTER INDIE BUSINESS(TRIAL) TRABAJO EMPRESA

- - ERROR - -
Android Wear
31/07/2019 • 5 minutes to read • Edit Online

El desgaste de Android es una versión de Android que está diseñada para dispositivos portátil, como las
inspecciones inteligentes. En esta sección se incluyen instrucciones sobre cómo instalar y configurar las
herramientas necesarias para el desarrollo de desgaste, un tutorial paso a paso para crear su primer dispositivo de
desgaste y una lista de ejemplos a los que puede hacer referencia para crear sus propias aplicaciones de desgaste.

Introducción
Presenta el desgaste de Android, describe cómo instalar y configurar el equipo para el desarrollo de desgaste y
proporciona pasos para ayudarle a crear y ejecutar su primera aplicación de desgaste de Android en un emulador o
dispositivo de desgaste.

Interfaz de usuario
Explica los controles específicos del desgaste de Android y proporciona vínculos a ejemplos que muestran cómo
usar estos controles.

Características de la plataforma
Los documentos de esta sección cubren características específicas del desgaste de Android. Aquí encontrará un
tema en el que se describe cómo crear un WatchFace.

Tamaños de pantalla
Obtenga una vista previa y optimice la interfaz de usuario para los tamaños de pantalla disponibles.

Implementación y pruebas
Explica cómo implementar la aplicación de desgaste de Android en un dispositivo de desgaste de Android o en un
emulador de Android configurado para el desgaste. También incluye sugerencias de depuración e información
sobre cómo configurar una conexión Bluetooth entre el equipo de desarrollo y un dispositivo Android.

Desgaste de las API


El sitio para desarrolladores de Android proporciona información detallada sobre las API de desgaste de claves,
como la actividad de portátil, los intentos, la autenticación, las complicaciones, la representación de complicaciones,
las notificaciones, Vistasy WatchFace.

Ejemplos
Puede encontrar una serie de ejemplos con el desgaste de Android (o ir directamente a GitHub).

MUESTRA DESCRIPCIÓN CAPTURA DE PANTALLA


MUESTRA DESCRIPCIÓN CAPTURA DE PANTALLA

SkeletonWear Un ejemplo sencillo de los aspectos


básicos de los proyectos de portátil,
incluidas las notificaciones de
GridViewPager y interactivas.

WatchViewStub Demostración sencilla del control


WatchViewStub que detecta la forma de
pantalla y carga automáticamente el
diseño correcto. Vea cómo funciona
WatchViewStub en el diseño Resources
/layout/main_activity. XML .

RecipeAssistant Demostración de las páginas de


notificación de desgaste, en forma de
pasos de recetas. Las notificaciones se
crean en RecipeService.cs.

ElizaChat Ejemplo divertido de interactuar con un


"asistente personal" denominado Eliza,
mediante el uso de notificaciones
interactivas para crear una conversación
mediante respuestas preparadas.

GridViewPager GridViewPager implementa el modelo


de navegación 2D, donde el usuario se
desliza verticalmente y, a continuación,
horizontalmente para navegar por las
opciones y el contenido.

WatchFace WatchFace es una esfera de inspección


personalizada con una hora, un minuto
y dos manos de estilo analógico. En este
ejemplo se muestra cómo crear un
servicio de reloj de inspección que
dibuja la hora actual y controla los
eventos de cambio de visibilidad y el
modo ambiente. Incluye un receptor de
difusión que escucha los cambios de
zona horaria y actualiza
automáticamente la hora según
corresponda.

Vídeos
Consulte estos vínculos de vídeo que describen Xamarin. Android con soporte técnico de uso:

DESCRIPCIÓN CAPTURA DE PANTALLA

Android L y mucho más – La versión preliminar para


desarrolladores de Android L presentó una gran cantidad de
nuevas API para que los desarrolladores aprovechen las
ventajas de, incluido el diseño de materiales, las notificaciones
y las nuevas animaciones, por nombrar algunas.

C#está en mis oídos y en mis ojos: El uso de – portátil de


Google Glass y Android podría parecer algo en el futuro (o un
episodio de gadget de inspector), pero muchas personas ya
están adoptando el futuro hoy mismo. C#los desarrolladores
saben esto y ya tienen las herramientas y los conocimientos
necesarios para aprovechar la eficacia de los dispositivos
portátil (desde el desarrollo de 2014).

Novedades de Xamarin. Android – Android L, desgaste de


Android, Android TV, Android auto, diseño de material y arte;
¿qué significa esto para usted como desarrollador de
Xamarin?, desde evolucione 2014.
Introducción a Android Wear
11/07/2019 • 2 minutes to read • Edit Online

Las guías de esta sección presentan Android Wear, describen cómo instalar y configurar el equipo para el
desarrollo de desgaste y proporcionan los pasos para ayudarle a crear y ejecutar su primera aplicación Android
Wear.

Introducción a Wear
Proporciona una introducción básica a Android Wear, describe sus características principales, se enumeran
algunos de los dispositivos Android Wear más populares y proporciona vínculos a documentación de Google
Android Wear esencial para obtener más información.

Configuración e instalación
Le guía por los pasos de instalación y los detalles de configuración necesarios para preparar el equipo y los
dispositivos para el desarrollo de Android Wear.

Hola, Wear
Este tutorial proporciona instrucciones paso a paso para crear un pequeño proyecto de Android Wear que
administra los clics de botón y muestra un contador haga clic en el dispositivo de desgaste.
Introducción a Android Wear
16/08/2019 • 18 minutes to read • Edit Online

Con la introducción del desgaste de Android de Google, ya no está restringido a los teléfonos y las tabletas cuando
se trata de desarrollar excelentes aplicaciones Android. La compatibilidad de Xamarin. Android con el desgaste de
Android permite ejecutar C# código en su muñeca. Esta introducción proporciona información general básica
sobre el desgaste de Android, describe sus características clave y ofrece información general sobre las
características disponibles en el desgaste de Android 2,0. En él se enumeran algunos de los dispositivos de desgaste
de Android más populares y se proporcionan vínculos a la documentación esencial sobre el desgaste de Android
de Google para su posterior lectura.

Información general
El desgaste de Android se ejecuta en una variedad de dispositivos, entre los que se incluyen la primera generación
de Motorola 360, la inspección G de LG y la marcha de Samsung en vivo. También se ha lanzado una segunda
generación, que incluye el SmartWatch 3 de Sony, con capacidades adicionales, como la reproducción de música
sin conexión y GPS integrada. Para el desgaste de Android 2,0, Google se ha agrupado con LG para dos nuevos
relojes: el deporte de inspección de LG y el estilo de inspección de LG.

Xamarin. Android 5,0 y versiones posteriores admiten el desgaste de Android a través de la compatibilidad con
Android 4.4 W (API 20) y un paquete de NuGet que agrega controles de interfaz de usuario específicos para el
desgaste adicional. Xamarin. Android 5,0 y versiones posteriores también incluyen funcionalidad para empaquetar
las aplicaciones de desgaste. Los paquetes NuGet también están disponibles para el desgaste de Android 2,0 como
se describe más adelante en esta guía.

Conceptos básicos sobre el desgaste de Android


El desgaste de Android tiene un paradigma de interfaz de usuario que difiere del de las aplicaciones de bolsillo de
Android. La primera ola de aplicaciones de desgaste se diseñó para extender una aplicación de mano
complementaria de algún modo, pero a partir del desgaste de Android 2,0, las aplicaciones de desgaste se pueden
usar de forma independiente. Cuando se implementa una aplicación de desgaste, se empaqueta con una aplicación
de mano complementaria. Dado que la mayoría de las aplicaciones de desgaste dependen de una aplicación
complementaria de mano, necesitan alguna manera de comunicarse con aplicaciones de mano. En las secciones
siguientes se describen estos escenarios de uso y se describen las características esenciales del desgaste de
Android.
Escenarios de uso
La primera versión del desgaste de Android se centró principalmente en la extensión de aplicaciones de mano
actuales con notificaciones mejoradas y la sincronización de datos entre la aplicación de mano y la aplicación
portátil. Por lo tanto, estos escenarios son relativamente sencillos de implementar.
Notificaciones de portátil
La manera más sencilla de admitir el desgaste de Android es aprovechar la naturaleza compartida de las
notificaciones entre el dispositivo de mano y el dispositivo portátil. Mediante el uso de la API de notificación de
WearableExtender support V4 y la clase (disponible en la biblioteca de compatibilidad de Android de Xamarin),
puede aprovechar las características nativas de la plataforma, como las tarjetas de estilo de bandeja de entrada o la
entrada de voz. El ejemplo RecipeAssistant proporciona código de ejemplo que muestra cómo enviar una lista de
notificaciones a un dispositivo de desgaste de Android.
Aplicaciones complementarias
Otra estrategia consiste en crear una aplicación completa que se ejecute de forma nativa en el dispositivo portátil y
pares con una aplicación de mano complementaria. Un buen ejemplo de este enfoque es la aplicación de ejemplo
de cuestionario , que muestra cómo crear una prueba que se ejecuta en un dispositivo de mano y realiza preguntas
de prueba en el dispositivo portátil.
Interfaz de usuario
El patrón de navegación principal para el desgaste es una serie de tarjetas organizadas verticalmente. Cada una de
estas tarjetas puede tener acciones asociadas que se superponen en la misma fila. La GridViewPager clase
proporciona esta funcionalidad; se adhiere al mismo concepto de adaptador ListView que. Normalmente, se
asocia GridViewPager con un FragmentGridPagerAdaptor (o GridPagerAdaptor ) que permite Fragment representar
cada celda de fila y columna como:

El desgaste también hace uso de botones de acción que se componen de un círculo de color grande con un
pequeño texto de Descripción debajo (como se muestra arriba). En el ejemplo GridViewPager se muestra cómo
GridViewPager usar GridPagerAdapter y en una aplicación de desgaste.

El desgaste de Android 2,0 agrega un cajón de navegación, un cajón de acciones y botones de acción insertados a
la interfaz de usuario de desgaste. Para más información sobre los elementos de la interfaz de usuario de 2,0 de
Android, consulte el tema sobre la anatomía de Android.
Comunicaciones
El desgaste de Android proporciona dos API de comunicación diferentes para facilitar la comunicación entre las
aplicaciones de portátil y las aplicaciones de mano complementarias:
API de datos – Esta API es similar a un almacén de datos sincronizado entre el dispositivo portátil y el dispositivo
de mano. Android se encarga de propagar los cambios entre portátil y el dispositivo de mano cuando es óptimo
hacerlo. Cuando el portátil está fuera del intervalo, pone en cola la sincronización para más adelante. El punto de
entrada principal para esta API WearableClass.DataApi es. Para obtener más información acerca de esta API, vea el
tema Android Syncing Data items .
API de mensajes – Esta API permite usar una ruta de comunicación de nivel inferior: una carga pequeña se envía
de forma unidireccional sin sincronización entre las aplicaciones de mano y portátil. El punto de entrada principal
para esta API WearableClass.MessageApi es. Para obtener más información acerca de esta API, consulte el tema
envío y recepción de mensajes de Android.
Puede optar por registrar devoluciones de llamada para recibir esos mensajes a través de cada una de las
interfaces del agente de escucha de API o, como alternativa, implementar WearableListenerService un servicio en
la aplicación que se derive de. Se crearán instancias de este servicio automáticamente con el desgaste de Android.
En el ejemplo FindMyPhone se muestra cómo implementar un WearableListenerService .
Implementación
Cada aplicación portátil se implementa con su propio archivo APK insertado en la aplicación principal APK. Este
empaquetado se administra automáticamente en Xamarin. Android 5,0 y versiones posteriores, pero debe
realizarse manualmente para las versiones de Xamarin. Android anteriores a la versión 5,0. Trabajar con el
empaquetado explica la implementación con más detalle.

Ampliar conocimientos
La mejor manera de familiarizarse con el desgaste de Android consiste en compilar y probar la primera aplicación.
La lista siguiente proporciona un orden de lectura recomendado para ayudarle a ponerse al día rápidamente:
1. Instalación & instalación proporciona instrucciones detalladas para instalar y configurar el entorno de
desarrollo para compilar aplicaciones de desgaste de Xamarin. Android.
2. Una vez que haya instalado los paquetes necesarios y haya configurado un emulador o un dispositivo,
consulte Hola, desgaste de las instrucciones paso a paso que explican cómo crear un pequeño proyecto de
desgaste de Android que controla los clics de los botones y muestra un contador de clic en el desgaste.
dispositivos.
3. Las pruebas de & de implementación proporcionan información más detallada sobre la configuración e
implementación en emuladores y dispositivos, incluidas instrucciones sobre cómo implementar la aplicación
en un dispositivo de desgaste a través de Bluetooth.
4. Trabajar con tamaños de pantalla explica cómo obtener una vista previa y optimizar la interfaz de usuario
para los distintos tamaños de pantalla disponibles en los dispositivos de desgaste.
5. Trabajar con el empaquetado describe los pasos para empaquetar aplicaciones de desgaste de forma
manual para su distribución en Google Play.
Una vez que haya creado su primera aplicación de desgaste, puede intentar crear una superficie de inspección
personalizada para el desgaste de Android. La creación de una esfera de inspección proporciona instrucciones
paso a paso y código de ejemplo para desarrollar un servicio de caras de supervisión digital de bajada, seguido de
más código que lo mejora en una superficie de inspección de estilo analógico con características adicionales.

Desgaste de Android 2,0


El desgaste de Android 2,0 presenta una variedad de nuevas características y funcionalidades, como
complicaciones, diseños curvos, dibujados de navegación y acciones, y notificaciones ampliadas. Además, el
desgaste de 2,0 permite crear aplicaciones independientes que funcionen de forma independiente de las
aplicaciones de mano. La nueva funcionalidad de gestos de muñecas permite interacciones de una sola mano con
la aplicación. En las secciones siguientes se resaltan estas características y se proporcionan vínculos para ayudarle
a empezar a usarlas en la aplicación.
Instalación de desgaste de paquetes 2,0
Para compilar una aplicación de desgaste de 2,0 con Xamarin. Android, debe agregar el paquete Xamarin.
Android. desgaste v 2.0 al proyecto (haga clic en la pestaña examinar):

Este paquete de NuGet contiene enlaces para las bibliotecas de compatibilidad de Android portátil y desgaste.
Además de Xamarin. Android. desgaste, se recomienda instalar el NuGet Xamarin. GooglePlayServices.
portátil :

Características clave del desgaste 2,0


El desgaste de Android 2,0 es la actualización más importante para el desgaste de Android desde su lanzamiento
inicial en 2014. En las secciones siguientes se resaltan las características clave del desgaste de Android 2,0 y se
proporcionan vínculos para ayudarle a empezar a usar estas nuevas características en la aplicación.
Complicaciones
Las complicaciones son widgets de reloj pequeños que se pueden ver de un vistazo sin tener que deslizarse por el
reloj. Las complicaciones son similares a los widgets del panel de estilo de escritorio; muestran información como
el tiempo, la duración de la batería, los eventos de calendario y las estadísticas de la aplicación de idoneidad:

Para obtener más información sobre las complicaciones, vea el tema sobre las complicaciones de las caras de la
observación de Android.
Navegación y dibujados de acciones
Dos nuevos alimentadores se incluyen en el desgaste de 2,0. El cajón de navegación, que aparece en la parte
superior de la pantalla, permite a los usuarios navegar entre las vistas de la aplicación (como se muestra a
continuación). El cajón de acciones, que aparece en la parte inferior de la pantalla (como se muestra a la derecha),
permite a los usuarios elegir en una lista de acciones.

Para obtener más información sobre estos dos nuevos interactivos interactivos, consulte el tema navegación y
acciones de desgaste de Android.
Diseños curvos
Desgaste 2,0 presenta nuevas características para mostrar diseños curvos en dispositivos de desgaste de ida y
vuelta. En concreto, la WearableRecyclerView nueva clase está optimizada para mostrar una lista de elementos
verticales en pantallas redondas:

WearableRecyclerView extiende la RecyclerView clase para admitir diseños curvos y gestos de desplazamiento
circular. Para obtener más información, consulte la documentación de la API de Android WearableRecyclerView .
Aplicaciones independientes
Las aplicaciones de desgaste de Android 2,0 pueden funcionar independientemente de las aplicaciones de mano.
Esto significa que, por ejemplo, una inspección inteligente puede seguir ofreciendo funcionalidad completa aunque
el dispositivo de mano complementario esté apagado o lejos del dispositivo portátil. Para obtener más información
sobre esta característica, consulte el tema aplicaciones independientes de Android.
Gestos de muñecas
Los gestos de muñecas permiten a los usuarios interactuar con la aplicación sin usar la pantalla – táctil los usuarios
pueden responder a la aplicación con una sola mano. Se admiten dos gestos de muñecas:
Desplazarse hacia afuera
Gesto de muñeca en
Para obtener más información, consulte el tema sobre gestos de muñecas de Android.
Hay muchas más características de desgaste 2,0, como acciones insertadas, respuesta inteligente, entrada remota,
notificaciones expandidas y un nuevo modo de puente para las notificaciones. Para obtener más información sobre
las nuevas características de desgaste 2,0, consulte la Introducción a la APIde Android.

Dispositivos
Estos son algunos ejemplos de los dispositivos que pueden ejecutar el desgaste de Android:
Motorola 360
Reloj de LG G
Inspección R de LG G
Samsung Gear Live
Sony SmartWatch 3
ASUS ZenWatch

Información adicional
Consulte la documentación sobre el desgaste de Android de Google:
Acerca del desgaste de Android
Diseño de aplicaciones de desgaste de Android
Biblioteca Android. support. portátil
Desgaste de Android 2,0

Resumen
Esta introducción proporciona información general sobre el desgaste de Android. Se describen las características
básicas del desgaste de Android y se incluye información general sobre las características introducidas en el
desgaste de Android 2,0. Proporciona vínculos a la lectura básica para ayudar a los desarrolladores a empezar a
trabajar con el desarrollo de uso de Xamarin. Android y a mostrar ejemplos de algunos de los dispositivos de
desgaste de Android actualmente en el mercado.

Vínculos relacionados
Instalación y configuración
Introducción
Configuración e instalación
16/08/2019 • 5 minutes to read • Edit Online

Este artículo le guía a través de los pasos de instalación y los detalles de configuración necesarios para preparar
el equipo y los dispositivos para el desarrollo del desgaste de Android. Al final de este artículo, tendrá una
instalación operativa de Xamarin. Android desgaste integrada en Visual Studio para Mac o Microsoft Visual
Studio y estará listo para empezar a crear su primera aplicación de trabajo de Xamarin. Android.

Requisitos
Lo siguiente es necesario para crear aplicaciones de desgaste de Android basadas en Xamarin:
Visual Studio o Visual Studio para Mac – Se requiere Visual Studio 2017 Community o posterior.
Xamarin. Android – Xamarin. Android 4,17 o posterior debe estar instalado y configurado con Visual
Studio o Visual Studio para Mac.
Android SDK -Android SDK 5.0.1 (API 21) o posterior debe instalarse a través del administrador de
Android SDK.
Kit para desarrolladores de Java El desarrollo de Xamarin Android requiere JDK 1,8 si está
desarrollando para el nivel de API 24 o superior (JDK 1,8 también es compatible con los niveles de API
anteriores a 24). –
Puede seguir usando JDK 1,7 si está desarrollando específicamente para el nivel de API 23 o una versión anterior.

IMPORTANT
Xamarin.Android no admite JDK 9.

Instalación
Después de haber instalado Xamarin. Android, realice los pasos siguientes para que esté listo para compilar y
probar aplicaciones de desgaste de Android:
1. Instale las herramientas y el Android SDK necesarios.
2. Configurar un dispositivo de prueba.
3. Cree su primera aplicación de desgaste de Android.
Estos pasos se describen en las secciones siguientes.
Instalación de Android SDK y herramientas
Inicie el Administrador de Android SDK:
Visual Studio
Visual Studio para Mac
Asegúrese de que tiene instalados los siguientes Android SDK y herramientas:
Android SDK Tools v 24.0.0 o superior, y
Android 4.4 W (API20), o
Android 5.0.1 (API21) o superior.
Si no tiene instaladas las herramientas y el SDK más recientes, descargue las herramientas de SDK y los bits de
API necesarios (puede que tenga que desplazarse – un poco para encontrarlos; la selección de la API se muestra a
continuación):
Visual Studio
Visual Studio para Mac

Configuración
Antes de poder usar probar la aplicación, debe configurar un emulador de desgaste de Android o un dispositivo
de desgaste de Android real.
Emulador de uso de Android
Antes de poder usar un emulador de desgaste de Android, debe configurar un dispositivo virtual Android de
desgaste de Android (AVD ) con el administrador del emulador de Google:
Visual Studio
Visual Studio para Mac

Para más información sobre cómo configurar un emulador de desgaste de Android, consulte depurar el desgaste
de Android en un emulador.
Dispositivo de desgaste de Android
Si tiene un dispositivo de desgaste de Android, como un desgaste de SmartWatch de Android, puede depurar la
aplicación en este dispositivo en lugar de usar un emulador. Para obtener información sobre el desarrollo con un
dispositivo de desgaste, consulte depurar en un dispositivo de desgaste.

Cree su primera aplicación de desgaste de Android


Siga las instrucciones Hello, desgaste para compilar su primera aplicación de inspección.

Empaquetar la aplicación
Las aplicaciones de desgaste de Android siempre se distribuyen con una aplicación de teléfono Android
complementaria.
Al agregar la aplicación de desgaste de Android como referencia a la aplicación principal de Android, se supone
que es un proyecto de desgaste de Android y generará automáticamente el XML y los metadatos necesarios.
Además, comprobará que los números de versión y paquete coinciden para que pueda enviar fácilmente sus
aplicaciones a Google Play.
Para más información sobre las aplicaciones de desgaste de empaquetado, consulte trabajar con empaquetado.

Vínculos relacionados
SkeletonWear (ejemplo)
Hola, Wear
31/07/2019 • 6 minutes to read • Edit Online

Cree su primera aplicación de desgaste de Android y ejecútela en un dispositivo o emulador de desgaste. En este
tutorial se proporcionan instrucciones paso a paso para crear un pequeño proyecto de desgaste de Android que
controla los clics de los botones y muestra un contador de clics en el dispositivo de desgaste. Explica cómo
depurar la aplicación mediante un emulador de desgaste o un dispositivo de desgaste que está conectado a
través de Bluetooth a un teléfono Android. También proporciona un conjunto de sugerencias de depuración para
el desgaste de Android.

Su primera aplicación de desgaste


Siga estos pasos para crear su primera aplicación de desgaste de Xamarin. Android:
1. Crear un nuevo proyecto de Android
Cree una nueva aplicación de desgaste de Android:
Visual Studio
Visual Studio para Mac
Esta plantilla incluye automáticamente el NuGet (y las dependencias) de Xamarin Android portátil Library ,
por lo que tendrá acceso a widgets específicos de desgaste. Si no ve la plantilla de desgaste, revise la guía de
instalación y configuración para comprobar que ha instalado un Android SDK compatible.
2. Elegir la plataforma de destino correcta
Visual Studio
Visual Studio para Mac
Asegúrese de que Android to target mínimo esté establecido en Android 5,0 (Lollipop) o posterior:

Para obtener más información sobre cómo establecer la plataforma de destino, consulte Descripción de los
niveles de la API de Android.
3. Editar el diseño Main. axml
Configure el diseño para que TextView contenga Button un y un para el ejemplo:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:id="@+id/scroll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#000000"
android:fillViewport="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:text="Main Activity"
android:textSize="36sp"
android:textColor="#006600" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:textColor="#cccccc"
android:id="@+id/result" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="showNotification"
android:text="Click Me!"
android:id="@+id/click_button" />
</LinearLayout>
</ScrollView>
</FrameLayout>

4. Editar el origen de MainActivity.CS


Agregue el código para incrementar un contador y mostrarlo cada vez que se haga clic en el botón:

[Activity (Label = "WearTest", MainLauncher = true, Icon = "@drawable/icon")]


public class MainActivity : Activity
{
int count = 1;

protected override void OnCreate (Bundle bundle)


{
base.OnCreate (bundle);

SetContentView (Resource.Layout.Main);

Button button = FindViewById<Button> (Resource.Id.click_button);


TextView text = FindViewById<TextView> (Resource.Id.result);

button.Click += delegate {
text.Text = string.Format ("{0} clicks!", count++);
};
}
}

5. Configurar un emulador o un dispositivo


El siguiente paso consiste en configurar un emulador o un dispositivo para implementar y ejecutar la aplicación.
Si aún no está familiarizado con el proceso de implementación y ejecución de aplicaciones de Xamarin. Android
en general, consulte la guía de Inicio rápido de Hello, Android.
Si no tiene un dispositivo de desgaste de Android, como un desgaste de SmartWatch de Android, puede ejecutar
la aplicación en un emulador. Para obtener información sobre cómo depurar aplicaciones de desgaste en un
emulador, consulte depurar el desgaste de Android en un emulador.
Si tiene un dispositivo de desgaste de Android, como un desgaste de SmartWatch de Android, puede ejecutar la
aplicación en el dispositivo en lugar de usar un emulador. Para obtener más información sobre la depuración en
un dispositivo de desgaste, consulte depurar en un dispositivo de desgaste.
6. Ejecutar la aplicación de desgaste de Android
El dispositivo de desgaste de Android debe aparecer en el menú desplegable del dispositivo. Asegúrese de elegir
el dispositivo de desgaste de Android correcto o AVD antes de iniciar la depuración. Después de seleccionar el
dispositivo, haga clic en el botón reproducir para implementar la aplicación en el emulador o el dispositivo.
Visual Studio
Visual Studio para Mac

Es posible que vea un mensaje solo un minuto... (o alguna otra pantalla intersticial) al principio:

Si usa un emulador de inspección, puede tardar un rato en iniciar la aplicación. Cuando se usa Bluetooth, se tarda
más tiempo en implementar la aplicación que en USB. (Por ejemplo, tarda unos 5 minutos en implementar esta
aplicación en una inspección de LG G que está conectada a un teléfono de Nexus 5).
Una vez que la aplicación se implemente correctamente, la pantalla del dispositivo de desgaste debería mostrar
una pantalla similar a la siguiente:

Pulse en la situado en la parte frontal del dispositivo de desgaste y ver el incremento de recuento con cada TAP:
Pasos siguientes
Consulte los ejemplos de desgaste , incluidas las aplicaciones de desgaste de Android con aplicaciones de
teléfono complementarias.
Cuando esté listo para distribuir la aplicación, consulte trabajar con empaquetado.

Vínculos relacionados
Haga clic en mi aplicación (ejemplo)
Interfaz de usuario
13/07/2019 • 2 minutes to read • Edit Online

Las siguientes secciones explican las diversas herramientas y bloques de creación que se utilizan para crear
interfaces de usuario en aplicaciones de Android Wear.

Controles
Explica Android Wear específicos controlan y proporcionan vínculos a ejemplos que muestran cómo usar estos
controles.
Controles de Android Wear
11/07/2019 • 2 minutes to read • Edit Online

Android Wear las aplicaciones pueden usar muchos de los mismos controles ya en uso para aplicaciones de
Android normales, incluido Button , TextView y recursos drawable la imagen. Controles de diseño incluidos
ScrollView , LinearLayout , y RelativateLayout también se puede usar.

Esta página contiene vínculos a los controles de Android Wear-específico desde el portátiles biblioteca de interfaz
de usuario disponibles en proyectos de Xamarin a través de la compatibilidad con ponibles paquete NuGet. Estos
controles incluyen lo siguiente:
FilterUserControl – crear una interfaz de navegación bidimensional donde el usuario desplaza hacia abajo,
a continuación, en para realizar una selección (para obtener más información, consulte FilterUserControl):

Otros controles importantes para las aplicaciones de desgaste incluyen:


BoxInsetLayout (consulte trabajar con tamaños de pantalla),
WatchViewStub (consulte trabajar con tamaños de pantalla),
CardFrame (consulte Android tarjetas crear),
CardScrollView (consulte Android tarjetas crear),
WearableListView (consulte crear listas Android).

Vínculos relacionados
Android.Support.Wearable docs
GridViewPager
31/07/2019 • 2 minutes to read • Edit Online

En el ejemplo GridViewPager se muestra cómo implementar el modelo de navegación del selector 2D para el
desgaste de Android.

En primer lugar, agregue el paquete NuGet de soporte técnico de Xamarin Android para el proyecto.
El XML de diseño tiene el siguiente aspecto:

<android.support.wearable.view.GridViewPager xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:keepScreenOn="true" />

Crear un GridPagerAdapter (o una subclase como FragmentGridPagerAdapter para proporcionar las vistas que se van
a mostrar cuando el usuario navega.
El adaptador de ejemplo muestra cómo implementar los métodos necesarios, incluidas las invalidaciones
RowCount para GetColumnCount , GetBackground , y GetFragment

Conecte el adaptador como se muestra a continuación:

pager.Adapter = new SimpleGridPagerAdapter (this, FragmentManager);

Vínculos relacionados
Documento del selector de 2D de Google
documentos de Android. support. portátil
GridViewPager (sample)
Características de la plataforma
13/07/2019 • 2 minutes to read • Edit Online

Documentos de esta sección tratan características específicas de Android Wear. Aquí encontrará un tema que
describe cómo crear un WatchFace.

Creación de una esfera del reloj


Un tutorial paso a paso para implementar un servicio de cara de supervisión personalizada para Android Wear. Se
proporcionan instrucciones para la creación de un eliminados servicio cara de inspección digital y, a continuación,
se agrega más código para crear un reloj analógico de estilo con características adicionales.
Creación de una esfera del reloj
16/08/2019 • 29 minutes to read • Edit Online

En esta guía se explica cómo implementar un servicio de reloj de observación personalizado para el desgaste de
Android 1,0. Se proporcionan instrucciones paso a paso para crear un servicio de caras de supervisión digital de
bajada, seguido de más código para crear una superficie de inspección de estilo analógico.

Información general
En este tutorial, se crea un servicio básico de la guía de observación para ilustrar los aspectos básicos de la
creación de una superficie de inspección 1,0 personalizada de un desgaste de Android. El servicio de la esfera de
reloj inicial muestra una simple inspección digital que muestra la hora actual en horas y minutos:

Después de desarrollar y probar esta superficie de inspección digital, se agrega más código para actualizarla a una
esfera de inspección analógica más sofisticada con tres manos:

Ver los servicios faciales se agrupan e instalan como parte de una aplicación de desgaste de 1,0. En los siguientes
ejemplos, MainActivity no contiene nada más que el código de la plantilla de aplicación de desgaste 1,0, de modo
que el servicio de reloj de inspección se puede empaquetar e implementar en Smart Watch como parte de la
aplicación. En efecto, esta aplicación servirá exclusivamente como vehículo para obtener el servicio de reloj de
observación cargado en el dispositivo (o emulador) de desgaste 1,0 para la depuración y las pruebas.

Requisitos
Para implementar un servicio de reloj de inspección, se requiere lo siguiente:
Android 5,0 (nivel de API 21) o superior en el dispositivo o emulador de desgaste.
Las bibliotecas de compatibilidad con el desgaste de Android de Xamarin se deben agregar al proyecto de
Xamarin. Android.
Aunque Android 5,0 es el nivel de API mínimo para implementar un servicio de reloj, se recomienda Android 5,1
o posterior. Los dispositivos de uso de Android que ejecutan Android 5,1 (API 22) o una versión superior permiten
el desgaste de las aplicaciones para controlar lo que se muestra en la pantalla mientras el dispositivo está en
modo ambiente de baja energía. Cuando el dispositivo deja el modo ambiente de baja energía, está en modo
interactivo . Para obtener más información sobre estos modos, consulte mantener visible la aplicación.

Iniciar un proyecto de aplicación


Cree un nuevo proyecto de desgaste de Android 1,0 denominado WatchFace (para obtener más información
sobre cómo crear nuevos proyectos de Xamarin. Android, consulte Hello, Android):
Visual Studio
Visual Studio para Mac

Establezca el nombre del paquete com.xamarin.watchface en:


Visual Studio
Visual Studio para Mac
Visual Studio
Visual Studio para Mac
Además, desplácese hacia abajo y habilite los permisos de Internet y WAKE_LOCK :

A continuación, descargue Preview . png – y se agregará a la carpeta drawables más adelante en este tutorial.

Adición del paquete de desgaste de Xamarin. Android


Visual Studio
Visual Studio para Mac
Inicie el administrador de paquetes NuGet (en Visual Studio, haga clic con el botón derecho en referencias en el
Explorador de soluciones y seleccione administrar paquetes NuGet... ). Actualice el proyecto a la versión
estable más reciente de Xamarin. Android. desgaste:

Después, si Xamarin. Android. support. v13 está instalado, desinstálelo:


Compilar y ejecutar la aplicación en un dispositivo o emulador de desgaste (para obtener más información sobre
cómo hacerlo, consulte la guía de Introducción ). Debería ver la siguiente pantalla de la aplicación en el dispositivo
de desgaste:
![Captura de pantalla] de la aplicación (creating-a-watchface-images/08-app-screen.png "Pantalla de la aplicación
en el dispositivo de desgaste")
Llegados a este punto, la aplicación de desgaste básica no tiene la funcionalidad de observación, ya que aún no
proporciona una implementación de Watch Point Service. Este servicio se agregará a continuación.

CanvasWatchFaceService
El desgaste de Android implementa caras de inspección CanvasWatchFaceService a través de la clase.
CanvasWatchFaceService se deriva de WatchFaceService , que a su vez se WallpaperService deriva de tal y como se
muestra en el diagrama siguiente:

CanvasWatchFaceService incluye un anidado CanvasWatchFaceService.Engine ; crea una instancia de


CanvasWatchFaceService.Engine un objeto que realiza el trabajo real de dibujar la superficie de inspección.
CanvasWatchFaceService.Engine se deriva de WallpaperService.Engine como se muestra en el diagrama anterior.

No se muestra en este Canvas diagrama el que CanvasWatchFaceService usa para Canvas dibujar la esfera – del
reloj que se pasa a través OnDraw del método, tal y como se describe a continuación.
En las secciones siguientes, se creará un servicio de portada de inspección personalizado siguiendo estos pasos:
1. Defina una clase denominada MyWatchFaceService que se derive de CanvasWatchFaceService .
2. Dentro de, cree una clase anidada
MyWatchFaceService MyWatchFaceEngine denominada que se derive
CanvasWatchFaceService.Engine de.

3. En MyWatchFaceService , implemente CreateEngine un método que cree MyWatchFaceEngine instancias de y


lo devuelva.
4. En MyWatchFaceEngine , implemente OnCreate el método para crear el estilo de la esfera de inspección y
realizar cualquier otra tarea de inicialización.
5. Implemente OnDraw el método MyWatchFaceEngine de. Se llama a este método cada vez que es necesario
volver a dibujar la esfera de inspección(es decir, invalidada). OnDraw es el método que dibuja (y vuelve a
dibujar) los elementos de la superficie de inspección, como la hora, el minuto y el segundo.
6. Implemente OnTimeTick el método MyWatchFaceEngine de. OnTimeTick se llama al menos una vez por
minuto (en los modos de ambiente e interactivos) o cuando ha cambiado la fecha y hora.
Para obtener más información CanvasWatchFaceService sobre, consulte la documentación de la API de Android
CanvasWatchFaceService . Del mismo modo, CanvasWatchFaceService. Engine explica la implementación real de
la superficie de inspección.
Agregar CanvasWatchFaceService
Visual Studio
Visual Studio para Mac
Agregue un nuevo archivo denominado MyWatchFaceService.CS (en Visual Studio, haga clic con el botón
derecho en WatchFace en el Explorador de soluciones, haga clic en Agregar > nuevo elemento... y
seleccione clase).
Reemplace el contenido de este archivo por el código siguiente:

using System;
using Android.Views;
using Android.Support.Wearable.Watchface;
using Android.Service.Wallpaper;
using Android.Graphics;

namespace WatchFace
{
class MyWatchFaceService : CanvasWatchFaceService
{
public override WallpaperService.Engine OnCreateEngine()
{
return new MyWatchFaceEngine(this);
}

public class MyWatchFaceEngine : CanvasWatchFaceService.Engine


{
CanvasWatchFaceService owner;
public MyWatchFaceEngine (CanvasWatchFaceService owner) : base(owner)
{
this.owner = owner;
}
}
}
}

MyWatchFaceService (derivado de CanvasWatchFaceService ) es el "programa principal" de la superficie de


inspección. MyWatchFaceService implementa solo un método OnCreateEngine ,, que crea instancias y devuelve un
MyWatchFaceEngine objeto ( MyWatchFaceEngine se deriva de CanvasWatchFaceService.Engine ). El MyWatchFaceEngine
objeto WallpaperService.Engine con instancias debe devolverse como. El MyWatchFaceService objeto de
encapsulación se pasa al constructor.
MyWatchFaceEngine es la implementación – de la esfera de inspección real que contiene el código que dibuja la
esfera del reloj. También controla eventos del sistema, como cambios en la pantalla (modos de
ambiente/interactivo, desactivación de la pantalla, etc.).
Implementar el método de creación de motor
El OnCreate método inicializa la esfera de inspección. Agregue el siguiente campo a MyWatchFaceEngine :

Paint hoursPaint;

Este Paint objeto se usará para dibujar la hora actual en la superficie de inspección. A continuación, agregue el
método siguiente MyWatchFaceEngine a:

public override void OnCreate(ISurfaceHolder holder)


{
base.OnCreate (holder);

SetWatchFaceStyle (new WatchFaceStyle.Builder(owner)


.SetCardPeekMode (WatchFaceStyle.PeekModeShort)
.SetBackgroundVisibility (WatchFaceStyle.BackgroundVisibilityInterruptive)
.SetShowSystemUiTime (false)
.Build ());

hoursPaint = new Paint();


hoursPaint.Color = Color.White;
hoursPaint.TextSize = 48f;
}

OnCreate se llama poco después MyWatchFaceEngine de iniciarse. Configura WatchFaceStyle (que controla cómo
interactúa el dispositivo con el usuario) y crea una instancia del Paint objeto que se usará para mostrar la hora.
La llamada a SetWatchFaceStyle hace lo siguiente:
1. Establece el modo de PeekModeShort inspección en, que hace que las notificaciones aparezcan como tarjetas
de "lectura" pequeñas en la pantalla.
2. Establece la visibilidad del fondo Interruptive en, lo que hace que el fondo de una tarjeta PEEK solo se
muestre brevemente si representa una notificación de interrupción.
3. Deshabilita la hora de la interfaz de usuario del sistema predeterminada para que no se dibuje en la
superficie de inspección, de modo que la superficie de inspección personalizada pueda mostrar la hora en
su lugar.
Para obtener más información sobre estas y otras opciones de estilo de la esfera de inspección, consulte la
documentación de la API de Android WatchFaceStyle. Builder .
Una SetWatchFaceStyle vez finalizada OnCreate , crea una Paint instancia del hoursPaint objeto () y establece su
color en blanco y su tamaño de texto en 48 píxeles (TEXTSIZE debe especificarse en píxeles).
Implementar el método OnDraw del motor
El OnDraw método es quizás el método – más CanvasWatchFaceService.Engine importante es el método que
realmente dibuja los elementos de la esfera de la inspección, como los dígitos y las manecillas del reloj. En el
ejemplo siguiente, dibuja una cadena de hora en la superficie de inspección. Agregue el método siguiente a
MyWatchFaceEngine :
public override void OnDraw (Canvas canvas, Rect frame)
{
var str = DateTime.Now.ToString ("h:mm tt");
canvas.DrawText (str,
(float)(frame.Left + 70),
(float)(frame.Top + 80), hoursPaint);
}

Cuando Android llama OnDraw a, pasa una Canvas instancia de y los límites en los que se puede dibujar la esfera.
En el ejemplo de código anterior DateTime , se usa para calcular la hora actual en horas y minutos (en formato de
12 horas). La cadena de tiempo resultante se dibuja en el lienzo mediante el Canvas.DrawText método. La cadena
mostrará 70 píxeles por encima del borde izquierdo y 80 píxeles hacia abajo desde el borde superior.
Para obtener más información sobre OnDraw el método, consulte la documentación de la API de Android OnDraw
.
Implementar el método OnTimeTick del motor
Android llama OnTimeTick periódicamente al método para actualizar la hora que se muestra en la superficie de
inspección. Se llama al menos una vez por minuto (en los modos de ambiente e interactivos), o cuando la fecha y
hora o la zona horaria han cambiado. Agregue el método siguiente a MyWatchFaceEngine :

public override void OnTimeTick()


{
Invalidate();
}

Esta implementación de OnTimeTick simplemente llama Invalidate a. El Invalidate método programa OnDraw
para volver a dibujar la esfera de inspección.
Para obtener más información sobre OnTimeTick el método, consulte la documentación de la API de Android
onTimeTick .

Registrar CanvasWatchFaceService
MyWatchFaceService debe estar registrado en el archivo AndroidManifest. XML de la aplicación de desgaste
asociada. Para ello, agregue el siguiente código XML a la <application> sección:

<service
android:name="watchface.MyWatchFaceService"
android:label="Xamarin Sample"
android:allowEmbedded="true"
android:taskAffinity=""
android:permission="android.permission.BIND_WALLPAPER">
<meta-data
android:name="android.service.wallpaper"
android:resource="@xml/watch_face" />
<meta-data
android:name="com.google.android.wearable.watchface.preview"
android:resource="@drawable/preview" />
<intent-filter>
<action android:name="android.service.wallpaper.WallpaperService" />
<category android:name="com.google.android.wearable.watchface.category.WATCH_FACE" />
</intent-filter>
</service>

Este XML hace lo siguiente:


1. Establece el android.permission.BIND_WALLPAPER permiso. Este permiso concede al servicio de reloj ver el
permiso para cambiar el papel tapiz del sistema en el dispositivo. Tenga en cuenta que este permiso se debe
establecer <service> en la sección en lugar de <application> en la sección externa.
2. Define un watch_face recurso. Este recurso es un archivo XML corto que declara un wallpaper recurso
(este archivo se creará en la sección siguiente).
3. Declara una imagen dibujable llamada preview que se mostrará en la pantalla de selección del selector de
inspección.
4. Incluye un intent-filter para permitir que Android sepa MyWatchFaceService que mostrará una esfera de
inspección.
Esto completa el código para el ejemplo básico WatchFace . El siguiente paso consiste en agregar los recursos
necesarios.

Agregar archivos de recursos


Antes de poder ejecutar el servicio de inspección, debe agregar el recurso watch_face y la imagen de vista previa.
En primer lugar, cree un nuevo archivo XML en Resources /XML/watch_face. XML y reemplace su contenido
por el siguiente código XML:

<?xml version="1.0" encoding="UTF-8"?>


<wallpaper xmlns:android="http://schemas.android.com/apk/res/android" />

Establezca la acción de compilación de este archivo en AndroidResource:


Visual Studio
Visual Studio para Mac

Este archivo de recursos define un wallpaper elemento simple que se utilizará para la esfera de inspección.
Si todavía no lo ha hecho, descargue Preview. png. Instálelo en Resources /drawable/Preview. png. Asegúrese
de agregar este archivo al WatchFace proyecto. Esta imagen de vista previa se muestra al usuario en el selector de
caras de inspección en el dispositivo de desgaste. Para crear una imagen de vista previa para su propia esfera de
inspección, puede realizar una captura de pantalla de la superficie del reloj mientras se está ejecutando. (Para
obtener más información sobre cómo obtener capturas de pantallas de dispositivos de desgaste, consulte realizar
capturas de pantallas).

Pruébalo.
Compile e implemente la aplicación en el dispositivo de desgaste. Debería ver que la pantalla de la aplicación de
desgaste aparece como antes. Haga lo siguiente para habilitar la nueva esfera de inspección:
1. Deslice el dedo hacia la derecha hasta que vea el fondo de la pantalla de inspección.
2. Toque y mantenga presionado en cualquier lugar del fondo de la pantalla durante dos segundos.
3. Deslice el dedo de izquierda a derecha para desplazarse por los distintos rostros de inspección.
4. Seleccione la esfera de ejemplo de Xamarin (que se muestra a la derecha):

5. Puntee en la esfera de ejemplo de Xamarin para seleccionarla.


Esto cambia la parte del reloj del dispositivo de desgaste para usar el servicio de la esfera de inspección
personalizada implementada hasta el momento:

Se trata de una esfera de inspección relativamente crudo porque la implementación de la aplicación es tan mínima
(por ejemplo, no incluye un fondo de la esfera Paint de reloj y no llama a los métodos de suavizado de contorno
para mejorar la apariencia). Sin embargo, implementa la funcionalidad básica necesaria para crear una superficie
de inspección personalizada.
En la siguiente sección, esta superficie de inspección se actualizará a una implementación más sofisticada.

Actualización de la esfera de inspección


En el resto de este tutorial, MyWatchFaceService se actualiza para mostrar una superficie de inspección de estilo
analógico y se amplía para admitir más características. Se agregarán las siguientes funcionalidades para crear la
superficie de inspección actualizada:
1. Indica la hora con la hora analógica, el minuto y la segunda manecilla.
2. Reacciona a los cambios en la visibilidad.
3. Responde a los cambios entre el modo ambiente y el modo interactivo.
4. Lee las propiedades del dispositivo de desgaste subyacente.
5. Actualiza automáticamente la hora a la que tiene lugar un cambio de zona horaria.
Antes de implementar los cambios de código siguientes, descargue drawable. zip, descomprima el archivo y
mueva los archivos. png descomprimidos a Resources /drawable (sobrescriba la versión preliminar.
pnganterior). Agregue los nuevos archivos. png al WatchFace proyecto.
Características del motor de actualización
El paso siguiente es actualizar MyWatchFaceService.CS a una implementación que dibuja una esfera de
inspección analógica y admite nuevas características. Reemplace el contenido de MyWatchFaceService.CS por
la versión analógica del código de la fuente de inspección en MyWatchFaceService.CS (puede cortar y pegar este
origen en el MyWatchFaceService.CSexistente).
Esta versión de MyWatchFaceService.CS agrega más código a los métodos existentes e incluye métodos
invalidados adicionales para agregar más funcionalidad. En las secciones siguientes se proporciona una visita
guiada del código fuente.
OnCreate
El método alcreate actualizado configura el estilo de la esfera de inspección como antes, pero incluye algunos
pasos adicionales:
1. Establece la imagen de fondo en el recurso xamarin_background que reside en Resources /drawable-
hdpi/xamarin_background. png.
2. Paint Inicializa objetos para dibujar la manecilla de la hora, la manecilla del minuto y la segunda mano.
3. Inicializa un Paint objeto para dibujar los tics de hora alrededor del borde de la superficie de inspección.
4. Crea un temporizador que llama al Invalidate método (Redraw ) para que la segunda mano se vuelva a
dibujar cada segundo. Tenga en cuenta que este temporizador es OnTimeTick necesario Invalidate porque
llama solo una vez cada minuto.
Este ejemplo solo incluye una imagen xamarin_background. png ; sin embargo, puede que desee crear una
imagen de fondo diferente para cada densidad de pantalla que admita la esfera de inspección personalizada.
OnDraw
El método OnDraw actualizado dibuja una superficie de inspección de estilo analógico mediante los pasos
siguientes:
1. Obtiene la hora actual, que ahora se mantiene en un time objeto.
2. Determina los límites de la superficie de dibujo y su centro.
3. Dibuja el fondo, escalado para ajustarse al dispositivo cuando se dibuja el fondo.
4. Dibuja doce TICs alrededor de la superficie del reloj (correspondiente a las horas de la esfera del reloj).
5. Calcula el ángulo, la rotación y la longitud de cada mano de inspección.
6. Dibuja cada mano en la superficie de inspección. Tenga en cuenta que la segunda mano no se dibuja si el
reloj está en modo ambiente.
OnPropertiesChanged
Se llama a este método para MyWatchFaceEngine informar sobre las propiedades del dispositivo de desgaste (por
ejemplo, el modo ambiente de baja bits y la protección de la grabación). En MyWatchFaceEngine , este método solo
comprueba el modo ambiente de baja velocidad (en el modo de ambiente de bajo nivel, la pantalla admite menos
bits para cada color).
Para obtener más información sobre este método, consulte la documentación de la API de Android
onPropertiesChanged .
OnAmbientModeChanged
Se llama a este método cuando el dispositivo de desgaste entra o sale del modo ambiente. En la
MyWatchFaceEngine implementación, la superficie de inspección deshabilita el suavizado de contorno cuando está
en modo ambiente.
Para obtener más información sobre este método, consulte la documentación de la API de Android
onAmbientModeChanged .
OnVisibilityChanged
Se llama a este método siempre que el reloj esté visible u oculto. En MyWatchFaceEngine , este método registra o
anula el registro del receptor de zona horaria (descrito a continuación) según el estado de visibilidad.
Para obtener más información sobre este método, consulte la documentación de la API de Android
onVisibilityChanged .
Característica de zona horaria
El nuevo MyWatchFaceService.CS también incluye funcionalidad para actualizar la hora actual cada vez que
cambia la zona horaria (por ejemplo, mientras viaja a través de zonas horarias). Casi al final de
MyWatchFaceService.CS, se define un cambio BroadcastReceiver de zona horaria que controla los objetos de
intención modificados por zona horaria:

public class TimeZoneReceiver: BroadcastReceiver


{
public Action<Intent> Receive { get; set; }
public override void OnReceive (Context context, Intent intent)
{
if (Receive != null)
Receive (intent);
}
}

El RegisterTimezoneReceiver método UnregisterTimezoneReceiver llama a los métodos y.


OnVisibilityChanged
UnregisterTimezoneReceiver se llama a cuando el estado de visibilidad de la esfera de inspección se cambia a
oculto. Cuando la superficie de inspección vuelve a estar RegisterTimezoneReceiver visible, se llama a
OnVisibilityChanged (vea el método).

El método RegisterTimezoneReceiver Engine declara un controlador para este evento de Receive receptor de
zona horaria; este controlador actualiza el time objeto con la nueva hora cada vez que se cruza una zona horaria:

timeZoneReceiver = new TimeZoneReceiver ();


timeZoneReceiver.Receive = (intent) => {
time.Clear (intent.GetStringExtra ("time-zone"));
time.SetToNow ();
};

Se crea un filtro de intención y se registra para el receptor de zona horaria:

IntentFilter filter = new IntentFilter(Intent.ActionTimezoneChanged);


Application.Context.RegisterReceiver (timeZoneReceiver, filter);

El UnregisterTimezoneReceiver método anula el registro del receptor de zona horaria:

Application.Context.UnregisterReceiver (timeZoneReceiver);
Ejecutar la superficie de inspección mejorada
Compile e implemente de nuevo la aplicación en el dispositivo de desgaste. Seleccione la esfera de reloj del
selector de caras de inspección como antes. La vista previa en el selector de inspección se muestra a la izquierda y
la nueva esfera de inspección se muestra a la derecha:

En esta captura de pantalla, la segunda mano se mueve una vez por segundo. Al ejecutar este código en un
dispositivo de desgaste, la segunda mano desaparece cuando el reloj entra en el modo ambiente.

Resumen
En este tutorial, se implementó y probó un desgaste de Android personalizado 1,0 watchface. Se
CanvasWatchFaceService introdujeron CanvasWatchFaceService.Engine las clases y, y los métodos esenciales de la
clase Engine se implementaron para crear una superficie simple de inspección digital. Esta implementación se
actualizó con más funcionalidad para crear una superficie de inspección analógica y se implementaron métodos
adicionales para controlar los cambios en la visibilidad, el modo ambiente y las diferencias en las propiedades del
dispositivo. Por último, se implementó un receptor de difusión de zona horaria para que el reloj actualice
automáticamente la hora a la que se cruza una zona horaria.

Vínculos relacionados
Crear caras de inspección
Ejemplo de WatchFace
WatchFaceService.Engine
Trabajar con tamaños de pantalla
31/07/2019 • 2 minutes to read • Edit Online

Los dispositivos de desgaste de Android pueden tener una pantalla rectangular o redonda, que también puede
tener tamaños diferentes.

Tipo de pantalla de identificación


La biblioteca de soporte técnico de desgaste proporciona algunos controles que le ayudan a detectar y adaptarse
a diferentes formas WatchViewStub de BoxInsetLayout pantalla, como y.
Tenga en cuenta que algunos de los otros controles de la biblioteca de GridViewPager compatibilidad (como)
detectan automáticamente la forma de pantalla y no deben agregarse como elementos secundarios de los
controles que se describen a continuación.
WatchViewStub
Vea el ejemplo de WatchViewStub para ver cómo detectar el tipo de pantalla y mostrar un diseño diferente para
cada tipo.
El archivo de diseño principal contiene android.support.wearable.view.WatchViewStub un que hace referencia a
diferentes diseños para pantallas rectangulares y app:rectLayout redondas usando los atributos y
app:roundLayout :

<android.support.wearable.view.WatchViewStub
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/stub"
app:rectLayout="@layout/rect_layout"
app:roundLayout="@layout/round_layout" />

La solución contiene diferentes diseños para cada estilo que se seleccionarán en tiempo de ejecución:

BoxInsetLayout
En lugar de crear diseños diferentes para cada tipo de pantalla, también puede crear una vista única que se
adapte a pantallas rectangulares o redondas.
En este ejemplo de Google se muestra cómo BoxInsetLayout usar el para usar el mismo diseño en pantallas
rectangulares y redondas.

Diseñador de IU de desgaste
Xamarin Android Designer admite pantallas rectangulares y redondas:

Aquí se muestra la superficie de diseño en estilo rectangular:

Aquí se muestra la superficie de diseño en el estilo redondo:

Simulador de desgaste
El Administrador del emulador de Google contiene definiciones de dispositivos para ambos tipos de pantalla.
Puede crear emuladores rectangulares y redondos para probar la aplicación.
El emulador se representará como esto para una pantalla rectangular:

Se representará como esto para una pantalla redonda:

Vídeo
Aplicaciones de pantalla completa para el desgaste de Android desde developers.Google.com.
Implementación y prueba
13/07/2019 • 2 minutes to read • Edit Online

Esta sección explica cómo probar la aplicación Android Wear en un dispositivo Android Wear (o en un emulador
de Android configurado para desgaste). También incluye depuración sugerencias e información acerca de cómo
configurar una conexión Bluetooth entre el equipo de desarrollo y un dispositivo Android. Cuando la aplicación
está lista, el último tema explica cómo preparar la aplicación para la implementación.

Depurar Android Wear en un emulador


Cómo depurar una aplicación de Xamarin.Android desgaste en el emulador de Android SDK.

Depuración en un dispositivo Wear


Cómo configurar un dispositivo Android para que se pueden implementar aplicaciones de Xamarin.Android
desgaste en él directamente desde Visual Studio o Visual Studio para Mac.

Desgaste de empaquetado de aplicaciones


Describe cómo empaquetar aplicaciones de desgaste de Xamarin.Android para su distribución en Google Play.
Depurar Android Wear en un emulador
11/07/2019 • 3 minutes to read • Edit Online

Estos artículos explica cómo depurar una aplicación de desgaste de Xamarin.Android en un emulador.

Depurar desgaste de información general del emulador


Desarrollo de aplicaciones de Android Wear requiere ejecutar la aplicación, ya sea en el hardware físico o un
emulador o simulador. El uso de hardware es el mejor enfoque, pero no siempre es el más práctico. En muchos
casos, puede ser más sencillo y más rentable simular o emular el hardware de Android Wear con un emulador,
como se describe a continuación. Si todavía no está familiarizado con el proceso de implementar y ejecutar
aplicaciones de Android Wear, vea Hola, Wear.

Configurar el emulador de Android


Para ejecutar la aplicación Wear en un emulador, debe instalar el emulador de Android SDK de Android y
configurarlo para Android Wear. Para el emulador de Android SDK instalación y configuración de información
general, consulte configuración de Android Emulator.
Cuando se crea un dispositivo virtual de desgaste, seleccione un perfil de dispositivo Android Wear (como
Android Wear cuadrado). Para mejorar el rendimiento, utilice el desgaste x86 CPU/ABI tal como se muestra en
este ejemplo:

Inicie el dispositivo Virtual Wear


Después de haber creado un dispositivo virtual Android Wear, puede elegir en el menú desplegable de
dispositivo en el IDE antes de iniciar la depuración. Si el dispositivo virtual no está disponible en el menú
desplegable del dispositivo, compruebe que el proyecto es un Android Wear de nivel de proyecto de aplicación
(no un proyecto de aplicación de Android) y que su nivel de API de destino está establecido en la misma API que
el dispositivo virtual. Por ejemplo:
Cuando se inicia el emulador de Android, Xamarin.Android implementará la aplicación de desgaste en el
emulador. El emulador ejecuta la aplicación con la imagen de dispositivo virtual configurada.
No se sorprenda si ve esto (o en otra pantalla intersticial) al principio. El emulador de inspección puede tardar
unos minutos en iniciarse:

El emulador puede dejarse en ejecución, de modo que no es necesario cerrarlo y reiniciarlo cada vez que se
ejecuta la aplicación.

Resumen
Esta guía explica cómo configurar el emulador de Android para el desarrollo de desgaste e iniciar un dispositivo
virtual de desgaste para la depuración.
Depuración en un dispositivo Wear
16/08/2019 • 7 minutes to read • Edit Online

En este artículo se explica cómo depurar una aplicación de desgaste de Xamarin. Android en un dispositivo de
desgaste.

Información general
Si tiene un dispositivo de desgaste de Android, como un desgaste de SmartWatch de Android, puede ejecutar la
aplicación en el dispositivo en lugar de usar un emulador. (Si aún no está familiarizado con el proceso de
implementación y ejecución de aplicaciones de uso de Android, consulte Hola, desgaste).

Preparar el dispositivo de desgaste:


Siga estos pasos para habilitar la depuración en el dispositivo de desgaste de Android:
1. Abra el menú de configuración en el dispositivo de desgaste de Android.
2. Desplácese a la parte inferior del menú y puntee en acercade.
3. Puntee en el número de compilación 7 veces.
4. En el menú configuración , pulse Opciones de desarrollador.
5. Confirme que está habilitada la depuración de ADB .

Depuración a través de USB


Si el dispositivo de desgaste tiene un puerto USB, puede conectarlo al equipo, implementarlo y ejecutar o depurar
la aplicación como lo haría con un teléfono Android (para más información, consulte depurar en un dispositivo).

Depuración a través de Bluetooth


Si el dispositivo de desgaste no tiene un puerto USB, puede implementar la aplicación en el dispositivo de
desgaste a través de Bluetooth mediante el enrutamiento de la salida de depuración de la aplicación a un teléfono
Android que esté conectado al equipo.
Preparación del teléfono
Siga estos pasos para preparar el teléfono para realizar conexiones Bluetooth al dispositivo de desgaste:
1. Si todavía no lo ha hecho, configure el teléfono para el desarrollo de Xamarin. Android, como se explica en
configuración del dispositivo para el desarrollo.
2. Descargue e instale la aplicación gratuita de desgaste de Android desde el Google Play Store.
Conectar el dispositivo
Siga estos pasos para conectar el dispositivo de desgaste a su teléfono:
1. En el teléfono que actuará como intermediario de Bluetooth (configurado anteriormente), inicie la
aplicación de desgaste de Android.
2. Pulse el icono de configuración .
3. Habilite la depuración a través de Bluetooth. Debería ver el siguiente estado en la pantalla de la
aplicación de desgaste de Android:

Host: disconnected
Target: connected

4. Conecte el teléfono al equipo a través de USB. En el equipo, escriba los siguientes comandos:

adb forward tcp:4444 localabstract:/adb-hub


adb connect 127.0.0.1:4444

Si el puerto 4444 no está disponible, puede usar cualquier otro puerto disponible al que tenga acceso.

NOTE
Si reinicia Visual Studio o Visual Studio para Mac, debe volver a ejecutar estos comandos para configurar una
conexión con el dispositivo de desgaste.

5. Cuando el dispositivo de desgaste le solicite, confirme que permite la depuración de ADB. En la aplicación
de desgaste de Android, debería ver el cambio de estado a:

Host: connected
Target: connected

6. Después de completar los pasos anteriores, al adb devices ejecutar se muestra el estado del teléfono y del
dispositivo de desgaste de Android:

List of devices attached


127.0.0.1:4444 device
019ad61df0a69399 device

Llegados a este punto, puede implementar la aplicación en el dispositivo de desgaste.


Realizar capturas de pantallas
Puede realizar una captura de pantalla del dispositivo de desgaste escribiendo el siguiente comando:

adb -s 127.0.0.1:4444 shell screencap -p /sdcard/DCIM/screencap.png

Copie la captura de pantalla en el equipo escribiendo el siguiente comando:

adb -s 127.0.0.1:4444 pull /sdcard/DCIM/screencap.png

Escriba el siguiente comando para eliminar la captura de pantalla del dispositivo:

adb -s 127.0.0.1:4444 shell rm /sdcard/DCIM/screencap.png

Desinstalación de una aplicación


Puede desinstalar una aplicación del dispositivo de desgaste escribiendo el siguiente comando:

adb -s 127.0.0.1:4444 uninstall <package name>


Por ejemplo, para quitar la aplicación con el nombre com.xamarin.weartest del paquete, escriba el siguiente
comando:

adb -s 127.0.0.1:4444 uninstall com.xamarin.weartest

Para obtener más información sobre la depuración de dispositivos de desgaste de Android a través de Bluetooth,
consulte depuración a través de Bluetooth.

Depuración de una aplicación de desgaste con una aplicación de


teléfono complementaria
Las aplicaciones de desgaste de Android se empaquetan con una aplicación de teléfono Android complementaria
para su distribución en Google Play (para obtener más información, consulte trabajar con empaquetado). Sin
embargo, todavía desarrolla la aplicación de desgaste y su aplicación complementaria por separado. Al publicar la
aplicación a través del Google Play Store, la aplicación de desgaste se empaquetará con la aplicación
complementaria y se instalará automáticamente si es posible.
Para depurar la aplicación de desgaste con una aplicación complementaria:
1. Cree e implemente la aplicación complementaria en el teléfono.
2. Haga clic con el botón derecho en el proyecto de desgaste y establézcalo como proyecto de inicio
predeterminado.
3. Implemente el proyecto de desgaste en el dispositivo portátil.
4. Ejecute y depure la aplicación de desgaste en el dispositivo.

Resumen
En este artículo se explica cómo configurar un dispositivo de desgaste de Android para el desgaste de la
depuración desde Visual Studio a través de Bluetooth y cómo depurar una aplicación de desgaste con una
aplicación de teléfono complementaria. También proporciona sugerencias de depuración comunes para depurar
una aplicación de desgaste a través de Bluetooth.
Aplicaciones de desgaste de empaquetado
16/08/2019 • 6 minutes to read • Edit Online

Las aplicaciones de desgaste de Android se empaquetan con una aplicación Android completa para su
distribución en Google Play.

Empaquetado automático
A partir de Xamarin Android 5,0, la aplicación de desgaste se empaqueta automáticamente como un recurso en
la aplicación de mano cuando se crea una referencia de proyecto desde el proyecto de mano al proyecto de
desgaste. Puede usar los pasos siguientes para crear esta asociación:
Visual Studio
Visual Studio para Mac
1. Si la aplicación de desgaste todavía no forma parte de la solución de mano, haga clic con el botón
derecho en el nodo de la solución y seleccione agregar > agregar proyecto existente.. ..
2. Navegue hasta el archivo . csproj de la aplicación de desgaste, selecciónelo y haga clic en abrir. El
proyecto de aplicación de desgaste debe estar ahora visible en la solución de mano.
3. Haga clic con el botón secundario en el nodo referencias y seleccione Agregar referencia.
4. En el cuadro de diálogo Administrador de referencias , habilite el proyecto de desgaste (haga clic para
agregar una marca de verificación) y, a continuación, haga clic en Aceptar.
5. Cambie el nombre del paquete para el proyecto de desgaste para que coincida con el nombre de paquete
del proyecto de mano (el nombre del paquete se puede cambiar en propiedades > manifiesto de
Android).
Tenga en cuenta que recibirá un error XA5211 si el nombre del paquete de la aplicación de desgaste no coincide
con el nombre del paquete de la aplicación de mano. Por ejemplo:

Error XA5211: Embedded wear app package name differs from handheld
app package name (com.companyname.mywearapp != com.companyname.myapp). (XA5211)

Para corregir este error, cambie el nombre del paquete de la aplicación de desgaste para que coincida con el
nombre del paquete de la aplicación de mano.
Al hacer clic en compilar > compilar todo, esta asociación desencadena el empaquetado automático del
proyecto de desgaste en el proyecto principal de mano (teléfono). La aplicación de desgaste se crea
automáticamente e incluye como un recurso en la aplicación de mano.
El ensamblado que genera el proyecto de aplicación de desgaste no se usa como referencia de ensamblado en el
proyecto de mano (teléfono). En su lugar, el proceso de compilación hace lo siguiente:
Comprueba que los nombres de paquete coinciden.
Genera XML y lo agrega al proyecto de mano para asociarlo a la aplicación de desgaste. Por ejemplo:
<!-- Handheld (Phone) Project.csproj -->
<ProjectReference Include="..\MyWearApp\MyWearApp.csproj">
<Project>{D80E1FEF-653B-448C-B2AA-609C74E88340}</Project>
<Name>MyWearApp</Name>
<IsAppExtension>True</IsAppExtension>
</ProjectReference>

Agrega la aplicación de desgaste como un recurso sin procesar al proyecto de mano.

Empaquetado manual
Puede escribir aplicaciones de desgaste de Android en Xamarin. Android antes de la versión 5,0, pero debe
seguir estas instrucciones de empaquetado manual para distribuir la aplicación:
1. Asegúrese de que el proyecto de portátil y los proyectos de mano (teléfono) tienen el mismo número de
versión y el mismo nombre de paquete.
2. Compile manualmente el proyecto portátil como una compilación de versión .
3. Agregue manualmente la versión . APK del paso (2) en el directorio Resources /raw del proyecto de
mano (teléfono).
4. Agregue manualmente un nuevo recurso de recursos XML /XML/wearable_app_desc. XML en el
proyecto de mano que hace referencia a portátil apk del paso (3):

<wearableApp package="wearable.app.package.name">
<versionCode>1</versionCode>
<versionName>1.0</versionName>
<rawPathResId>NAME_OF_APK_FROM_STEP_3</rawPathResId>
</wearableApp>

5. Agregue manualmente un <meta-data /> elemento al elemento archivo AndroidManifest. XML


<application> del proyecto de mano que hace referencia al nuevo recurso XML:

<meta-data android:name="com.google.android.wearable.beta.app"
android:resource="@xml/wearable_app_desc"/>

Vea también las instrucciones manualesdel sitio para desarrolladores de Android packging.

También podría gustarte