Autor: harcalion

Empaquetando WorldWide Telescope y compartiendo el soporte para ficheros FITS de Herschel

Aquí no hay nada que retomar, porque ya en su momento corregí el mal uso que se hacía de ficheros FITS (por ejemplo los de Herschel) que tenían una cabecera auxiliar (extension header) en vez de tener todos los metadatos en la cabecera primaria.

Después de insistir mucho para que se aceptase el Pull request en GitHub (https://github.com/WorldWideTelescope/wwt-windows-client/pull/83), resulta que la American Astronomical Society (AAS) no piensa lanzar ni una sola versión más de la versión de escritorio, así que nadie podrá disfrutar de mi arreglo. Me propongo enmendar este problema y permitir que todo el mundo pueda  crear capas y composiciones con ficheros FITS de Herschel y los datos que ya están presentes en WWT.

En la imagen de abajo, WWT en modo depuración en mi máquina con un fichero FITS de Herschel .

WWT_1

Las cabeceras del fichero FITS son las siguientes:

Principal:

SIMPLE = T / Java FITS: Mon Jan 18 10:18:51 CET 2016 
BITPIX = 32 
NAXIS = 0 / Dimensionality 
EXTEND = T / May contain datasets 
TIMESYS = 'UTC ' / All dates are in UTC time 
LONGSTRN= 'OGIP 1.0' / The OGIP long string convention may be used. 
COMMENT This FITS file may contain long string keyword values that are 
COMMENT continued over multiple keywords. This convention uses the '&' 
COMMENT character at the end of a string which is then continued 
COMMENT on subsequent keywords whose name = 'CONTINUE'. 
---------------Herschel FITS Data Generator--------------- 
This product is generated by Herschel software. 
HCSS____= 5 / HCSS Fits Product Version 
-------------- Herschel Structure Data-------------------- 
Following fields are private to the structure of the 
Java object this HDU is representing. 
CLASS___= 'herschel.ia.dataset.image.RgbSimpleImage' / java representation 
INFO____= 'Browse Product' 
-------------- Herschel Parameter Data-------------------- 
All actual parameter names are converted to FITS compliant 
conventions. Note that the HIERARCH comments contain the 
appropriate key mapping 
TYPE = 'BROWSE ' / Product Type Identification 
CREATOR = 'SPG v14.0.1' / Generator of this product 
DATE = '2016-01-12T21:08:09.152000' / Creation date of this product 
DESC = 'Browse Product' / Name of this product 
INSTRUME= 'SPIRE ' / Instrument attached to this product 
MODELNAM= 'FLIGHT ' / Model name attached to this product 
DATE-OBS= '2009-06-25T01:55:39.000000' / Start date of this product 
DATE_OBS= '2009-06-25T01:55:39.000000' / Start date of this product 
DATE-END= '2009-06-25T02:57:23.000000' / End date of this product 
FORMATV = '1.0 ' / Version of product format 
TELESCOP= 'Herschel Space Observatory' / Name of telescope 
OBJECT = 'M66 ' / Target name 
OBSERVER= 'copspire' / Observer name 
PROPOSAL= 'Calibration_copspire_15' / Proposal name 
OBS_ID = 1342179029 / [] Observation identifier 
ODNUMBER= 42 / [] Operational day number 
AOT = 'Photometer' / AOT Identifier 
AOR = 'Calibration_H_COP_SJL_OD42_01_1-SPhoto-20x20rep4_AB&' 
CONTINUE '' / & 
COMMENT AOR Label as entered in HSpot 
CUSMODE = 'SpirePhotoLargeScan' / CUS observation mode 
INSTMODE= 'POF5 ' / Instrument Mode 
OBS_MODE= 'Large Map' / Observation mode name 
POINTMOD= 'Cross_scan' / Pointing mode 
MISSIONC= 'MC_H11_P7_S10_COP' / Mission configuration 
EQUINOX = 2000.0 / [] Equinox of celestial coordinate system 
RADESYS = 'ICRS ' / Coordinate reference frame for the RA and DEC 
RA = 170.06281229854167 / [deg] Actual Right Ascension of pointing 
RA_NOM = 170.062625 / [deg] Requested Right Ascension of pointing 
DEC = 12.993779663437786 / [deg] Actual Declination of pointing 
DEC_NOM = 12.991555555555555 / [deg] Requested Declination of pointing 
POSANGLE= 290.6511889657665 / [deg] Spacecraft pointing Position angle 
PMRA = 0.0 / [arcsec a-1] Target's proper motion RA (arcs& 
COMMENT ec/yr) as given by the observer 
PMDEC = 0.0 / [arcsec a-1] Target's proper motion Dec (arc& 
COMMENT sec/yr) as given by the observer 
ORIGIN = 'Herschel Science Centre' / Site that created the product 
HIERARCH key.TYPE='type' 
HIERARCH key.CREATOR='creator' 
HIERARCH key.DATE='creationDate' 
HIERARCH key.DESC='description' 
HIERARCH key.INSTRUME='instrument' 
HIERARCH key.MODELNAM='modelName' 
HIERARCH key.DATE-OBS='startDate' 
HIERARCH key.DATE-END='endDate' 
HIERARCH key.FORMATV='formatVersion' 
HIERARCH key.TELESCOP='telescope' 
HIERARCH key.OBJECT='object' 
HIERARCH key.OBSERVER='observer' 
HIERARCH key.PROPOSAL='proposal' 
HIERARCH key.OBS_ID='obsid' 
HIERARCH key.ODNUMBER='odNumber' 
HIERARCH key.AOT='aot' 
HIERARCH key.AOR='aorLabel' 
HIERARCH key.CUSMODE='cusMode' 
HIERARCH key.INSTMODE='instMode' 
HIERARCH key.OBS_MODE='obsMode' 
HIERARCH key.POINTMOD='pointingMode' 
HIERARCH key.MISSIONC='missionConfig' 
HIERARCH key.EQUINOX='equinox' 
HIERARCH key.RADESYS='raDeSys' 
HIERARCH key.RA='ra' 
HIERARCH key.RA_NOM='raNominal' 
HIERARCH key.DEC='dec' 
HIERARCH key.DEC_NOM='decNominal' 
HIERARCH key.POSANGLE='posAngle' 
HIERARCH key.PMRA='pmRA' 
HIERARCH key.PMDEC='pmDEC' 
HIERARCH key.ORIGIN='origin' 
-----------------Dataset Children------------------------- 
Below you will find all HDU locations that are children of 
this composite dataset. 
DSETS___= 3 / Number of datasets 
DS_0 = 1 / HDU of Child Dataset 
DS_1 = 2 / HDU of Child Dataset 
DS_2 = 3 / HDU of Child Dataset END

Nos fijamos en el atributo OBJECT, que nos indica que el objeto es la galaxia M66. Todos estos valores, por lo general, no los usa ninguno de los programas que saben leer FITS “estándar”, los valores “útiles” están en la cabecera auxiliar (XTENSION):

XTENSION= 'IMAGE ' / Java FITS: Mon Jan 18 10:18:51 CET 2016
BITPIX = 8
NAXIS = 2 / Dimensionality
NAXIS1 = 453
NAXIS2 = 478
PCOUNT = 0 / No extra parameters
GCOUNT = 1 / One group
LONGSTRN= 'OGIP 1.0' / The OGIP long string convention may be used.
COMMENT This FITS file may contain long string keyword values that are
COMMENT continued over multiple keywords. This convention uses the '&'
COMMENT character at the end of a string which is then continued
COMMENT on subsequent keywords whose name = 'CONTINUE'.
-------------- Herschel Structure Data--------------------
Following fields are private to the structure of the
Java object this HDU is representing.
EXTNAME = 'red ' / name of this HDU
CLASS___= 'herschel.ia.dataset.ArrayDataset' / java representation
DATA____= 'herschel.ia.numeric.Byte2d' / java Data
-------------- Herschel Parameter Data--------------------
All actual parameter names are converted to FITS compliant
conventions. Note that the HIERARCH comments contain the
appropriate key mapping
CRPIX1 = 227.0 / [] WCS: Reference pixel position axis 1, uni&
COMMENT t=Scalar
CRPIX2 = 240.0 / [] WCS: Reference pixel position axis 2, uni&
COMMENT t=Scalar
CRVAL1 = 170.06281229854167 / [] WCS: First coordinate of reference pixel
CRVAL2 = 12.993779663437786 / [] WCS: Second coordinate of reference pixel
CDELT1 = -0.001666666666667 / [] WCS: Pixel scale axis 1, unit=Angle
CDELT2 = 0.001666666666667 / [] WCS: Pixel scale axis 2, unit=Angle
CTYPE1 = 'RA---TAN' / WCS: Projection type axis 1, default="LINEAR"
CTYPE2 = 'DEC--TAN' / WCS: Projection type axis 2, default="LINEAR"
EQUINOX = 2000.0 / [] WCS: Equinox, unit=Duration
CROTA2 = 0.0 / [] The Rotation angle
HIERARCH key.CRPIX1='crpix1'
HIERARCH key.CRPIX2='crpix2'
HIERARCH key.CRVAL1='crval1'
HIERARCH key.CRVAL2='crval2'
HIERARCH key.CDELT1='cdelt1'
HIERARCH key.CDELT2='cdelt2'
HIERARCH key.CTYPE1='ctype1'
HIERARCH key.CTYPE2='ctype2'
HIERARCH key.EQUINOX='equinox'
HIERARCH key.CROTA2='crota2'

Estos son los que permiten dibujar la imagen. Hablando de imágenes, una para aliviar tantos bloques ASCII:

WWT_2

Comprobamos que la imagen se dibuja en el lugar correcto del cielo, y la retícula nos da la información de los datos de Spitzer que hay justo debajo en la estructura de capas de WWT. Es, después de todo, la galaxia M66.

Después de la teoría viene la práctica, y como prometí que íbamos a empaquetar el software para que todo el mundo pudiese realizar esta composición, vamos a hacerlo utilizando el sistema de distribución que viene incluido en la solución que está en GitHub (https://github.com/WorldWideTelescope/wwt-windows-client).

Para ello, lo primero que hay que hacer es descargar una extensión de Visual Studio, porque la versión 2017 ya no lo incluye dentro de las características estándar. Esta extensión se encuentra en:

https://marketplace.visualstudio.com/items?itemName=VisualStudioProductTeam.MicrosoftVisualStudio2017InstallerProjects

Una vez instalada, el proyecto WorldWide Telescope es accesible y se pueden realizar los siguientes pasos:

  • Como indica el ReadMe.txt dentro del proyecto Setup1, descomprimir el fichero datafiles.zip.
  • Establecer la configuración en “Release”.
  • Compilar el proyecto Worldwide Telescope.

Ya tenemos un ejecutable de conveniencia y un instalador MSI para distribuir la aplicación:

WWT_4

Esta versión del instalador la puedes encontrar en mi OneDrive:

https://1drv.ms/u/s!AoCZ8E1PIRqs4thFkZWBy7o-40i8GA

Si no queremos complicarnos con tipos de proyecto obsoletos y extensiones, también se puede crear muy fácilmente un instalador de tipo ClickOnce (para entendernos, como que el usa Google Chrome):

  • Botón derecho sobre la solución WWTExplorer.
  • Publicar (o Publish).
  • Escoger una ubicación en el disco duro local.
  • Instalación desde CD-ROM o DVD-ROM.
  • La aplicación no buscará actualizaciones.
  • Pulsar en Finalizar (Finish).
WWT_3

Puedes encontrar la versión ClickOnce del instalador comprimida en OneDrive:

https://1drv.ms/u/s!AoCZ8E1PIRqs4thEE5UboqZVuIgkOg

 

Anuncios

Retomando Cableman (I – Android)

Hoy actualizando las apps de la tablet (una obsoleta Nexus 10, gracias Google), he visto que tenía instalada la app de CableMan para Android, y funcionaba. Eso significa que el despliegue en un dispositivo de verdad funciona, a diferencia del emulador de Android, donde se produce un error al ejecutar la aplicación.

EDIT.: He encontrado un pantallazo que demuestra que también funcionó en emulador en algún momento del pasado:

cableman

La situación actual es Visual Studio 15.7.3, la siguiente lista de paquetes:

Id Versions ProjectName 
-- -------- ----------- 
NETStandard.Library {2.0.3} CableMan.UWP 
UrhoSharp.Forms {1.8.93} CableMan.UWP 
Xamarin.Forms {3.0.0.482510} CableMan.UWP 
Microsoft.NETCore.Platforms {2.0.2} CableMan.iOS 
NETStandard.Library {2.0.3} CableMan.iOS 
UrhoSharp.Forms {1.8.93} CableMan.iOS 
Xamarin.Forms {3.0.0.482510} CableMan.iOS 
Microsoft.NETCore.Platforms {2.0.2} CableMan.Android 
NETStandard.Library {2.0.3} CableMan.Android 
UrhoSharp.Forms {1.8.93} CableMan.Android 
Xamarin.Android.Arch.Core.Common {1.0.0} CableMan.Android 
Xamarin.Android.Arch.Lifecycle.C... {1.0.3} CableMan.Android 
Xamarin.Android.Arch.Lifecycle.R... {1.0.3} CableMan.Android 
Xamarin.Android.Support.Animated... {27.0.2} CableMan.Android 
Xamarin.Android.Support.Annotations {27.0.2} CableMan.Android 
Xamarin.Android.Support.Compat {27.0.2} CableMan.Android 
Xamarin.Android.Support.Core.UI {27.0.2} CableMan.Android 
Xamarin.Android.Support.Core.Utils {27.0.2} CableMan.Android 
Xamarin.Android.Support.Design {27.0.2} CableMan.Android 
Xamarin.Android.Support.Fragment {27.0.2} CableMan.Android 
Xamarin.Android.Support.Media.Co... {27.0.2} CableMan.Android 
Xamarin.Android.Support.Transition {27.0.2} CableMan.Android 
Xamarin.Android.Support.v4 {27.0.2} CableMan.Android 
Xamarin.Android.Support.v7.AppCo... {27.0.2} CableMan.Android 
Xamarin.Android.Support.v7.CardView {27.0.2} CableMan.Android 
Xamarin.Android.Support.v7.Media... {27.0.2} CableMan.Android 
Xamarin.Android.Support.v7.Palette {27.0.2} CableMan.Android 
Xamarin.Android.Support.v7.Recyc... {27.0.2} CableMan.Android 
Xamarin.Android.Support.Vector.D... {27.0.2} CableMan.Android 
Xamarin.Forms {3.0.0.482510} CableMan.Android

Otros datos de configuración son: Java 1.8.0_172 y una imagen de Android x86 API 27 (Oreo 8.1).

Veamos si se puede actualizar algo para cambiar el comportamiento u obtener un mensaje de error más claro. En la consola de NuGet aparecen 21 actualizaciones, así que adelante con todas. Hizo falta reiniciar Visual Studio para actualizar algunos paquetes, algo que nunca deja de asombrarme por lo cutre que resulta. Después del reinicio, la lista de paquetes es esta:

Id Versions ProjectName 
-- -------- ----------- 
NETStandard.Library {2.0.3} CableMan.UWP 
UrhoSharp.Forms {1.8.93} CableMan.UWP 
Xamarin.Forms {3.0.0.561731} CableMan.UWP 
Microsoft.NETCore.Platforms {2.1.0} CableMan.iOS 
NETStandard.Library {2.0.3} CableMan.iOS 
UrhoSharp.Forms {1.8.93} CableMan.iOS 
Xamarin.Forms {3.0.0.561731} CableMan.iOS 
Microsoft.NETCore.Platforms {2.1.0} CableMan.Android 
NETStandard.Library {2.0.3} CableMan.Android 
UrhoSharp.Forms {1.8.93} CableMan.Android 
Xamarin.Android.Arch.Core.Common {1.0.0.1} CableMan.Android 
Xamarin.Android.Arch.Lifecycle.C... {1.0.3.1} CableMan.Android 
Xamarin.Android.Arch.Lifecycle.R... {1.0.3.1} CableMan.Android 
Xamarin.Android.Support.Animated... {27.0.2.1} CableMan.Android 
Xamarin.Android.Support.Annotations {27.0.2.1} CableMan.Android 
Xamarin.Android.Support.Compat {27.0.2.1} CableMan.Android 
Xamarin.Android.Support.Core.UI {27.0.2.1} CableMan.Android 
Xamarin.Android.Support.Core.Utils {27.0.2.1} CableMan.Android 
Xamarin.Android.Support.Design {27.0.2.1} CableMan.Android 
Xamarin.Android.Support.Fragment {27.0.2.1} CableMan.Android 
Xamarin.Android.Support.Media.Co... {27.0.2.1} CableMan.Android 
Xamarin.Android.Support.Transition {27.0.2.1} CableMan.Android 
Xamarin.Android.Support.v4 {27.0.2.1} CableMan.Android 
Xamarin.Android.Support.v7.AppCo... {27.0.2.1} CableMan.Android 
Xamarin.Android.Support.v7.CardView {27.0.2.1} CableMan.Android 
Xamarin.Android.Support.v7.Media... {27.0.2.1} CableMan.Android 
Xamarin.Android.Support.v7.Palette {27.0.2.1} CableMan.Android 
Xamarin.Android.Support.v7.Recyc... {27.0.2.1} CableMan.Android 
Xamarin.Android.Support.Vector.D... {27.0.2.1} CableMan.Android 
Xamarin.Forms {3.0.0.561731} CableMan.Android

Todavía había un aviso en el panel del Package Manager avisando que había paquetes pendientes de desinstalar y que si reiniciaba Visual Studio otra vez. Me resistí a esos cantos de sirena y miré si había actualizaciones del SDK de Android o de las imágenes para el emulador. No era el caso, otra de las piezas de configuración era Android SDK Platform API 27 v3.

Compilando y desplegando de nuevo la aplicación volvió a morir sin errores. Para el próximo artículo:

  • Intentar resolver el error de conexión a logcat: Android application is debugging.
    Couldn’t connect to logcat, GetProcessId returned: 0
  • Desplegar de nuevo a dispositivo físico Android para saber si es un escenario que todavía funciona.
  • Probar la versión UWP.

Retomando First (I)

En este caso, como desarrollé este proyecto en NetBeans, no se me ocurrió otra cosa que continuarlo usando la Beta de NetBeans 9, ahora bajo el control de la Apache Software Foundation, pero con la misma interfaz amigable de siempre:

First1.png

Una vez configurado el proyecto como un proyecto Maven (ya definí todas las dependencias en algún momento del pasado), me encuentro el error que ya me temía, las bibliotecas relacionadas con Java Advanced Imaging (JAI) han desaparecido de los repositorios públicos de Maven:

Failed to execute goal on project FirstMvn: Could not resolve dependencies for project es.upm.fi.gtd.first:FirstMvn:jar:1.0-SNAPSHOT: The following artifacts could not be resolved: com.sun.media:jai_imageio:jar:1.1, javax.media:jai_core:jar:1.1.3: Could not find artifact com.sun.media:jai_imageio:jar:1.1 in central (https://repo.maven.apache.org/maven2), try downloading from https://jai-imageio.dev.java.net/binary-builds.html -> [Help 1]

La parte buena del mensaje de error es que te da la solución de descargarlas de https://jai-imageio.dev.java.net/binary-builds.html, la parte mala es que esa web ya no existe. Menos mal que en la página de Oracle están archivados los binarios en http://www.oracle.com/technetwork/java/javasebusiness/downloads/java-archive-downloads-java-client-419417.html y, por una vez en la vida, no cobran por descargarlos.

Sin embargo, la utilización de estos ficheros significa seguir dependiendo de los aceleradores nativos JNI escritos en C que utilizaba Sun. Para evitarlo, hay una reimplementación de esta biblioteca en GitHub que es puro Java: https://github.com/stain/jai-imageio-core

La única pega de utilizarla es que el espacio de nombres es diferente y hay que cambiarlo:

Por ejemplo, un import original de First era:

import com.sun.media.imageio.plugins.tiff.GeoTIFFTagSet;

En la nueva biblioteca será:

import com.github.jaiimageio.plugins.tiff.GeoTIFFTagSet;

Compilando después de hacer este cambio, el compilador se queja de otro espacio de nombres de JAI (javax.media.jai):

Caused by: java.lang.RuntimeException: Uncompilable source code - package javax.media.jai does not exist

En mi código utilizo directamente varias clases de este espacio de nombres, que no existe en la reimplementación de la biblioteca en GitHub.

import javax.media.jai.BorderExtender;
import javax.media.jai.InterpolationBicubic;
import javax.media.jai.InterpolationBicubic2;
import javax.media.jai.InterpolationBilinear;
import javax.media.jai.InterpolationNearest;

import javax.media.jai.JAI;
import javax.media.jai.ParameterBlockJAI;
import javax.media.jai.PlanarImage;
import javax.media.jai.RasterFactory;
import javax.media.jai.TiledImage;

En siguientes entradas veremos cómo sustituir estas clases o eliminar su uso si fuera necesario. Ahora lo primero es recodificar como UTF-8 correcto todo el código fuente y esa no es tarea sobre la que escribir un artículo, se hace y punto.

Retomando Herschel Quick Look (WinObjC)

El estado de este proyecto es el más frustrante de todos, ya que cuando la runtime de WinObjC se distribuía como un binario comprimido, llegó a ejecutar e incluso funcionar como UWP. Desde que se distribuye como un paquete (principios de 2017 según el registro de cambios del README.md en GitHub) nunca ha llegado a funcionar y sólo muestra una pantalla en blanco si hay mucha suerte.

Una de estas veces que fui a continuar trabajando en este proyecto me encontré el siguiente error al cargar el proyecto principal:

C:\Users\teles\OneDrive\Prog\Herschel Quick Look Modern\Herschel Quick Look\Herschel Quick Look.vsimporter\Herschel Quick Look-WinStore10\Herschel Quick Look.vcxproj : error : Cannot load project with duplicated project items: ..\..\Herschel_Quick_Look_Prefix.pch is included as 'ClInclude' and as 'ClInclude' item types.

Para resolver este problema hay que:

Editar el fichero vcxproj del proyecto principal. Comentar la línea:

<!--ClInclude Include="..\..\Herschel_Quick_Look_Prefix.pch" /-->

Y recargar el proyecto. El error habrá desaparecido por completo.

También, mucho cuidado al usar WinObjC (que depende de Clang por detrás) con el código en una carpeta compartida de OneDrive. Al recompilar la solución, aparecerán un gran número de errores de este tipo:

Severity Code Description Project File Line Suppression State
Error no such file or directory: 'C:\Users\teles\OneDrive\Prog\Herschel Quick Look Modern\Herschel Quick Look\Classes\qv\archive\xmlparser\HsaXmlHandler.m' Herschel Quick Look (Herschel Quick Look\Herschel Quick Look) C:\Users\teles\OneDrive\Prog\Herschel Quick Look Modern\Herschel Quick Look\Herschel Quick Look.vsimporter\Herschel Quick Look-WinStore10\clang.exe 1 
Error no input files Herschel Quick Look (Herschel Quick Look\Herschel Quick Look) C:\Users\teles\OneDrive\Prog\Herschel Quick Look Modern\Herschel Quick Look\Herschel Quick Look.vsimporter\Herschel Quick Look-WinStore10\clang.exe 1

No sé si es un error o una feature de Clang, pero desde luego falla todo el proceso de compilación. Con el mismo código copiado a una carpeta local, estos errores desaparecen.

Retomando Dark Influence (II – Android)

Era el turno de la aplicación de Android, que daba un curioso mensaje sobre que la keystore en formato JKS ya no se recomendaba y que era aconsejable migrarla a PKCS12. Como no quería hacerlo de modo manual, empecé a seguir el tutorial que aparece aquí para preparar la app para su publicación:

https://docs.microsoft.com/en-us/xamarin/android/deploy-test/release-prep/?tabs=vswin

Lo primero que encontré fue un bug de Xamarin, en el que aunque establezcas el icono de la aplicación aquí:

DarkInfluence2_1

Seguirá devolviendo un error de compilación:

Severity Code Description Project File Line Suppression State
Error No resource found that matches the given name (at 'icon' with value '@mipmap/Icon'). DarkInfluence.Droid C:\Users\teles\Source\Workspaces\VampirOnline\Droid\obj\Release\android\manifest\AndroidManifest.xml 6

Que se resuelve editando manualmente el fichero AssemblyInfo.cs y añadiendo la siguiente línea:

[assembly: Application(Icon = "@mipmap/icon")]

Por supuesto si es ese icono el que queremos configurar como icono de la aplicación.

Una vez archivada la app, podemos firmarla mediante un asistente que generará una keystore apropiada. Para ello hay que pulsar en Distribuir (Distribute … en la imagen).

DarkInfluence2_2

Durante el asistente hay que seguir el tutorial enlazado al principio de este artículo y crear una nueva keystore. Una vez realizado esto podemos seguir intentando desplegar la app en el emulador de Android. El error sobre la migración de keystore ya no aparece pero un nuevo problema se presenta:

1>Build succeeded.
1>Unexpected install output: Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES: Failed to collect certificates from /data/app/vmdl840508115.tmp/base.apk: Attempt to get length of null array]
1>
1> at Mono.AndroidTools.Internal.AdbOutputParsing.CheckInstallSuccess(String output, String packageName) in E:\A\_work\25\s\External\androidtools\Mono.AndroidTools\Internal\AdbOutputParsing.cs:line 337
1> at Mono.AndroidTools.AndroidDevice.<>c__DisplayClass94_0.<InstallPackage>b__0(Task`1 t) in E:\A\_work\25\s\External\androidtools\Mono.AndroidTools\AndroidDevice.cs:line 746
1> at System.Threading.Tasks.ContinuationTaskFromResultTask`1.InnerInvoke()
1> at System.Threading.Tasks.Task.Execute()
1>
1>Deploy failed

Al parecer está causado por APK antiguos firmados con otro certificado. Visual Studio/Xamarin no los borrará y recreará, lo que provocará el error:

Output file 'bin\Debug\\DarkInfluence.Droid-armeabi-v7a-Signed.apk' exists

Parecía algo que se podía solucionar borrando manualmente los de todas las arquitecturas que haya. Seguía fallando con el mismo error INSTALL_PARSE_FAILED_NO_CERTIFICATES. Sospechando un bug en Xamarin, hice una búsqueda en Internet, donde encontré un informe de error de Visual Studio que se ajustaba a este mensaje:

https://developercommunity.visualstudio.com/content/problem/209865/cannot-deploy-xamarin-forms-app-error-install-pars.html

Parece que si versiones más modernas de Java (como 9 o 10) están instaladas como en mi caso, es necesario desinstalarlas para que el mecanismo de firmado de APK, basado en Java, funcione correctamente. Esto en realidad es un bug de Xamarin o el SDK de Android ya que la versión de Java seleccionada en Visual Studio es 1.8.0_172 y algún ejecutable se estaba localizando en el PATH.

Continuará…

Retomando Dark Influence (I)

Animado por el hecho de que Visual Studio 2017 se actualizaba a la versión 15.7.2, le di una segunda oportunidad al proyecto. De manera inesperada, simplemente con actualizar, el proyecto UWP volvía a funcionar, sin mostrar el error debido a dependencias de .NET Standard.

En otro ordenador donde tengo también configurada la conexión con TFS, y que está menos actualizado, los proyectos inicialmente no estaban disponibles, siendo necesaria la instalación de algunos SDKs de Windows bastante antiguos. Para ello sólo hay que pulsar con el botón derecho en los proyectos UWP que aparecen como “(no disponible)” y seleccionar “Descargar actualización”. Ojo, puede que estuvieran ya instalados, pero tuve que moverlos a otra unidad hace un par de semanas porque C: se estaba quedando sin espacio y quizá el instalador de Visual Studio no se fiaba de la integridad de la instalación de los SDKs.

Una vez hecho esto, los proyectos UWP ya aparecen cargados, pero los proyectos Xamarin de Android e iOS siguen siendo “incompatibles”.

DarkInfluence1

En esta ocasión, simplemente con hacer click derecho y seleccionar “Volver a cargar el proyecto”, el proyecto pasa a cargarse y estar disponible.

Ahora llega la prueba de fuego, ejecutar la versión UWP. Como dispositivo de despliegue selecciono “Equipo local”.

DarkInfluence2

La aplicación UWP se ejecuta correctamente y muestra su (sencillísima) interfaz de usuario:

DarkInfluence3

Todo esto simplemente actualizando Visual Studio. La solución y los proyectos relacionados no se han modificado ni una sola línea. Para terminar compruebo que los paquetes Nuget están actualizados. No es así, hay 7 actualizaciones que aplico con cierto miedo.

PM> Get-Package -updates

Id Versions Description ProjectName 
-- -------- ----------- ----------- 
Microsoft.NETCore.UniversalWindo... {6.1.4} Provides a set of packages that can be use... DarkInfluence.Windows.Test 
Microsoft.ApplicationInsights {2.6.4} Application Insights Base API. This packag... DarkInfluence.Windows 
Microsoft.ApplicationInsights.Pe... {1.2.3} This channel provides a peristant channel ... DarkInfluence.Windows 
Microsoft.ApplicationInsights.Wi... {1.1.1} Application Insights for .Net Windows appl... DarkInfluence.Windows 
Microsoft.NETCore.UniversalWindo... {6.1.4} Provides a set of packages that can be use... DarkInfluence.Windows 
NUnit {3.10.1} NUnit is a unit-testing framework for all ... DarkInfluence.UITests 
Xamarin.UITest {2.2.4} UI Automation Framework for testing Androi... DarkInfluence.UITests 
No hay actualizaciones de paquete disponibles en el origen del paquete actual del proyecto 'DarkInfluence.Droid'.
Xamarin.TestCloud.Agent {0.21.5} Xamarin Test Cloud Agent DarkInfluence.iOS

Hay un aviso con respecto a Insights:

U1608: Se detectó una versión del paquete fuera de la restricción de dependencia: Microsoft.ApplicationInsights.WindowsApps 1.1.1 requiere Microsoft.ApplicationInsights (= 1.2.3), pero la versión Microsoft.ApplicationInsights 2.6.4 ya se resolvió.

Compruebo para terminar esta puesta a punto que la aplicación sigue ejecutando con la misma configuración que antes y así es, aunque el compilar nos vuelve a mostrar el aviso anterior sobre Microsoft.ApplicationInsights.WindowsApps.

En la siguiente entrada, comprobaré el estado de la aplicación Xamarin para Android cuyas dependencias (el JDK instalado, versiones de Xamarin, API destino de la imagen de dispositivo en el emulador, etc.) la hacen especialmente interesante. Espero que este artículo te haya resultado útil.

Retomar antiguos proyectos software “caseros”

Suele ser muy complicado por dos razones. O bien las dependencias han desaparecido (a veces ocurre en Maven), o bien algunos IDE como Visual Studio tienen demasiada influencia en la gestión de configuración del proyecto y una actualización del IDE te deja el proyecto en un estado inconsistente. Ojo que esto no sólo pasa en VS, sino que Android Studio a través de Gradle hace lo mismo. Una actualización de Android Studio fuerza a actualizar Gradle que aplica nuevas reglas y el proyecto ya no compila sin haber cambiado ni una sola versión de las dependencias.

Voy a listar el estado actual los proyectos caseros en los que estoy trabajando e iré escribiendo futuros posts sobre cómo hice para resolver todos los problemas que me he ido encontrando.

First (mi antiguo TFC):

Este lo tengo reciente. Hoy mismo he instalado NetBeans 9.0 Beta y he intentado compilar mediante Maven el código del proyecto, que llegaba a ejecutar en NetBeans 8.2, recién desinstalado.

  • Error: Un paquete perteneciente a Image I/O (para manejar ficheros TIFF) ya no está en ninguno de los repositorios configurados de Maven.
  • Causa: Borrar el antiguo repositorio (C:\usuario\.netbeans o quizá C:\usuario\.m2, ya investigaré) con las dependencias descargadas de los repositorios de Maven.
  • Plan de acción: Usar referencias locales para todas las bibliotecas que falten.

Cableman (una aplicación de Xamarin Forms y UrhoSharp):

El mayor problema es que no recuerdo el estado anterior (es posible que sólo funcionase en un dispositivo real Android y en Windows UWP). Pero no hay framework más acoplado que Xamarin a las versiones de Visual Studio. Tras dos actualizaciones de versión (de 15.5 a 15.7), ya no funciona en Android (emulador) ni en Windows UWP.

  • Error: En Android da un error de runtime porque las rutas de Assets están mal. En UWP la actualización de Visual Studio ha introducido una dependencia de .NET  Standard, incompatible con la estrategia actual de compartición de código, que es mediante proyecto compartido, valga la redundancia.
  • Causa: Desconocida, updates de Xamarin o Visual Studio.
  • Plan de acción: El plan de acción de actualizar la estrategia de compartición de código de proyecto compartido a .NET Standard no ha tenido éxito porque UrhoSharp no funciona cuando se comparte el código de la lógica por .NET Standard.

Dark Influence (otra aplicación de Xamarin Forms):

Esta aplicación, sencillísima, funcionaba correctamente en Windows, Windows 10 Mobile, Android e iOS. De momento es un botón que hace un random en un array, aunque hay bastante lógica ya escrita y compartida mediante (otra vez) un proyecto compartido.

  • Error: Esto provoca errores en los proyectos específicos de plataforma porque Xamarin Forms aparentemente ha introducido una dependencia de .NET Standard.
  • Causa: Desconocida, updates de Xamarin o Visual Studio.
  • Plan de acción: Migrar a .NET Standard, ya que este proyecto no usa UrhoSharp.

Herschel Quick Look (un port de la versión de iOS a UWP usando WinObjC)

Todo compila bien, pero los XIB con delegates aparentemente no los soporta la herramienta de WinObjC xib2nib.

  • Error: Pantalla principal de la aplicación en blanco, con muchos nodos del XIB apareciendo como unhandled en la ejecución de xib2nib.
  • Causa: Desconocida por el momento. Quizá el delegate que se encarga de pintar la pantalla.
  • Plan de acción: Utilizando la herramienta nib2objc que convierte los ficheros de interfaz de XCode a ficheros de código en Objective C, tengo un fichero .m equivalente para la pantalla principal. No tengo muy claro cómo integrar ese fichero con el delegate que pinta todo lo demás.

 

Suelen decir que explicar un problema te ayuda a entenderlo, así que vamos a intentar entender todas estas cosas por aquí próximamente.

Sherlock Holmes and the Devil’s Daughter (no arranca)

Sí, parece que las compañías cada vez se arreglan para introducir bugs más raros, y cuando encima tienes varias capas añadidas (como Steam, la Game Bar de Windows y el DVR de Nvidia) que parece que se están peleando por dibujar cosas extrañas encima de tu juego, pues el caos es tremendo.

En realidad lo que me pasó es que configuré el sonido de Windows para que pasase de los auriculares a los altavoces integrados en el monitor. A partir de ese momento el juego no funcionaba: arrancaba, mostraba una pantalla en blanco, luego una en negro y no se podía continuar. No lo pude arreglar por los medios habituales, a pesar de que desactivé todos los overlays y reinstalé el juego desde cero.

Fue volver a configurar los auriculares como dispositivo predeterminado y arrancar el juego instantáneamente. Lo que no tengo claro es si tienes que mantener el dispositivo de sonido que utilizabas cuando lo instalaste o cuando jugaste por primera vez. Espero que sirva de ayuda.

EA regala Los Sims 2 al terminar su soporte

Si entras en Origin y en el menú Origin -> Canjear código de producto escribes “I-LOVE-THE-SIMS” (sin las comillas), en tu colección aparecerá la versión Colección Definitiva de Los Sims 2. Eso son 8 expansiones y 9 paquetes de contenido. Un regalazo.

El juego básico de Los Sims 2 y todas sus expansiones. Esto es la Colección Definitiva.

El juego básico de Los Sims 2 y todas sus expansiones. Esto es la Colección Definitiva.

 

Es como si Microsoft hubiese regalado Windows XP el día que terminó el soporte el 8 de abril de 2014. Como una manera de decir, lo sentimos por todos los bugs que todavía quedan, no los vamos a arreglar, a cambio aquí tenéis una copia gratis. Vale, no es exactamente lo mismo porque Windows XP es una pieza de software extremadamente barata, mientras que Los Sims 2 con todas sus expansiones y packs… no quiero ni pensarlo.

Este regalo de Electronic Arts originalmente era una manera de decirle gracias a la gente que tenía una copia de Los Sims 2 registrada en Origin pero, desde ayer día 23 de julio, todos los usuarios de Origin pueden descargarla gratis introduciendo el código hasta el día 31 de julio. Los aficionados más impacientes pueden entretenerse con la segunda entrega del simulador de vida hasta que en septiembre vea la luz la cuarta entrega. Eso si no se retrasa, como Dragon Age: Inquisition y Battlefield: Hardline.

Siempre se habla de la armadura de caballo de Oblivion como el inicio de la fiebre DLC, pero eso es sólo porque era multiplataforma (en consolas con tienda centralizada y conexión a Internet) y los consoleros no estaban acostumbrados a esto de ir añadiendo contenido a sus juegos. Cuando salió Oblivion en marzo de 2006, Los Sims 2 —que estaba en la calle desde septiembre de 2004— ya llevaba 3 expansiones, 2 packs de contenido y se había lanzado en 4 ediciones diferentes. Además, había introducido desde el principio una tienda online donde comprar —individualmente— todo tipo de objetos para mejorar la vida de nuestro Sim o, al menos, hacerla mucho más bonita.