{"id":2102,"date":"2023-08-08T13:23:32","date_gmt":"2023-08-08T13:23:32","guid":{"rendered":"https:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/?p=2102"},"modified":"2023-08-09T08:29:55","modified_gmt":"2023-08-09T08:29:55","slug":"flutter-devops-azure-devops-y-microsoft-appcenter-parte-2","status":"publish","type":"post","link":"https:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/flutter-devops-azure-devops-y-microsoft-appcenter-parte-2\/","title":{"rendered":"Flutter DevOps: Azure DevOps y Microsoft AppCenter (Parte 2)"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-2157\" src=\"http:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/wp-content\/uploads\/sites\/21\/2023\/07\/devops-flutter-parte-2.jpg\" alt=\"\" width=\"936\" height=\"565\" srcset=\"https:\/\/encaminablogs.wpenginepowered.com\/piensa-en-software-desarrolla-en-colores\/wp-content\/uploads\/sites\/21\/2023\/07\/devops-flutter-parte-2.jpg 936w, https:\/\/encaminablogs.wpenginepowered.com\/piensa-en-software-desarrolla-en-colores\/wp-content\/uploads\/sites\/21\/2023\/07\/devops-flutter-parte-2-300x181.jpg 300w, https:\/\/encaminablogs.wpenginepowered.com\/piensa-en-software-desarrolla-en-colores\/wp-content\/uploads\/sites\/21\/2023\/07\/devops-flutter-parte-2-768x464.jpg 768w, https:\/\/encaminablogs.wpenginepowered.com\/piensa-en-software-desarrolla-en-colores\/wp-content\/uploads\/sites\/21\/2023\/07\/devops-flutter-parte-2-610x368.jpg 610w\" sizes=\"auto, (max-width: 936px) 100vw, 936px\" \/><\/p>\n<p>En el <a href=\"https:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/flutter-devops-azure-devops-y-microsoft-appcenter-parte-1\/\" target=\"_blank\" rel=\"noopener\">primer art\u00edculo<\/a> vimos los pasos iniciales necesarios para configurar <strong>Microsoft AppCenter<\/strong> y <strong>Azure DevOps<\/strong> para compilar y desplegar aplicaciones <strong>Flutter<\/strong>.<\/p>\n<p>En esta segunda parte vamos a ver c\u00f3mo realizar la compilaci\u00f3n y el despliegue.<\/p>\n<p><!--more--><\/p>\n<h2>Compilar nuestra aplicaci\u00f3n Flutter<\/h2>\n<p>Para crear un nuevo pipeline, accederemos a los pipelines en el men\u00fa lateral izquierdo y presionaremos el bot\u00f3n azul <strong>New pipeline<\/strong> en la parte superior derecha.<\/p>\n<p>El primer paso ser\u00e1 indicar donde est\u00e1 el c\u00f3digo de nuestra aplicaci\u00f3n:<\/p>\n<p><a href=\"http:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/wp-content\/uploads\/sites\/21\/2023\/07\/devops_newpipeline1.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-2128 aligncenter\" src=\"http:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/wp-content\/uploads\/sites\/21\/2023\/07\/devops_newpipeline1.jpg\" alt=\"\" width=\"662\" height=\"433\" srcset=\"https:\/\/encaminablogs.wpenginepowered.com\/piensa-en-software-desarrolla-en-colores\/wp-content\/uploads\/sites\/21\/2023\/07\/devops_newpipeline1.jpg 662w, https:\/\/encaminablogs.wpenginepowered.com\/piensa-en-software-desarrolla-en-colores\/wp-content\/uploads\/sites\/21\/2023\/07\/devops_newpipeline1-300x196.jpg 300w, https:\/\/encaminablogs.wpenginepowered.com\/piensa-en-software-desarrolla-en-colores\/wp-content\/uploads\/sites\/21\/2023\/07\/devops_newpipeline1-610x399.jpg 610w\" sizes=\"auto, (max-width: 662px) 100vw, 662px\" \/><\/a><\/p>\n<p>Si lo tenemos en <strong>Azure DevOps<\/strong> seleccionaremos la primera opci\u00f3n <strong>Azure Repos Git<\/strong> y nos pedir\u00e1 que seleccionemos el repositorio donde est\u00e1 nuestro c\u00f3digo.<\/p>\n<p>A continuaci\u00f3n nos pedir\u00e1 que configuremos por defecto nuestro pipeline:<\/p>\n<p><a href=\"http:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/wp-content\/uploads\/sites\/21\/2023\/07\/devops_newpipeline2.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-2129 aligncenter\" src=\"http:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/wp-content\/uploads\/sites\/21\/2023\/07\/devops_newpipeline2.jpg\" alt=\"\" width=\"822\" height=\"384\" srcset=\"https:\/\/encaminablogs.wpenginepowered.com\/piensa-en-software-desarrolla-en-colores\/wp-content\/uploads\/sites\/21\/2023\/07\/devops_newpipeline2.jpg 822w, https:\/\/encaminablogs.wpenginepowered.com\/piensa-en-software-desarrolla-en-colores\/wp-content\/uploads\/sites\/21\/2023\/07\/devops_newpipeline2-300x140.jpg 300w, https:\/\/encaminablogs.wpenginepowered.com\/piensa-en-software-desarrolla-en-colores\/wp-content\/uploads\/sites\/21\/2023\/07\/devops_newpipeline2-768x359.jpg 768w, https:\/\/encaminablogs.wpenginepowered.com\/piensa-en-software-desarrolla-en-colores\/wp-content\/uploads\/sites\/21\/2023\/07\/devops_newpipeline2-610x285.jpg 610w\" sizes=\"auto, (max-width: 822px) 100vw, 822px\" \/><\/a><\/p>\n<p>En nuestro caso, seleccionaremos la opci\u00f3n <strong>Starter pipeline<\/strong> que nos crear\u00e1 un <em>pipeline<\/em> vac\u00edo para que empecemos a trabajar.<\/p>\n<p><a href=\"http:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/wp-content\/uploads\/sites\/21\/2023\/07\/devops_newpipeline3.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-2130 aligncenter\" src=\"http:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/wp-content\/uploads\/sites\/21\/2023\/07\/devops_newpipeline3.jpg\" alt=\"\" width=\"1388\" height=\"539\" srcset=\"https:\/\/encaminablogs.wpenginepowered.com\/piensa-en-software-desarrolla-en-colores\/wp-content\/uploads\/sites\/21\/2023\/07\/devops_newpipeline3.jpg 1388w, https:\/\/encaminablogs.wpenginepowered.com\/piensa-en-software-desarrolla-en-colores\/wp-content\/uploads\/sites\/21\/2023\/07\/devops_newpipeline3-300x116.jpg 300w, https:\/\/encaminablogs.wpenginepowered.com\/piensa-en-software-desarrolla-en-colores\/wp-content\/uploads\/sites\/21\/2023\/07\/devops_newpipeline3-1024x398.jpg 1024w, https:\/\/encaminablogs.wpenginepowered.com\/piensa-en-software-desarrolla-en-colores\/wp-content\/uploads\/sites\/21\/2023\/07\/devops_newpipeline3-768x298.jpg 768w, https:\/\/encaminablogs.wpenginepowered.com\/piensa-en-software-desarrolla-en-colores\/wp-content\/uploads\/sites\/21\/2023\/07\/devops_newpipeline3-610x237.jpg 610w\" sizes=\"auto, (max-width: 1388px) 100vw, 1388px\" \/><\/a><\/p>\n<p>Podemos borrar el ejemplo que nos incluye <strong>Azure DevOps<\/strong> por defecto, ya que no necesitaremos nada de esto.<\/p>\n<h3>Creaci\u00f3n de variables del pipeline<\/h3>\n<p>Antes de comenzar a escribir c\u00f3digo, vamos a crear algunas variables dentro del propio pipeline, para poder almacenar contrase\u00f1as de forma segura. En la esquina superior derecha, al lado del bot\u00f3n azul <strong>Save and run,<\/strong> tenemos un bot\u00f3n gris: <strong>Variables. <\/strong>Al pulsarlo se abre un panel lateral donde veremos las variables ya creadas y a\u00f1adir nuevas.<\/p>\n<p>Al pulsar sobre <strong>New Variable<\/strong> o el bot\u00f3n <strong>+<\/strong>,\u00a0 introducimos la clave, el valor y si la variable es secreta:<\/p>\n<p><a href=\"http:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/wp-content\/uploads\/sites\/21\/2023\/07\/devops_buildnewvariable.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-2131 aligncenter\" src=\"http:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/wp-content\/uploads\/sites\/21\/2023\/07\/devops_buildnewvariable.jpg\" alt=\"Creando una nueva variable\" width=\"459\" height=\"276\" srcset=\"https:\/\/encaminablogs.wpenginepowered.com\/piensa-en-software-desarrolla-en-colores\/wp-content\/uploads\/sites\/21\/2023\/07\/devops_buildnewvariable.jpg 459w, https:\/\/encaminablogs.wpenginepowered.com\/piensa-en-software-desarrolla-en-colores\/wp-content\/uploads\/sites\/21\/2023\/07\/devops_buildnewvariable-300x180.jpg 300w\" sizes=\"auto, (max-width: 459px) 100vw, 459px\" \/><\/a><\/p>\n<p>De esta forma podemos configurar variables secretas, como el alias y password del keystore de Android, el password de certificado de iOS o variables no secretas como el directorio del proyecto que queremos compilar.<\/p>\n<p>Para nuestro ejemplo necesitaremos definir 4 variables:<\/p>\n<ul>\n<li><strong>AndroidKSAlias:<\/strong> La marcaremos como <strong>secreta<\/strong> e introduciremos el alias del keystore que subimos a los archivos seguros.<\/li>\n<li><strong>AndroidKSPassword:<\/strong> La marcaremos como <strong>secreta<\/strong> e introduciremos la contrase\u00f1a el keystore que subimos a los archivos seguros.<\/li>\n<li><strong>IOSPassword:<\/strong> La marcaremos como <strong>secreta<\/strong> e introduciremos la contrase\u00f1a del certificado que subimos a los archivos seguros.<\/li>\n<li><strong>projectDirectory:<\/strong> Introduciremos el directorio raiz donde tenemos los archivos yml de nuestro proyecto Flutter.<\/li>\n<\/ul>\n<h3>Trigger, agente y acceso a variables<\/h3>\n<p>Ya podemos comenzar a escribir nuestro <strong>YAML<\/strong>. En primer lugar comenzaremos por definir la rama que lanzar\u00e1 el proceso de forma autom\u00e1tica al registrar alg\u00fan cambio con la opci\u00f3n <strong>trigger<\/strong>:<\/p>\n<pre class=\"brush: yaml; title: ; notranslate\" title=\"\">\r\ntrigger:\r\n    -main\r\n<\/pre>\n<p>Con esta opci\u00f3n, indicamos que queremos que se lance la compilaci\u00f3n cada vez que se realice un cambio en la rama ***main*** de nuestro repositorio.<\/p>\n<p>A continuaci\u00f3n, vamos a indicar que queremos un agente en concreto. Como queremos compilar tanto iOS como Android, necesitaremos usar una imagen de macOS que sea la m\u00e1s actualizada:<\/p>\n<pre class=\"brush: yaml; title: ; notranslate\" title=\"\">\r\npool:\r\n  vmImage: 'macos-latest'\r\n<\/pre>\n<p>Tenemos que indicarle al pipeline que queremos que use un grupo de variables (que hemos creado anteriormente):<\/p>\n<pre class=\"brush: yaml; title: ; notranslate\" title=\"\">\r\nvariables: \r\n  - group: build-test-variable-group\r\n<\/pre>\n<p>Y ya podemos comenzar con los pasos de la compilaci\u00f3n, indicando la instrucci\u00f3n <strong>steps<\/strong>:<\/p>\n<pre class=\"brush: yaml; title: ; notranslate\" title=\"\">\r\nsteps:\r\n<\/pre>\n<h3>Compilar nuestra aplicaci\u00f3n<\/h3>\n<p>A continuaci\u00f3n de <strong>steps<\/strong> empezaremos a indicar tareas con la instrucci\u00f3n <strong>task<\/strong> para cada acci\u00f3n que queramos que realice nuestro pipeline. La lista de tareas que vamos a realizar ser\u00e1:<\/p>\n<ul>\n<li>Instalar la versi\u00f3n 11 de Java (requerida por Flutter en estos momentos).<\/li>\n<li>Instalar la \u00faltima versi\u00f3n estable de Flutter.<\/li>\n<li>Compilar el proyecto Flutter.<\/li>\n<li>Firmar el apk de Android.<\/li>\n<li>Instalar el certificado de Apple en un keychain temporal.<\/li>\n<li>Instalar el profile de aprovisionamiento de Apple.<\/li>\n<li>Archivar con xCode la aplicaci\u00f3n de iOS.<\/li>\n<li>Copiar el IPA y APK al directorio de artefactos.<\/li>\n<\/ul>\n<p>Para instalar la versi\u00f3n 11 de Java usaremos la tarea <strong>JavaToolInstaller@0<\/strong> indicando la arquitectura, la versi\u00f3n y la fuente del JDK:<\/p>\n<pre class=\"brush: yaml; title: ; notranslate\" title=\"\">\r\n- task: JavaToolInstaller@0\r\n  inputs:\r\n    versionSpec: '11'\r\n    jdkArchitectureOption: x64\r\n    jdkSourceOption: PreInstalled\r\n<\/pre>\n<p>La tarea de instalar Flutter solo nos pide definir la versi\u00f3n, el canal y el modo:<\/p>\n<pre class=\"brush: yaml; title: ; notranslate\" title=\"\">\r\n- task: FlutterInstall@0\r\n  inputs:\r\n    channel: stable\r\n    version: latest\r\n    mode: auto\r\n<\/pre>\n<p>Podemos indicar una versi\u00f3n concreta si no queremos siempre estar en la \u00faltima o incluso cambiar el canal a dev u otro si lo necesitamos. En este ejemplo usamos siempre la \u00faltima versi\u00f3n en el canal estable.<\/p>\n<p>Ahora que ya tenemos todo lo necesario instalado, podemos compilar nuestra aplicaci\u00f3n flutter usando la tarea <strong>FlutterBuild@0<\/strong>:<\/p>\n<pre class=\"brush: yaml; title: ; notranslate\" title=\"\">\r\n- task: FlutterBuild@0\r\n  inputs:\r\n    target: mobile\r\n    projectDirectory: $(projectDirectory)\r\n    entryPoint: 'lib\/main.dart'\r\n    apkTargetPlatform: android-arm64\r\n    iosTargetPlatform: device\r\n    iosCodesign: false\r\n<\/pre>\n<p>Aqu\u00ed podremos definir el target de compilaci\u00f3n entre varias opciones:<\/p>\n<ul>\n<li><strong>Mobile<\/strong>: iOS y Android.<\/li>\n<li><strong>Desktop<\/strong>: Windows, Linux y macOS.<\/li>\n<li><strong>Web<\/strong>: Generar la versi\u00f3n web.<\/li>\n<li><strong>All<\/strong>: Todas las plataformas: iOS, Android, Windows, Linux, macOS, web.<\/li>\n<\/ul>\n<p>Tambi\u00e9n podremos indicar una plataforma en concreto como ipa para iOS, apk o aab para Android. A continuaci\u00f3n, indicamos el destino de compilaci\u00f3n para iOS y Android con <strong>apkTargetPlatform<\/strong> y <strong>iosTargetPlatform<\/strong> donde decidir si queremos compilar para simuladores o dispositivos. Finalmente establecemos a <em><strong>false<\/strong><\/em> la opci\u00f3n <strong>iosCodesign<\/strong> para firmar manualmente el paquete m\u00e1s adelante.<\/p>\n<h3>Firmar nuestra aplicaci\u00f3n Android<\/h3>\n<p>Una vez generados los archivos apk e ipa, podemos ir al paso de firmar ambos. Para Android vamos a usar la tarea de Azure DevOps <strong>AndroidSigning@3<\/strong>:<\/p>\n<pre class=\"brush: yaml; title: ; notranslate\" title=\"\">\r\n- task: AndroidSigning@3\r\n  inputs:\r\n    apkFiles: '**\/*.apk'\r\n    apksignerKeystoreFile: 'release.keystore'\r\n    apksignerKeystoreAlias: '$(AndroidKSAlias)'\r\n    apksignerKeystorePassword: '$(AndroidKSPassword)'\r\n    apksignerKeyPassword: '$(AndroidKSPassword)'\r\n<\/pre>\n<p>Buscamos el archivo apk que queremos firmar, indicamos el nombre del keystore que hemos guardado en la librer\u00eda anteriormente y las variables de alias y password.<\/p>\n<h3>Instalar los certificados y perfiles de Apple<\/h3>\n<p>A continuaci\u00f3n vamos a instalar el certificado y el perfil de firmado de iOS en el agente de Azure DevOps:<\/p>\n<pre class=\"brush: yaml; title: ; notranslate\" title=\"\">\r\n- task: InstallAppleCertificate@2\r\n  inputs:\r\n    certSecureFile: release.p12\r\n    certPwd: $(IOSPassword)\r\n    keychain: temp\r\n    deleteCert: true\r\n- task: InstallAppleProvisioningProfile@1\r\n  inputs:\r\n    provisioningProfileLocation: secureFiles\r\n    provProfileSecureFile: release.mobileprovision\r\n    removeProfile: true\r\n<\/pre>\n<p>Con la tarea <strong>InstallAppleCertificate@2<\/strong> instalamos el certificado que hemos subido a la librer\u00eda, indicando el password de las variables, que usaremos la keychain temporal y que al terminar se borre el certificado. Esta tarea establecer\u00e1 internamente la variable de entorno <em><strong>$(APPLE_CERTIFICATE_SIGNING_IDENTITY)<\/strong><\/em> con el valor correcto al terminar.<\/p>\n<p>A continuaci\u00f3n ejecutamos la tarea <strong>InstallAppleProvisioningProfile@1<\/strong> desde el archivo subido a la librer\u00eda e indicando que se elimine el perfil al terminar. Esta tarea establecer\u00e1 la variable de entorno <em><strong>$(APPLE_PROV_PROFILE_UUID)<\/strong><\/em> con el UUID del perfil instalado.<\/p>\n<h3>Compilar nuestra aplicaci\u00f3n iOS<\/h3>\n<p>Ya estamos listos para compilar nuestro IPA usando la tarea <strong>xcode@5<\/strong> de Azure DevOps:<\/p>\n<pre class=\"brush: yaml; title: ; notranslate\" title=\"\">\r\n- task: Xcode@5\r\n  inputs:\r\n    actions: archive\r\n    xcWorkspacePath: '**\/Runner.xcworkspace'\r\n    scheme: Runner\r\n    sdk: $(sdk)\r\n    configuration: $(configuration)\r\n    xcodeVersion: default\r\n    packageApp: true\r\n    exportOptions: auto\r\n    exportPath: 'output\/release\/iphoneos'\r\n    signingOption: manual\r\n    signingIdentity: $(APPLE_CERTIFICATE_SIGNING_IDENTITY)\r\n    provisioningProfileUuid: $(APPLE_PROV_PROFILE_UUID)\r\n    useXcpretty: false\r\n<\/pre>\n<p>En esta tarea indicamos la acci\u00f3n archive, para que genere un <em><strong>.IPA<\/strong><\/em> firmado. Como Workspace indicamos el Runner.xcworkscpace del proyecto de Flutter y le pasamos las variables de la librer\u00eda <strong>$(sdk)<\/strong> y <strong>$(configuration)<\/strong> de forma que podemos controlar con estas variables que configuraci\u00f3n y SDK queremos usar. Indicamos que queremos firmar de forma manual y los valores del certificado y perfil que deseamos usar.<\/p>\n<p>En este paso, podemos tener un error de compilaci\u00f3n indicando que no se puede firmar los PODs con el certificado que hemos indicado. Tenemos que denegar que se intenten firmar los PODs explicitamente, editando el archivo <strong><em>Podfile<\/em><\/strong> del directorio ios de Flutter, a\u00f1adiendo al final lo siguiente:<\/p>\n<pre class=\"brush: ruby; title: ; notranslate\" title=\"\">\r\npost_install do |installer|\r\n  installer.pods_project.targets.each do |target|\r\n    flutter_additional_ios_build_settings(target)\r\n    target.build_configurations.each do |config|\r\n      config.build_settings&#x5B;'EXPANDED_CODE_SIGN_IDENTITY'] = &quot;&quot;\r\n      config.build_settings&#x5B;'CODE_SIGNING_REQUIRED'] = &quot;NO&quot;\r\n      config.build_settings&#x5B;'CODE_SIGNING_ALLOWED'] = &quot;NO&quot;\r\n    end\r\n  end\r\nend\r\n<\/pre>\n<p>Con este peque\u00f1o cambio, indicamos para cada pod del proyecto que no requiere ni permite el firmado.<\/p>\n<p>En este punto ya hemos compilado y firmado, tanto nuestra aplicaci\u00f3n de iOS como de Android, y estamos listos para desplegarlas a AppCenter y distribuirlas a nuestros usuarios.<\/p>\n<h2>Desplegar nuestra aplicaci\u00f3n a AppCenter.<\/h2>\n<p>Una vez compilada nuestra aplicaci\u00f3n, el primer paso para distribuirla a AppCenter es copiar y publicar los archivos <strong><em>IPA<\/em><\/strong> y <strong><em>APK<\/em><\/strong> a un directorio desde el que luego podamos acceder con la tareas de distribuci\u00f3n de <strong>AppCenter<\/strong>.<\/p>\n<p>Para esto, en primer lugar, vamos a usar la tarea <strong>CopyFiles@2<\/strong>:<\/p>\n<pre class=\"brush: yaml; title: ; notranslate\" title=\"\">\r\n- task: CopyFiles@2\r\n  inputs:\r\n    Contents: '**\/*.ipa'\r\n    targetFolder: '$(build.artifactStagingDirectory)'\r\n\r\n- task: CopyFiles@2\r\n  inputs:\r\n    Contents: '**\/*.apk'\r\n    targetFolder: '$(build.artifactStagingDirectory)'\r\n<\/pre>\n<p>Ahora podemos usar esta ruta para acceder a los binarios en la tarea <strong>AppCenterDistibute@3. <\/strong>Necesitaremos una tarea para cada plataforma y el nombre que le dimos a la conexi\u00f3n de servicio que creeamos en el primer paso de la secci\u00f3n <strong>Preparando Azure DevOps<\/strong>:<\/p>\n<pre class=\"brush: yaml; title: ; notranslate\" title=\"\">\r\n- task: AppCenterDistribute@3\r\n  inputs:\r\n    serverEndpoint: 'AppCenter Android Connection'\r\n    appSlug: 'EQUIPO\/NOMBREAPP'\r\n    symbolsOption: Android\r\n    appFile: '$(build.artifactStagingDirectory)\/botapp\/build\/app\/outputs\/apk\/$(configuration)\/app-release.apk'\r\n    releaseNotesOption: input\r\n    releaseNotesInput: 'Pipeline automatic build'\r\n    destinationType: groups\r\n\r\n- task: AppCenterDistribute@3\r\n  inputs:\r\n    serverEndpoint: 'AppCenter iOS Connection'\r\n    appSlug: 'EQUIPO\/NOMBREAPP'\r\n    symbolsOption: Apple\r\n    appFile: '$(build.artifactStagingDirectory)\/output\/$(configuration)\/$(sdk)\/botapp.ipa'\r\n    releaseNotesOption: input\r\n    releaseNotesInput: 'Pipeline automatic build'\r\n    destinationType: groups\r\n<\/pre>\n<p>En cada tarea,\u00a0 indicaremos la conexi\u00f3n a AppCenter que queremos usar, que es el nombre que pusimos en el paso inicial de configuraci\u00f3n de Azure DevOps.<\/p>\n<p>A continuaci\u00f3n, idicamos el <strong>app slug<\/strong>, una combinaci\u00f3n entre el nombre de organizaci\u00f3n en AppCenter y el nombre de la aplicaci\u00f3n tambi\u00e9n en AppCenter, tal como sale en la url de la aplicaci\u00f3n, por ejemplo:<\/p>\n<p><strong>https:\/\/appcenter.ms\/users\/<em>yjulian<\/em>\/apps\/<em>Build-test-Android<\/em><\/strong><\/p>\n<p><strong>yjulian<\/strong> ser\u00eda el nombre de organizaci\u00f3n y <strong>Build-test-Android<\/strong> el nombre de la aplicaci\u00f3n, por lo que el <strong>appSlug<\/strong> correcto ser\u00eda <em><strong>yjulian\/Build-test-Android<\/strong><\/em>.<\/p>\n<p>La opci\u00f3n <strong>symbolsOption<\/strong> nos permite indicar si la simbolizaci\u00f3n de depuraci\u00f3n es de Android o iOS (Apple).<\/p>\n<p><strong>releaseNotesOption<\/strong> nos permite indicar si queremos las notas de la versi\u00f3n manualmente en la build (input) usando la propiedad <strong>releaseNotesInput<\/strong>. Tambi\u00e9n podemos indicarle la opci\u00f3n <strong><em>file<\/em><\/strong> y en la propiedad <strong>releaseNotesFile<\/strong> indicar un archivo donde tenemos las notas de la versi\u00f3n.<\/p>\n<p>Por \u00faltimo, la propiedad <strong>destinationType,<\/strong> la establecemos a <em><strong>groups<\/strong><\/em> para indicar que deseamos distribuir la aplicaci\u00f3n mediante <strong>AppCenter. <\/strong>Podemos indicar <strong><em>stores<\/em><\/strong> para distribuir la aplicaci\u00f3n a las tiendas usando AppCenter como intermediario.<\/p>\n<p>Si ejecutamos el pipeline, tras completar todas las tareas, tendremos nuestras aplicaciones desplegadas en AppCenter y listas para ser usadas en nuestros dispositivos de pruebas:<\/p>\n<p><a href=\"http:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/wp-content\/uploads\/sites\/21\/2023\/07\/appcenter_newrelease.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2145\" src=\"http:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/wp-content\/uploads\/sites\/21\/2023\/07\/appcenter_newrelease.png\" alt=\"Nueva release de Android desde nuestra build\" width=\"1286\" height=\"790\" srcset=\"https:\/\/encaminablogs.wpenginepowered.com\/piensa-en-software-desarrolla-en-colores\/wp-content\/uploads\/sites\/21\/2023\/07\/appcenter_newrelease.png 1286w, https:\/\/encaminablogs.wpenginepowered.com\/piensa-en-software-desarrolla-en-colores\/wp-content\/uploads\/sites\/21\/2023\/07\/appcenter_newrelease-300x184.png 300w, https:\/\/encaminablogs.wpenginepowered.com\/piensa-en-software-desarrolla-en-colores\/wp-content\/uploads\/sites\/21\/2023\/07\/appcenter_newrelease-1024x629.png 1024w, https:\/\/encaminablogs.wpenginepowered.com\/piensa-en-software-desarrolla-en-colores\/wp-content\/uploads\/sites\/21\/2023\/07\/appcenter_newrelease-768x472.png 768w, https:\/\/encaminablogs.wpenginepowered.com\/piensa-en-software-desarrolla-en-colores\/wp-content\/uploads\/sites\/21\/2023\/07\/appcenter_newrelease-610x375.png 610w\" sizes=\"auto, (max-width: 1286px) 100vw, 1286px\" \/><\/a><\/p>\n<h2>Pr\u00f3ximos pasos.<\/h2>\n<p>Ahora que somos capaces de desplegar nuestra aplicaci\u00f3n a AppCenter de forma autom\u00e1tica, \u00bfc\u00f3mo podemos ejecutar tests en dispositivos reales de forma integrada con nuestra build o test unitarios y hacer que el resultado de estos tests decida si desplegar o no las aplicaciones? Lo veremos en pr\u00f3ximos art\u00edculos.<\/p>\n<!-- AddThis Advanced Settings generic via filter on the_content --><!-- AddThis Share Buttons generic via filter on the_content --><span class=\"et_bloom_bottom_trigger\"><\/span>","protected":false},"excerpt":{"rendered":"<p>En el primer art\u00edculo vimos los pasos iniciales necesarios para configurar Microsoft AppCenter y Azure DevOps para compilar y desplegar aplicaciones Flutter. En esta segunda parte vamos a ver c\u00f3mo realizar la compilaci\u00f3n y el despliegue.<!-- AddThis Advanced Settings generic via filter on get_the_excerpt --><!-- AddThis Share Buttons generic via filter on get_the_excerpt --><\/p>\n","protected":false},"author":216,"featured_media":2157,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[122,130,4,3],"tags":[139,138,137,136],"class_list":["post-2102","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-devops","category-flutter","category-microsoft-azure","category-movilidad","tag-agile","tag-appcenter","tag-devops","tag-flutter"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v18.2.1 (Yoast SEO v27.3) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Flutter DevOps: Azure DevOps y Microsoft AppCenter (Parte 2) - Piensa en software, desarrolla en colores<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/flutter-devops-azure-devops-y-microsoft-appcenter-parte-2\/\" \/>\n<meta property=\"og:locale\" content=\"es_ES\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Flutter DevOps: Azure DevOps y Microsoft AppCenter (Parte 2)\" \/>\n<meta property=\"og:description\" content=\"En el primer art\u00edculo vimos los pasos iniciales necesarios para configurar Microsoft AppCenter y Azure DevOps para compilar y desplegar aplicaciones Flutter. En esta segunda parte vamos a ver c\u00f3mo realizar la compilaci\u00f3n y el despliegue.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/flutter-devops-azure-devops-y-microsoft-appcenter-parte-2\/\" \/>\n<meta property=\"og:site_name\" content=\"Piensa en software, desarrolla en colores\" \/>\n<meta property=\"article:published_time\" content=\"2023-08-08T13:23:32+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-08-09T08:29:55+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/wp-content\/uploads\/sites\/21\/2023\/07\/devops-flutter-parte-2.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"936\" \/>\n\t<meta property=\"og:image:height\" content=\"565\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Yeray Juli\u00e1n Ferreiro\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Escrito por\" \/>\n\t<meta name=\"twitter:data1\" content=\"Yeray Juli\u00e1n Ferreiro\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tiempo de lectura\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/blogs.encamina.com\\\/piensa-en-software-desarrolla-en-colores\\\/flutter-devops-azure-devops-y-microsoft-appcenter-parte-2\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/blogs.encamina.com\\\/piensa-en-software-desarrolla-en-colores\\\/flutter-devops-azure-devops-y-microsoft-appcenter-parte-2\\\/\"},\"author\":{\"name\":\"Yeray Juli\u00e1n Ferreiro\",\"@id\":\"https:\\\/\\\/blogs.encamina.com\\\/piensa-en-software-desarrolla-en-colores\\\/#\\\/schema\\\/person\\\/13b6621c1e9a67b558944485a3cef541\"},\"headline\":\"Flutter DevOps: Azure DevOps y Microsoft AppCenter (Parte 2)\",\"datePublished\":\"2023-08-08T13:23:32+00:00\",\"dateModified\":\"2023-08-09T08:29:55+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/blogs.encamina.com\\\/piensa-en-software-desarrolla-en-colores\\\/flutter-devops-azure-devops-y-microsoft-appcenter-parte-2\\\/\"},\"wordCount\":1855,\"commentCount\":0,\"image\":{\"@id\":\"https:\\\/\\\/blogs.encamina.com\\\/piensa-en-software-desarrolla-en-colores\\\/flutter-devops-azure-devops-y-microsoft-appcenter-parte-2\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/blogs.encamina.com\\\/piensa-en-software-desarrolla-en-colores\\\/wp-content\\\/uploads\\\/sites\\\/21\\\/2023\\\/07\\\/devops-flutter-parte-2.jpg\",\"keywords\":[\"agile\",\"appcenter\",\"devops\",\"flutter\"],\"articleSection\":[\"Devops\",\"Flutter\",\"Microsoft Azure\",\"Movilidad\"],\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/blogs.encamina.com\\\/piensa-en-software-desarrolla-en-colores\\\/flutter-devops-azure-devops-y-microsoft-appcenter-parte-2\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/blogs.encamina.com\\\/piensa-en-software-desarrolla-en-colores\\\/flutter-devops-azure-devops-y-microsoft-appcenter-parte-2\\\/\",\"url\":\"https:\\\/\\\/blogs.encamina.com\\\/piensa-en-software-desarrolla-en-colores\\\/flutter-devops-azure-devops-y-microsoft-appcenter-parte-2\\\/\",\"name\":\"Flutter DevOps: Azure DevOps y Microsoft AppCenter (Parte 2) - Piensa en software, desarrolla en colores\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/blogs.encamina.com\\\/piensa-en-software-desarrolla-en-colores\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/blogs.encamina.com\\\/piensa-en-software-desarrolla-en-colores\\\/flutter-devops-azure-devops-y-microsoft-appcenter-parte-2\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/blogs.encamina.com\\\/piensa-en-software-desarrolla-en-colores\\\/flutter-devops-azure-devops-y-microsoft-appcenter-parte-2\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/blogs.encamina.com\\\/piensa-en-software-desarrolla-en-colores\\\/wp-content\\\/uploads\\\/sites\\\/21\\\/2023\\\/07\\\/devops-flutter-parte-2.jpg\",\"datePublished\":\"2023-08-08T13:23:32+00:00\",\"dateModified\":\"2023-08-09T08:29:55+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/blogs.encamina.com\\\/piensa-en-software-desarrolla-en-colores\\\/#\\\/schema\\\/person\\\/13b6621c1e9a67b558944485a3cef541\"},\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/blogs.encamina.com\\\/piensa-en-software-desarrolla-en-colores\\\/flutter-devops-azure-devops-y-microsoft-appcenter-parte-2\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\\\/\\\/blogs.encamina.com\\\/piensa-en-software-desarrolla-en-colores\\\/flutter-devops-azure-devops-y-microsoft-appcenter-parte-2\\\/#primaryimage\",\"url\":\"https:\\\/\\\/blogs.encamina.com\\\/piensa-en-software-desarrolla-en-colores\\\/wp-content\\\/uploads\\\/sites\\\/21\\\/2023\\\/07\\\/devops-flutter-parte-2.jpg\",\"contentUrl\":\"https:\\\/\\\/blogs.encamina.com\\\/piensa-en-software-desarrolla-en-colores\\\/wp-content\\\/uploads\\\/sites\\\/21\\\/2023\\\/07\\\/devops-flutter-parte-2.jpg\",\"width\":936,\"height\":565},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/blogs.encamina.com\\\/piensa-en-software-desarrolla-en-colores\\\/#website\",\"url\":\"https:\\\/\\\/blogs.encamina.com\\\/piensa-en-software-desarrolla-en-colores\\\/\",\"name\":\"Piensa en software, desarrolla en colores\",\"description\":\"Las ventajas que te ofrece Microsoft Azure y el mundo.NET\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/blogs.encamina.com\\\/piensa-en-software-desarrolla-en-colores\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"es\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/blogs.encamina.com\\\/piensa-en-software-desarrolla-en-colores\\\/#\\\/schema\\\/person\\\/13b6621c1e9a67b558944485a3cef541\",\"name\":\"Yeray Juli\u00e1n Ferreiro\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/43aa43675361343e0c3a136afdfef5536b39d4c70ceb548df8ada523d10811a6?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/43aa43675361343e0c3a136afdfef5536b39d4c70ceb548df8ada523d10811a6?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/43aa43675361343e0c3a136afdfef5536b39d4c70ceb548df8ada523d10811a6?s=96&d=mm&r=g\",\"caption\":\"Yeray Juli\u00e1n Ferreiro\"},\"description\":\"Apasionado de los dispositivos m\u00f3viles y el desarrollo. Jugando con cacharritos desde las PDAs PSIOn Workabout y Windows PocketPC. Ex MVP de Windows Phone Dev, Windows Dev, Development Technologies y Xamarin.\",\"url\":\"https:\\\/\\\/blogs.encamina.com\\\/piensa-en-software-desarrolla-en-colores\\\/author\\\/yjulian\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Flutter DevOps: Azure DevOps y Microsoft AppCenter (Parte 2) - Piensa en software, desarrolla en colores","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/flutter-devops-azure-devops-y-microsoft-appcenter-parte-2\/","og_locale":"es_ES","og_type":"article","og_title":"Flutter DevOps: Azure DevOps y Microsoft AppCenter (Parte 2)","og_description":"En el primer art\u00edculo vimos los pasos iniciales necesarios para configurar Microsoft AppCenter y Azure DevOps para compilar y desplegar aplicaciones Flutter. En esta segunda parte vamos a ver c\u00f3mo realizar la compilaci\u00f3n y el despliegue.","og_url":"https:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/flutter-devops-azure-devops-y-microsoft-appcenter-parte-2\/","og_site_name":"Piensa en software, desarrolla en colores","article_published_time":"2023-08-08T13:23:32+00:00","article_modified_time":"2023-08-09T08:29:55+00:00","og_image":[{"width":936,"height":565,"url":"http:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/wp-content\/uploads\/sites\/21\/2023\/07\/devops-flutter-parte-2.jpg","type":"image\/jpeg"}],"author":"Yeray Juli\u00e1n Ferreiro","twitter_card":"summary_large_image","twitter_misc":{"Escrito por":"Yeray Juli\u00e1n Ferreiro","Tiempo de lectura":"9 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/flutter-devops-azure-devops-y-microsoft-appcenter-parte-2\/#article","isPartOf":{"@id":"https:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/flutter-devops-azure-devops-y-microsoft-appcenter-parte-2\/"},"author":{"name":"Yeray Juli\u00e1n Ferreiro","@id":"https:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/#\/schema\/person\/13b6621c1e9a67b558944485a3cef541"},"headline":"Flutter DevOps: Azure DevOps y Microsoft AppCenter (Parte 2)","datePublished":"2023-08-08T13:23:32+00:00","dateModified":"2023-08-09T08:29:55+00:00","mainEntityOfPage":{"@id":"https:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/flutter-devops-azure-devops-y-microsoft-appcenter-parte-2\/"},"wordCount":1855,"commentCount":0,"image":{"@id":"https:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/flutter-devops-azure-devops-y-microsoft-appcenter-parte-2\/#primaryimage"},"thumbnailUrl":"https:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/wp-content\/uploads\/sites\/21\/2023\/07\/devops-flutter-parte-2.jpg","keywords":["agile","appcenter","devops","flutter"],"articleSection":["Devops","Flutter","Microsoft Azure","Movilidad"],"inLanguage":"es","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/flutter-devops-azure-devops-y-microsoft-appcenter-parte-2\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/flutter-devops-azure-devops-y-microsoft-appcenter-parte-2\/","url":"https:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/flutter-devops-azure-devops-y-microsoft-appcenter-parte-2\/","name":"Flutter DevOps: Azure DevOps y Microsoft AppCenter (Parte 2) - Piensa en software, desarrolla en colores","isPartOf":{"@id":"https:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/#website"},"primaryImageOfPage":{"@id":"https:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/flutter-devops-azure-devops-y-microsoft-appcenter-parte-2\/#primaryimage"},"image":{"@id":"https:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/flutter-devops-azure-devops-y-microsoft-appcenter-parte-2\/#primaryimage"},"thumbnailUrl":"https:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/wp-content\/uploads\/sites\/21\/2023\/07\/devops-flutter-parte-2.jpg","datePublished":"2023-08-08T13:23:32+00:00","dateModified":"2023-08-09T08:29:55+00:00","author":{"@id":"https:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/#\/schema\/person\/13b6621c1e9a67b558944485a3cef541"},"inLanguage":"es","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/flutter-devops-azure-devops-y-microsoft-appcenter-parte-2\/"]}]},{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/flutter-devops-azure-devops-y-microsoft-appcenter-parte-2\/#primaryimage","url":"https:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/wp-content\/uploads\/sites\/21\/2023\/07\/devops-flutter-parte-2.jpg","contentUrl":"https:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/wp-content\/uploads\/sites\/21\/2023\/07\/devops-flutter-parte-2.jpg","width":936,"height":565},{"@type":"WebSite","@id":"https:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/#website","url":"https:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/","name":"Piensa en software, desarrolla en colores","description":"Las ventajas que te ofrece Microsoft Azure y el mundo.NET","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"es"},{"@type":"Person","@id":"https:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/#\/schema\/person\/13b6621c1e9a67b558944485a3cef541","name":"Yeray Juli\u00e1n Ferreiro","image":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/secure.gravatar.com\/avatar\/43aa43675361343e0c3a136afdfef5536b39d4c70ceb548df8ada523d10811a6?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/43aa43675361343e0c3a136afdfef5536b39d4c70ceb548df8ada523d10811a6?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/43aa43675361343e0c3a136afdfef5536b39d4c70ceb548df8ada523d10811a6?s=96&d=mm&r=g","caption":"Yeray Juli\u00e1n Ferreiro"},"description":"Apasionado de los dispositivos m\u00f3viles y el desarrollo. Jugando con cacharritos desde las PDAs PSIOn Workabout y Windows PocketPC. Ex MVP de Windows Phone Dev, Windows Dev, Development Technologies y Xamarin.","url":"https:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/author\/yjulian\/"}]}},"_links":{"self":[{"href":"https:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/wp-json\/wp\/v2\/posts\/2102","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/wp-json\/wp\/v2\/users\/216"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/wp-json\/wp\/v2\/comments?post=2102"}],"version-history":[{"count":0,"href":"https:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/wp-json\/wp\/v2\/posts\/2102\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/wp-json\/wp\/v2\/media\/2157"}],"wp:attachment":[{"href":"https:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/wp-json\/wp\/v2\/media?parent=2102"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/wp-json\/wp\/v2\/categories?post=2102"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.encamina.com\/piensa-en-software-desarrolla-en-colores\/wp-json\/wp\/v2\/tags?post=2102"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}