Ejecutar una aplicación Angular en Cordova

Ejecutar una aplicación Angular en Cordova
homer-simpson

Cara al intentar ejecutar la app Angular en Cordova

Últimamente me he dedicado a encapsular una aplicación Web hecha en Angularjs (versión 1) en una app Cordova para los tres principales sistemas operativos: Android, iOS y Windows Phone. Algo que a priori parecía que no me iba a dar mucho trabajo porque ya tengo experiencia en Cordova ha sido un pequeño via crucis de errores y de patearme páginas de ayuda y posts de Stackoverflow.  En este post resumo lo que he aprendido estos dias de momentos de desesperación y de tirarme de los pelos.

A tener en cuenta en todas las plataformas

 

1 – HTML5 mode

En versión web es habitual poner el modo HTML5 del locationProvider a true para tener las URL’s sin las dichosas #. Queda mucho más limpio y hace que no se parezca más a una web de toda la vida. Pero en Cordova no funciona, ni falta que hace ya que la URL no se ve, pero si no lo sabes te puedes volver loco ya que el enrutamiento no funciona y al intentar ir a otra página desde el móvil se te queda cara de tonto.

En mi caso he querido tener el mismo código para la web que para la aplicación Cordova ya que así evidentemente el mantenimiento es más sencillo. Para diferenciar código no común simplemente miro si en el objecto window está el objeto cordova que se carga sólo en el index.html de Cordova que es el único elemento no común en mi proyecto. Con una tarea gulp construyo el build para web o Cordova y es la tarea la que coje el index correcto.

Por tanto para asignar el modo de la URL, simplemente en la configuración donde está el :

 

2 – Quitar href=”#”

Relacionado con el tema anterior de las # en las URL’s también hay que tener cuidado con los enlaces <a href=”#”…. que muchas veces se usan no como links normales sino simplemente para elementos clikcables para no tener que añadirles por CSS un cursor pointer en el hover o quizás por semántica. En estos casos quitar el # y dejarlo como href=”” ya que la almohadilla provoca errores en el routing al parecer una URL de angular. En mi caso cualquier click en uno de estos anchors provocaba irse a la home ya que se iba a la raiz.

 

3 – Quitar <base href=”/” />

El tag de HTML base es útil para definir todas las URL’s relativas respecto a una base, dependiendo de donde se despliegue la web es útil. Pero en Cordova da problemas. Hay que quitarlo de nuestro index.html.

 

4 – Sanitize

Para que vaya bien el enroutamiento también es necesario añadir la siguiente línea para que se permitan URL con “file” ya que en Cordova las URL’s estan con dicho protocolo:

 

5 – Fastclick

El evento click en pantallas táctiles tarda unos 300ms en ejecutarse, es el tiempo que se toma el dispositivo para distinguirlo de un doble tap. Aunque parece poco ese tiempo se nota y da sensación de lentitud. Para este problema yo suelo usar el evento touchstart“en lugar del click pero en angular ya no hay nada parecido a ng-touch o algo así. Parece ser que en versiones anteriores si que lo había pero ahora lo han deprecado y en la misma web de angular aconsejan el uso de fastclick para quitar el delay. Por tanto lo añadiremos en el app.run() de la siguiente manera:

 

windows-phone-logo

En windows phone mi problema fué que aunque instalaba la app en un dispositivo real sin problemas en cuanto la intentaba ejecutar inmediatamente después de mostrar el splashscreen abortaba y volvía al menú sin saber por qué. Por tanto para depurarla el Visual Studio me salvó la vida. Para abrir el proyecto hay que buscar el fichero .sln que está en platforms/windows.

Después de pelearme durante un tiempo esto es lo que aprendí:

1 – Sanitize

Hay que ampliar el sanitize anterior con los protocolos propios de microsoft ms-appx, también lo haremos para las url’s de las imágenes:

 

2 – Seguridad acceso DOM

Resulta que Microsoft es muy pijotera con la seguridad en cuanto a manipulación del DOM y no le gusta los tejemanejes que hace Angular con los append, insertBefore etc. De echo con jquery 1.x también había problema y no se podía usar directamente, por suerte en jquery 2.0 se resolvió el problema.

Para solucionar el problema encontré una libreria echa para tal efecto: https://github.com/Microsoft/winstore-jscompat

Por tanto simplemente con añadir el script antes de jquery y angular problema resuelto:

El script se puede dejar en el index común a los otros sistemas operativos porque si no es una MSapp no hace nada.

 

ios_logo

En iOS el problema no lo tuve con Angular en concreto sino con las llamadas Ajax a una API externa. Desde iOS 9 la seguridad ha aumentado mucho y conseguir hacer una llamada Ajax es una pequeña pesadilla. Aquí se explica cómo. Básicamente consiste en:

1 – Añadir Content Security Policy

Añadir el dominio de la API. Además en mi caso he añadido lo necesario para poder acceder a apis de google como la de google maps.

 

2 – Añadir ATS exception

En el fichero platforms/ios/<ProjectName>/<ProjectName>-Info.plist hay que añadir una excepción de seguridad (cambiar dominio.api por el que toque). En mi caso he añadido una línea más de la que hay en la documentación (NSAllowsArbitraryLoads) porque necesitaba acceder a imágenes desde un servidor externo:

 

Lo malo que tiene es que este fichero se autogenera cada vez que hacemos un build por tanto para automatizar el proceso se puede hacer lo siguiente:

En el config.xml añadir una llamada a un sh que modificará el Info.list, en la documentación pone que hay que asociarlo al “before_build” para que se ejecute justo antes de hacer el build, pero según he comprobado esto es un error y hay que ejecutarlo lógicamente después del build “after_build”:

Y añadir en hooks/ios_ats.sh el sh siguiente al que he añadido otro paso respecto a la documentación para tener el otro permiso que necesitaba para las imágenes:

Para que el sh sea ejecutable hay que darle permisos:

Y eso es todo…

Siguiendo estos pasos y con un poco de suerte finalmente conseguiremos que nuestra aplicación Angular ¡funcione en Cordova! homer_simpsonwoohooo

 

Enviar comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *