VISITAS:

lunes, 17 de noviembre de 2014

Notificaciones push para Android con Corona SDK y Gamethrive


NOTA: Utilizaré el servicio GameThrive, el cuál tiene la ventaja de ser gratuito, ser compatible con notificaciones Android e iOS, y además tiene un plugin gratuito para Corona SDK.


1. Registrarse en Gamethrive (si no estamos registrados previamente).

https://gamethrive.com/

2. Crear un projecto con notificaciones en Google

https://console.developers.google.com/project

Pulsar en "Crear proyecto"

Dar un nombre al proyecto.
El ID del proyecto da igual.
Pulsar el botón "Crear" (puede tardar casi un minuto en crear el proyecto).

En el frame de la izquierda, pulsar en "Descripción general".
Arriba aparece el número del proyecto (#PN). Este dato será necesario para enviar notificaciones a la aplicación.

En el  frame de la izquierda, pulsar en APIs y autenticación. Después pulsar en APIs
Buscar "Google Cloud Messaging for Android" y pulsar en el botón a la derecha de esta línea para activar el servicio.
Una vez activado, aparecerá arriba en la pantalla con los demás servicios activados.

En el frame de la izquierda, pulsar en APIs y autenticación. Después pulsar en Credenciales.
Pulsar el botón "Crear clave nueva".
Pulsar en "Clave de servidor"
No escribir nada en el textbox y pulsar el botón "Crear".
La clave de la API (#KEY) la necesitaremos después.

3. Crear una aplicación en Gamethrive

Entrar en la cuenta de Gamethrive que hemos creado en el apartado 1.

Ir al panel de aplicaciones.

Pulsar el botón "Add a new app"
Dar un nombre a la aplicación (se recomienda poner el mismo nombre que se puso en Google, para evitar confusiones).
Pulsar el botón "Submit".

En el frame izquierdo, pulsar "Application Settings"
Se muestran App ID/Key (#APPID) y REST API Key (#REST) que se utilizarán después.
En la sección "Platforms", pulsar el botón "Configure" en la línea de "Google Play".
Copiar la clave que se generó en Google al final del apartado 2 (#KEY).
Pulsar el botón "Save".
Aparecerá la línea "Google Play" como "Active"

4. Corona build.settings

Dentro de settings, añadir el siguiente elemento, por ejemplo, después del elemento orientation:

plugins =
{
    ["plugin.GameThrivePushNotifications"] =
    {
        publisherId = "com.gamethrive",
    },
    ["plugin.google.play.services"] =
    {
            publisherId = "com.coronalabs",
            supportedPlatforms = { android=true },
    },
},

También dentro de settings, hay que poner la siguiente sección:

        android =
        {
            permissions =
            {
                { name = ".permission.C2D_MESSAGE", protectionLevel = "signature" },
            },
            usesPermissions =
            {
                "android.permission.INTERNET",
                "android.permission.GET_ACCOUNTS",
                "android.permission.RECEIVE_BOOT_COMPLETED",
                "com.google.android.c2dm.permission.RECEIVE",
                ".permission.C2D_MESSAGE",
            },
        },


4. Corona config.lua

Dentro de application, añadir el siguiente elemento, por ejemplo, después del elemento content:

        notification = {
            google = { projectNumber = "#PN" },
        }, 

5. Corona main.lua

Al principio del fichero main.lua:


-- Esta función es llamada cuando el usuario abre una notificación o cuando la aplicación está abierta y activa.
function DidReceiveRemoteNotification(message, additionalData, isActive)
    if (additionalData) then
        if (additionalData.discount) then
            native.showAlert( "Discount!", message, { "OK" } )
            -- 
        elseif(additionalData.bonusCredits) then
            native.showAlert( "Bonus Credits!", message, { "OK" } )
            -- 
        elseif(additionalData.actionSelected) then -- Interactive notification button pressed
            native.showAlert("Button Pressed!", "ButtonID:" .. additionalData.actionSelected, { "OK"} )
        end
    end
end

local GameThrive = require("plugin.GameThrivePushNotifications")
GameThrive.Init("poner aquí #APPID de gamethrive", "poner aquí #PN de google", DidReceiveRemoteNotification)

La función DidReceiveRemoteNotification se ejecutará cuando el usuario abra una notificación.
Casos:
  • El móvil está apagado: cuando se encienda el móvil aparecerá la notificación y al pulsarla, se abrirá la aplicación y se ejecutará esta función.
  • La aplicación está abierta y activa (foreground): se invocará esta función, aunque no aparecerá el icono de la notificación
  • Si la aplicación no está activa: aparecerá el icono de la notificación y cuando el usuario lo pulse, se abrirá la aplicación y se ejecutará esta función.
Parámetros de esta función:
  • message: es el mensaje de la notificación.
  • additionalData: son datos adicionales que podemos añadir a la notificación (ya se envíe desde la web de gamethrive o bien a través del API de gamethrive).
  • isActive: indica (true o false) si la aplicación estaba activa.

6. Icono de notificación

El icono de notificación debe ser un fichero en formato PNG, con fondo transparente y color blanco.
Se debe crear un icono para cada una de las distintas densidades de pantalla y otro conjunto de iconos para Android API v11. En resumen, hay que crear los siguientes iconos:


  • IconNotificationDefault-ldpi.png ---> 18x18 px
  • IconNotificationDefault-ldpi-v11.png ---> 18x18 px
  • IconNotificationDefault-mdpi.png ---> 24x24 px
  • IconNotificationDefault-mdpi-v11.png ---> 24x24 px
  • IconNotificationDefault-hdpi.png ---> 36x36 px
  • IconNotificationDefault-hdpi-v11.png ---> 36x36px
  • IconNotificationDefault-xhdpi.png ---> 48x48 px
  • IconNotificationDefault-xhdpi-v11.png ---> 48x48 px

Hay que tener cuidado de dejar al menos un pixel en ldpi, un pixel en mdpi, un pixel en hdpi y dos pixel en xhdpi, como borde entre la imagen y el icono.




jueves, 28 de agosto de 2014

Estados de una Activity en Android

ESTADOS

Los estados en los que puede estar una Activity en Android son:

  • NON-EXIST
  • STOPPED: no visible
  • PAUSED: visible
  • RUNNING: visible y en foreground
Las transiciones entre estados y las funciones de la Activity invocadas son las siguientes:

  • NON-EXIST --> STOPPED: onCreate()
  • STOPPED --> PAUSED: onStart()
  • PAUSED --> RUNNING: onResume()
  • RUNNING --> PAUSED: onPause() y onSaveInstanceState()
  • PAUSED --> STOPPED: onStop()
  • STOPPED --> NON-EXIST: onDestroy()


EVENTOS QUE CAUSAN CAMBIOS DE ESTADO

Lanzar la Activity

Pasa de estado NON-EXIST a estado RUNNIG, invocándose las siguientes funciones:
  • onCreate()
  • onStart()
  • onResume()

Pulsar Back

Pasa de estado RUNNIG a estado NON-EXIST, invocándose las siguientes funciones:
    • onPause()
    • onSaveInstanceState()
    • onStop()
    • onDestroy()

    Pulsar Home

    Pasa de estado RUNNIG a estado STOP, invocándose las siguientes funciones:
        • onPause()
        • onSaveInstanceState()
        • onStop()

        Abrir la aplicación en recientes después de Home

        Pasa de estado STOP a estado RUNNING, invocándose las siguientes funciones:
            • onStart()
            • onResume()

            Abrir la aplicación en recientes después de Back

            Pasa de estado NON-EXIST a estado RUNNING, invocándose las siguientes funciones:
                • onCreate()
                • onStart()
                • onResume()

                Rotar dispositivo

                Pasa de estado RUNNIG a estado RUNNING, invocándose las siguientes funciones:
                    • onPause()
                    • onSaveInstanceState()
                    • onStop()
                    • onDestroy()
                    • onCreate()
                    • onStart()
                    • onResume()

                    Lanzar otra Activity desde la Activity

                    Pasa de estado RUNNIG a estado STOP, invocándose las siguientes funciones:
                        • onPause()
                        • onSaveInstanceState()
                        • onStop()

                        Pulsar Back en la otra Activity

                        Pasa de estado STOP a estado RUNNING, invocándose las siguientes funciones:
                            • onStart()
                            • onResume()


                            CÓMO VE EL S.O. ANDROID LAS ACTIVITIES

                            Cuando el usuario pulsa sobre una aplicación en su móvil o tablet Android, el sistema operativo no arranca la aplicación, sino que arranca una Activity y la pone en estado RUNNING.
                            Normalmente, las aplicaciones contienen múltiples activities, ¿cuál de ellas se arranca? Esto viene definido en el fichero AndroidManifest.xml. Una activity tendrá definido:

                               

                            dentro de

                            Si desde la Activity inicial se arranca otra Activity, el sistema arrancará la nueva Activity y la pondrá en estado RUNNING (encima de la anterior). Estas dos actividades están en el stack de actividades de Android.
                            Si se pulsa Back, la actividad actual se destruye y vuelve la actividad inicial a estado RUNNING (el mismo efecto se consigue invocando el método finish() ).

                            Si se pulsa Back en la actividad inicial, se destruye la Activity inicial y volveremos donde estábamos antes de arrancar la aplicación.

                            El responsable de realizar todas estas tareas es el ActivityManager de Android, el cual mantiene un stack de actividades compartido entre todas las aplicaciones.

                            martes, 15 de julio de 2014

                            Unity 3D: Publicación para iOS en Apple App Store

                            Introducción

                            Desarrollar un juego 3D ó 2D en Unity no es demasiado difícil, aunque requiere una capacidad de programación (en C# o Unity script) relativamente importante.
                            Cuando se desarrolla con Unity, las pruebas se realizan en el mismo entorno Unity, ya sea Windows o Mac OS X.
                            Sin embargo, al final, queremos publicar nuestro juego en una plataforma móvil tal como Android o iOS. La publicación en Android la trataré dentro de poco, pero hoy quiero explicar cómo publicar para iOS (por cierto, bastante más complejo que para Android).

                            Requisitos previos

                            Para poder publicar en la Apple AppStore es necesario cumplir unos requisitos previos:
                            • Tener el Apple developer. Para ello hay que registrarse en http://developer.apple.com. Apple cobra 99$ al año.
                            • Tener un ordenador Mac. Apple no permite generar aplicaciones para iOS desde Windows u otros sistemas operativos
                            • Tener instalado XCode
                            • Tener un juego desarrollado y probado en Unity (esto es fundamental)

                            Pasos


                            1. Probar con el simulador en XCode
                            2. Probar en un dispositivo
                            3. Subir app al store
                            4. Actualizar la app

                            Esta guía es muy sencilla y describe paso a paso cómo publicar un juego en la tienda de aplicaciones de Apple. Los pasos que aquí se describen están realizados en julio de 2014. Si cuando leas este post, ha pasado mucho tiempo desde entonces, puede ser que algunos pasos hayan cambiado ligeramente, aunque los cambios no suelen ser muy importantes.

                            PROBAR CON EL SIMULADOR

                            UNITY


                            1. File > Build Settings…

                            2. En la sección Platform, seleccionar iOS

                            3. Si el botón Switch Platform está activo, pulsarlo para adaptar los assets del proyecto a iOS (esto puede tardar un rato)

                            4. Pulsar en Player Settings

                            5. Preparar icono de la aplicación para App Store

                                 - Preparar el icono en PNG 1024x1024 (también vale JPG, pero no tiene transparencia)
                                 - Este icono debe utilizarse como icono de la aplicación en Player Settings, si no, Apple puede rechazarlo


                            6. En el Inspector:
                                 - En la sección Resolución and Presentation, seleccionar Default Orientation (normalmente se pone Auto Rotation, para que pueda girar). Marcar Use Animated Rotation para que los giros sean animados. Seleccionar Allowed Orientations (si debe ser landscape, seleccionar sólo Landscape Left y Landscape Right)
                                 - En la sección Icon, seleccionar un icono de 1024x1024 para la aplicación
                                 - En la sección Other Settings, lo más importante se encuentra en Identification, donde hay que poner el bundle id, por ej, com.joseanquiles.laberinto. También hay que especificar bundle versión, que en la primera versión será 1.0. El resto de valores se pueden dejar por defecto. En Optimization es muy importante elegir SDK Version. Las dos opciones son: Simulator SDK, Device SDK. Como ahora vamos a probar en el simulador de XCode, seleccionamos Simulator SDK.

                            7. Pulsar el botón Build para generar el proyecto de XCode. Si ya se ha generado antes, es mejor reemplazar. Se genera un proyecto XCode (por defecto dentro del directorio del proyecto Unity). Se recomienda añadir como sufijo al directorio _iOS o similar, para reconocer rápidamente el contenido de este directorio

                            XCODE


                            1. Con el Finder entrar en el directorio del proyecto Unity/Proyecto XCode generado en el paso anterior

                            2. Si XCode está abierto, cerrarlo.

                            3. Doble click en el fichero Unity-iPhone.xcodeproj Se abrirá XCode

                            4. En la parte superior izquierda, seleccionar el dispositivo y después la versión de iOS (no elegir iOS 6.1, porque no funciona, no sé porqué)

                            5. Pulsar el botón Run (similar a Play) en la parte superior izquierda

                            6. Para capturar screenshots con el simulador, compilar la app para Simulator SDK (tal y como se explicó anteriormente), ejecutar en XCode y en el menú del simulador: Archivo > Guardar captura de pantalla. La captura se guarda en el escritorio

                                 - Screenshots para iPhone 4: PNG 960x640 -> utilizar el device iPhone 3.5"

                                 - Screenshots para iPhone 5: PNG 1136x640 -> utilizar el device iPhone 4”

                                 - Screenshots para iPad: PNG 1024x768 -> utilizar el device iPad



                            PROBAR EN UN DISPOSITIVO


                            Requisitos: Estar registrado en iOS Developer Program de Apple

                            Portal del desarrollador de Apple: http://developer.apple.com/membercenter/index.action


                            PORTAL DE DESARROLLO


                            1. Registrar un dispositivo de test (si ya se ha registrado antes, esto no es necesario)

                                 - Portal del desarrollador > Certificates, Identifiers & Profiles
                                 - iOS Apps > Devices > All
                                 - Pulsar el botón + para añadir un nuevo dispositivo
                                 - Name: dar un nombre al dispositivo
                                 - UDID -> para descubrir el UDID del dispositivo, pasar al siguiente punto

                            2. Descubrir el UDID del dispositivo

                                 - Conectar el dispositivo por USB
                                 - Abrir XCode
                                 - Window > Organizer
                                 - En DEVICES, seleccionar el dispositivo
                                 - En el apartado Identifier se muestra el UDID (copiarlo al clipboard)

                            3. Volver al portal del desarrollador para continuar el registro del dispositivo:

                                 - UDID: copiar el UDID cogido en el punto anterior
                                 - Pulsar en Continue
                                 - Pulsar en Register

                            4. Registrar el ID de la aplicación

                                 - Portal del desarrollador > Certificates, Identifiers & Profiles
                                 - iOS Apps > Identifiers > App IDs
                                 - Pulsar el botón +
                                 - App ID description: Patri Labyrinth
                                 - App ID prefix: generado automáticamente
                                 - App ID suffix:
                                           seleccionar Explicit App ID
                                           Bundle ID: com.joseanquiles.laberinto
                                 - App services: no cambiar nada
                                 - Pulsar el botón Continue
                                 - Confirm your App ID
                                 - Pulsar el botón Confirm
                                 - Registration complete
                                 - Pulsar el botón Done

                            5. Crear un perfil de provisión para desarrollo

                            Es necesario que XCode y el dispositivo tengan un perfil de provisión de desarrollo de la aplicación para poder testear en el dispositivo

                                 - Portal del desarrollador > Certificates, Identifiers & Profiles
                                 - iOS Apps > Provisioning profiles > All
                                 - Pulsar el botón +
                                 - Seleccionar iOS App Development
                                 - Pulsar el botón Continue
                                 - App ID: Patri Labyrinth
                                 - Pulsar el botón Continue
                                 - Select Certificate: José Antonio Quiles (iOS development)
                                 - Pulsar el botón Continue
                                 - Devices: Select All
                                 - Pulsar el botón Continue
                                 - Profile Name: Patri Labyrinth Development
                                 - Pulsar el botón Generate
                                 - Pulsar el botón Download
                                 - El fichero con el perfil de provisión se guarda en Descargas (se puede mover a otro directorio)


                            XCODE


                            1. Cargar el perfil de provisión de desarrollo en XCode

                                 - Conectar el dispositivo por USB
                                 - Si XCode está abierto, cerrarlo.
                                 - Doble click en el fichero Unity-iPhone.xcodeproj Se abrirá XCode
                                 - Window > Organizer
                                 - Pulsar sobre el dispositivo
                                 - Si está activo, pulsar Use for development
                                 - En el frame izquierdo seleccionar Provisioning profiles en el dispositivo conectado
                                 - Pulsar el botón + Add
                                 - Seleccionar el fichero del perfil de provisión de desarrollo que hemos generado y descargado anteriormente

                            2. Instalar el perfil de provisión de desarrollo en el dispositivo

                                 - Arrastrar el perfil de provisión al dispositivo conectado en la sección Provisioning profiles
                                 - Para confirmar que el dispositivo tiene el perfil instalado: en el dispositivo entrar en Ajustes > General > Perfil y comprobar que está el perfil que hemos instalado.

                            UNITY

                            1. Si XCode está abierto, cerrarlo

                            2. File > Build Settings…

                            3. Pulsar el botón Player Settings

                            4. En el Inspector, en la sección Other Settings, elegir SDK Version: Device SDK

                            5. Pulsar el botón Build. Elegir Replace

                            XCODE


                                 - Conectar el dispositivo por USB
                                 - Si XCode está abierto, cerrarlo.
                                 - Doble click en el fichero Unity-iPhone.xcodeproj Se abrirá XCode
                                 - Asegurarse que el dispositivo no está locked
                                 - Pulsar en Run (parecido a Play)
                                 - El programa se ejecutará en el dispositivo




                            SUBIR APLICACIÓN AL APP STORE


                            iTUNES CONNECT


                            http://itunesconnect.apple.com

                            1. Añadir la aplicación a iTunes Connect

                                 - Entrar en iTunes connect
                                 - Pinchar en Manage your Apps
                                 - Pulsar el botón Add New App
                                 - Idioma por defecto: English
                                 - App Name: Patri’s Labyrinth
                                 - SKU Number: Patri_Labyrinth_01
                                 - Bundle ID: seleccionar el de la app que generamos en Unity
                                 - Pulsar el botón continue
                                 - Elegir el precio (Free si es gratis)
                                 - Desmarcar Discount for educational institutions
                                 - Pulsar el botón Continue
                                 - Version number: 1.0
                                 - Copyright: @Quilart
                                 - Category: Games
                                 - Subcategory: elegir una
                                 - Rating: marcar None en todos
                                 - Description: …..
                                 - Keywords: …. separadas por comas
                                 - Support URL: http://joseanquiles.blogspot.com
                                 - Meter los datos en Contact Information
                                 - Sección Uploads:
                                      - Large App icon: elegir el PNG 1024x1024
                                      - 3.5 inch retina: elegir los screenshots de 3.5”
                                      - 4 inch retina: elegir los screenshots de 4”
                                      - iPad screenshots: elegir los screenshots de iPad
                                 - Pulsar el botón Save
                                 - Pulsar el botón View Details
                                 - Pulsar el botón Ready for Upload Binary
                                 - Responder No a todas las preguntas
                                 - Pulsar el botón Save
                                 - Pulsar el botón Continue

                            PORTAL DEL DESARROLLADOR


                            1. Crear un perfil de provisión para distribución

                            Portal del desarrollador de Apple: http://developer.apple.com/membercenter/index.action

                                 - Portal del desarrollador > Certificates, Identifiers & Profiles
                                 - iOS Apps > Provisioning profiles > All
                                 - Pulsar el botón +
                                 - Seleccionar App Store
                                 - Pulsar el botón Continue
                                 - App ID: Patri Labyrinth
                                 - Pulsar el botón Continue
                                 - Select Certificate: José Antonio Quiles (iOS development)
                                 - Pulsar el botón Continue
                                 - Profile Name: Patri Labyrinth Distribution
                                 - Pulsar el botón Generate
                                 - Pulsar el botón Download
                                 - El fichero con el perfil de provisión se guarda en Descargas (se puede mover a otro directorio)

                            XCODE


                            1. Cambiar settings

                                 - En el frame izquierdo seleccionar el proyecto
                                 - En la pestaña capabilities, en la sección Game Center, si aparece algún aviso, pulsar Fix issues
                                 - En la pestaña Build Settings, pulsar el botón All para ver todas las opciones
                                 - Sección code signing, Provisioning profile, elegir el perfil adecuado

                            2. Recompilar el proyecto

                                 - Product > Clean
                                 - Product > Archive (este proceso es largo)
                                 - Al final se abrirá el Organizer
                                 - Pulsar el botón Validate (esto validará la app antes de subirla) NOTA: Si diera un error "no identities were available”, entrar en el portal y descargar de nuevo el perfil de provisión de distribución, luego darle doble click para que lo coja XCode.
                                 - Pulsar el botón Distribute
                                 - Elegir Submit to the iOS App Store
                                 - Pulsar el botón Next
                                 - Elegir el perfil de distribución
                                 - Pulsar el botón Next
                                 - La aplicación comenzará a subirse al App Store

                            3. Con este termina el proceso. Ahora habrá que esperar unos 7 días a que Apple acepte la aplicación y la haga disponible en el AppStore.

                            4. En iTunes Connect se puede ver el estado de la aplicación. El primer estado será: Upload Received


                                 

                            SUBIR ACTUALIZACIÓN AL APP STORE     


                            iTUNES CONNECT


                            http://itunesconnect.apple.com

                            Nota: no actualizar una app si todavía no está en estado Ready for Sale. Es posible hacerlo, pero retrasará el proceso.

                            1. Preparar la actualización en iTunes Connect

                                 - Entrar en iTunes Connect
                                 - Manage your Apps
                                 - Pulsar sobre la app que se desea actualizar
                                 - En el apartado Versions, apuntar el número de versión actual, para generar una nueva. Por ejemplo, si la actual es la 1.0, la siguiente puede ser la 2.0
                                 - En el apartado Versions, pulsar el botón Add Version
                                 - Version number: la nueva versión (por ejemplo, 2.0)
                                 - What’s new: cambios en esta versión (en inglés)
                                 - Pulsar el botón Save
                                 - Ahora el status debería ser: Prepare for Upload
                                 - Pulsar el botón Ready for Upload Binary
                                 - Responder a todas las preguntas y pulsar el botón Continue
                                 - Seleccionar: Automatically release “App” once it has been approved
                                 - Pulsar el botón Save
                                 - Ahora el status debería ser: Waiting for Upload

                            2. Generar la nueva versión en Unity

                                 - File > Build Settings
                                 - Seleccionar plataforma iOS
                                 - Pulsar Switch Platform
                                 - Pulsar el botón Player Settings
                                 - En la sección Other Settings, poner Bundle Version = nueva versión
                                 - Pulsar el botón Build para generar el proyecto XCode
                                 - Marcar Enable replace, y pulsar el botón Replace
                                 

                            XCODE


                            1. Con el Finder entrar en el directorio del proyecto Unity/Proyecto XCode generado en el paso anterior

                            2. Si XCode está abierto, cerrarlo.

                            3. Doble click en el fichero Unity-iPhone.xcodeproj Se abrirá XCode

                            4. Cambiar settings

                                 - En el frame izquierdo seleccionar el proyecto
                                 - En la pestaña capabilities, en la sección Game Center, si aparece algún aviso, pulsar Fix issues
                                 - En la pestaña Build Settings, pulsar el botón All para ver todas las opciones
                                 - Sección code signing, Provisioning profile, elegir el perfil adecuado

                            5. Recompilar el proyecto

                                 - Product > Clean
                                 - Product > Archive (este proceso es largo)
                                 - Al final se abrirá el Organizer
                                 - Pulsar el botón Validate (esto validará la app antes de subirla) NOTA: Si diera un error "no identities were available”, entrar en el portal y descargar de nuevo el perfil de provisión de distribución, luego darle doble click para que lo coja XCode.
                                 - Pulsar el botón Distribute
                                 - Elegir Submit to the iOS App Store
                                 - Pulsar el botón Next
                                 - Elegir el perfil de distribución
                                 - Pulsar el botón Next
                                 - La aplicación comenzará a subirse al App Store

                            3. Con este termina el proceso. Ahora habrá que esperar unos 7 días a que Apple acepte la aplicación y la haga disponible en el AppStore. 

                            4. En iTunes Connect se puede ver el estado de la aplicación. El primer estado será: Upload Received en New Version (la versión anterior estará Ready for Sale)



                            martes, 15 de abril de 2014

                            Ficheros de comandos de Windows

                            Los ficheros de comandos de Windows son una forma sencilla de automatizar algunas tareas.
                            Para crear un fichero de comandos, simplemente hay que ponerle la extensión .CMD
                            Veamos ahora algunas de las cosas que se pueden hacer en estos ficheros de comandos.

                            Comandos básicos

                            @echo off
                            Desactiva la salida de todos los comandos que se van ejecutando (incluido él mismo). Se suele poner como la primera línea de un fichero de comandos.

                            echo mensaje
                            Saca un mensaje en la consola.

                            msg * mensaje
                            Saca un mensaje en una ventana (popup), pero sin detener la ejecución.

                            pause
                            Detiene la ejecución de los comandos hasta que se pulse una tecla. Muestra el mensaje "Presione una tecla para continuar . . .". Si no se desea que salga el mensaje estándar, utilizar pause>nul (sin espacios).

                            exit
                            Termina la ejecución de los comandos.

                            rem
                            Línea de comentario

                            Comandos del sistema operativo

                            cd
                            Cambia a un directorio

                            copy
                            Copia un fichero a otro fichero o lugar

                            del
                            Borra un fichero

                            move
                            Cambia el nombre de un fichero o lo mueve a otro directorio

                            cls
                            Borra la pantalla

                            type
                            Muestra el contenido de un fichero

                            Creación de ficheros de texto

                            Es posible crear un fichero con contenido textual:
                            echo línea 1 > fichero.txt
                            echo línea 2 >> fichero.txt
                            echo línea 3 >> fichero.txt

                            Variables

                            set var=valor
                            Crea una variable y le asigna un valor

                            %var%
                            Accede al valor de la variable

                            set /P var=Introduzca valor:
                            Pide al usuario que introduzca el valor de la variable

                            set /A var=%var1% + %var2%
                            Realiza una operación matemática y el resultado lo mete en la variable

                            Redirección

                            |
                            Pasa la salida de un comando a la entrada de otro comando
                            Ejemplo:
                                 ipconfig | findstr /C:"LAN"

                            ||
                            Ejecuta el segundo comando sólo si el primero falla
                            Ejemplo:
                                copy fichero1 fichero2 || echo No existe el fichero

                            >
                            Escribe la salida de un comando en un fichero
                            Ejemplo:
                                type fichero1 > fichero2

                            >>
                            Añade la salida de un comando a un fichero existente
                            Ejemplo:
                                dir >> fichero2

                            <
                            Toma como entrada de un comando el contenido de un fichero

                            Condiciones

                            if [not] string1 == string2 comando
                            Ejecuta el comando si el string1 es igual al string2

                            if [not] exist fichero comando
                            Ejecuta el comando si existe el fichero

                            Saltos

                            goto etiqueta
                            .....
                            :etiqueta


                            jueves, 3 de abril de 2014

                            Ejecución de paquetes solaris

                            Cuando se instala un paquete Solaris con el comando pkgadd, lo que se hace es procesar el fichero prototype (man -s4 prototype).
                            Este fichero consta de líneas con uno de los siguientes formatos:


                            • # comentario
                            • ! comando
                            • objeto

                            Las líneas de comentario se ignoran.
                            Las líneas de comando y de objeto se explican a continuación.

                            Líneas de comando

                            Se permiten los siguientes comandos:

                            !param=value

                            Permite definir variables que se pueden utilizar después.
                            Ejemplo:
                                    !USER=usuario2
                                    !GROUP=grupo4

                            !include

                            Para incluir otro fichero prototype

                            !default

                            Especifica el modo, usuario y grupo por defecto.
                            Ejemplo:
                                    !default 0755 $USER $GROUP

                            Líneas de objeto

                            En cada línea de objeto se especifica un fichero, directorio, etc.
                            El formato de las líneas de objeto es:

                                    type class location mode owner group

                            type

                            Especifica el tipo de objeto:
                            • f : fichero
                            • e : fichero para editar después de instalar
                            • v : fichero volátil que puede cambiar después de la instalación. Se crea con tamaño cero (por ej, ficheros de log)
                            • d : directorio
                            • i : fichero de control (pkginfo, request, depend, postinstall, preremove, etc)

                            class

                            En pkginfo se definen una serie de clases. Por ejemplo:

                                CLASSES="none parche"

                            En prototype se asigna una de estas clases a cada fichero. Estas clases indican el orden de instalación (en el ejemplo anterior, se instalarán primero los ficheros de la clase none y después los ficheros de la clase parche). En request se pueden decidir las clases a instalar.

                            location

                            Hay tres opciones para especificar un location:
                            • path absoluto: el objeto se instala en dicho path absoluto
                            • path relativo: el fichero es relocatable
                            • path1=path2: el path2 indica un fichero cuyo contenido se copiará al path1 durante la instalación
                            Un path puede contener una variable:
                            • $variable
                            • si la variable comienza con minúscula, es una variable build time
                            • si la variable comienza con mayúscula, es una variable install time (del request)

                            mode (opcional)

                            Son los permisos del objeto destino en octal

                            owner (opcional)

                            Es el usuario propietario del objeto

                            group (opcional)

                            Es el grupo propietario del objeto




                            viernes, 14 de febrero de 2014

                            Programación funcional en LUA

                            Las funciones como valores

                            En LUA, las funciones son valores con las mismas propiedades que el resto de valores (strings, números, tablas, etc). Las funciones se pueden almacenar en variables (globales o locales) y en tablas. Se pueden pasar funciones como argumentos y se pueden retornar funciones.
                            Una propiedad muy importante de las funciones en LUA es que tienen "lexical scoping". Esto significa que una función puede acceder a las variables de las funciones que le rodean. O sea, si una función f1 contiene internamente a otra función f2(), entonces todas las variables que se declaran en el scope de f1 pueden ser accedidas desde la función f2. Esto que parece algo sin importancia, se convertirá en LUA en algo fundamental para la programación funcional.
                            Las funciones en LUA son objetos anónimos, como el resto de valores, o sea, no tienen nombre. Cuando hablamos de la función print, realmente estamos hablando de una variable a la que se le ha asignado una función (valor) que muestra texto por consola.
                            Habitualmente, cuando escribimos una función, lo hacemos con la siguiente sintaxis:
                            function suma(a,b)
                                return a + b;
                            end
                            Sin embargo, esto es una forma de escribir lo que realmente estamos haciendo, que es lo siguiente:
                            suma = function (a,b)
                                return a + b;
                            end
                            Por consiguiente, una definición de función es realmente una sentencia de asignación que crea un valor de tipo "function" y lo asigna a  una variable.
                            Aunque lo normal es construir un valor "function" y asignarlo a una variable, hay ocasiones en que nos interesa construir la función y que permanezca anónima. Veamos un ejemplo.
                            La librería table ofrece una función table.sort() que recibe como argumento una tabla y ordena sus elementos. Esta función debe permitir ordenación ascendente, descendente, numérica, por fecha, etc de los elementos de la tabla. Para ello, en lugar de existir cientos de variantes de esta función, lo que se hace es pasar un segundo argumento (opcional) que es una función para comparar dos valores. Por ejemplo, supongamos la siguiente tabla de alumnos con sus notas:
                            alumnos = {
                                { nombre="Luis", nota=6.3 },
                                { nombre="Juan", nota=8.6 },
                                { nombre="María", nota=9.8 }
                            };
                            Para ordenar esta tabla por nombre de alumno:
                            table.sort(alumnos, function (a1, a2) return a1.nombre < a2.nombre; end );
                            También podemos ordenar la tabla por nombre pero de forma descendente:
                            table.sort(alumnos, function (a1, a2) return a1.nombre > a2.nombre; end );
                            Las funciones que reciben como argumento otra función se denominan high-order functions.
                            Otro ejemplo de función high-order es el cálculo de la derivada de una función matemática en un punto. La derivada de una función f() en un punto es ( f(x+d) - f(x) ) / d
                            function derivada(f, d)
                                d = d or 0.0001;
                                return function (x)
                                    return (f(x+d) - f(x)) / d;
                                end
                            end
                            De esta forma, podemos tener la función derivada de sen(x):
                            d_seno = derivada(math.sin);
                            Las funciones se pueden almacenar no sólo en variables globales, sino también en variables locales e incluso en tablas (esto dará lugar a los módulos y programación orientada a objetos en LUA).

                            Closures

                            Cuando escribimos una función dentro de otra función, la función interna tiene acceso a todas las variables de la función contenedora, incluidas las variables locales. A esta característica le llamamos lexical-scoping. Aunque esto suena bastante obvio, realmente no lo es, si lo combinamos con el hecho de que las funciones son valores como el resto de valores del lenguaje.
                            Veamos un ejemplo:
                            newCounter = function ()
                                local i = 0;
                                return function ()
                                    i = i + 1;    -- incrementa la variable local externa i
                                    return i;
                                end
                            end
                            Esta función (que se asigna a la variable newCounter) crea y retorna una función anónima que incrementa el valor de la variable i (local a la función contenedora). ¿Qué ocurre cuando utilizamos newCounter para crear nuevas funciones? Cuando invoquemos a la nueva función construida, ¿cómo accederá a la variable i?
                            Veamos un ejemplo de uso:
                            func1 = newCounter();
                            print(func1());     -- 1
                            print(func1());     -- 2
                            Lo interesante en este ejemplo es que cuando invocamos a la función construida y retornada por newCounter(), se ejecuta una función que accede a una variable que era interna a su función contenedora, la variable i. Pero entonces, esa variable i, ya ha desaparecido ¿no? Ya que era una variable local a la función newCounter() y newCounter ya no existe. ¿Que ha ocurrido?
                            LUA maneja esta situación adecuadamente, mediante el concepto de closure. Para simplificar, un closure es una función más todo el entorno que la rodea. En este caso, la función retornada por newCounter() es un closure, que incluye la propia función anónima y la variable i.
                            Por ejemplo, si creamos otra nueva función anónima volviendo a invocar a newCounter(), se vuelve a retornar un closure nuevo con otra variable i:
                            func2 = newCounter();
                            print(func2());    -- 1
                            print(func1());    -- 3
                            print(func2());    -- 2
                            Esto ocurre porque func1 y func2 son dos closures distintos, cada uno con su propia instancia de la variable i.
                            Hablando técnicamente, los valores son closures, no las funciones.
                            Si la función newCounter() recibiera por ejemplo un argumento, ese argumento pasaría al closure:
                            newIncrementer = function (inc)
                                local i = 0;
                                return function ()
                                    i = i + inc;
                                    return i;
                                end
                            end
                            En este caso, el closure incluye la función anónima, la variable i y el argumento inc.
                            Un ejemplo aclaratorio de los closures:
                            a = { };local x = 20;for i = 1, 10 do    local y = 0;    a[i] = function() y = y + 1; return x + y; end;end
                            En este ejemplo, el bucle for crea 10 closures (10 instancias de una función anónima). Cada uno de estos closures tiene una instancia de la variable y que es distinta. Sin embargo, todos los closures comparten la misma variable x.

                            Funciones en las tablas

                            Una consecuencia obvia de que las funciones (realmente closures) son valores como otro cualquiera es que podemos almacenarlas en variables locales, variables globales y en tablas.
                            Almacenar funciones en tablas es algo muy común en LUA. Por ejemplo, cuando llamamos a math.sin(2.56) estamos invocando a un miembro de la tabla math que se llama sin y es una función.
                            Para crear una tabla que tenga miembros función hacemos lo siguiente:
                            util = { };
                            util.suma = function (x, y) return x + y; end
                            util.resta = function (x, y) return x - y; end
                            De igual forma, también podemos utilizar el constructor de la tabla:
                            util = {
                                suma = function (x, y) return x + y; end,
                                resta = function (x, y) return x - y; end
                            };
                            Además, LUA ofrece una tercera alternativa para tablas con miembros función:
                            util = { };
                            function util.suma(x, y) return x + y; end
                            function util.resta(x, y) return x - y; end
                            En cualquiera de los casos, la invocación a las funciones de la tabla util sería de la siguiente forma:
                            util.suma(3, 2);
                            util.resta(4,7);

                            Funciones locales

                            Cuando almacenamos una función en una variable local, dichas funciones sólo pueden ser utilizadas en el scope en que se definen:
                            local func1 = function (a, b) return a ^ b; end
                            local func2 = function (x) return f(x, x); end
                            Esto es muy útil en los packages, donde las funciones del package (scope) pueden utilizar las otras funciones locales








                            martes, 11 de febrero de 2014

                            iOS: Certificados y perfiles de provisión

                            Introducción

                            Desarrollar programas para iOS (iPod, iPhone o iPad) tiene, además de lo que es el propio programa, otras tareas "accesorias" que a veces complican bastante el despliegue de la aplicación en dispositivos reales.
                            Apple adoptó la filosofía de que sólo Apple da permiso para que una aplicación corra en dispositivos iOS. Esto es algo bastante estricto, pero da muchas ventajas a los usuarios, ya que así se garantiza que las aplicaciones que se instalan han pasado por un control de Apple.

                            Certificados digitales de Apple

                            Pero, si sólo Apple puede autorizar aplicaciones, ¿cómo podemos desarrollar una aplicación nosotros?
                            La idea es que los desarrolladores tengan un certificado reconocido (autorizado) por Apple y que firmen las aplicaciones, de forma que los dispositivos vean que la firma está avalada por Apple.
                            Cuando un desarrollador se apunta al programa de desarrolladores de Apple, puede solicitar un certificado firmado por el propio Apple que se puede utilizar para firmar aplicaciones. Para ello, el desarrollador tiene que generar un CSR (certificate signing request) mediante la aplicación de llaveros de MAC OS.
                            La aplicación de llaveros genera automáticamente dos claves: una privada y una pública. El CSR lleva la clave pública, además del nombre y mail del desarrollador y se firma utilizando la clave pública. El CSR se envía a Apple (http://developer.apple.com). Como el CSR está firmado utilizando la clave privada, Apple se asegura que realmente viene del desarrollador.
                            Cuando Apple recibe el CSR, emite un certificado firmado por Apple. El certificado emitido por Apple contiene los mismos datos (incluida la clave pública) pero con la firma de Apple.
                            El certificado emitido por Apple (fichero .cer) lo descargamos a nuestro equipo y lo arrastramos (drag and drop) a la aplicación de llaveros.

                            Perfiles de provisión

                            Ya tenemos un certificado firmado por Apple con el que podremos firmar nuestras aplicaciones. Pero los dispositivos todavía no saben si pueden confiar en ti, y para esto surgen los perfiles de provisión.
                            Cuando creamos un perfil de provisión, lo que estamos haciendo es asociar una serie de dispositivos al certificado que hemos generado en el apartado anterior. El perfil de provisión es un fichero .provision se utiliza durante el proceso de compilación de una aplicación iOS y se despliega también en el dispositivo. Para crear un fichero de provisión hay que hacerlo en la web de desarrollo de Apple y descargarlo en el equipo. Luego se hace doble click y lo coge el Organizer de XCode.
                            Se pueden tener varios perfiles de provisión, uno para cada aplicación. Esto es lo normal.
                            En resumen, el perfil de provisión dice que el código compilado por nosotros se le permite ejecutar en una serie de dispositivos.

                            Compilación y ejecución de la aplicación

                            A la hora de compilar, lo importante es decirle a XCode que utilice nuestro certificado y el perfil de provisión.
                            Si miramos lo que contiene una aplicación compilada, podemos ver el perfil de provisión (que es una copia del original) y un directorio denominado _CodeSignature que contiene un fichero llamado CodeResources que es una lista de hashes de todos los ficheros del proyecto (realmente, firmas con nuestro certificado de todos los ficheros del proyecto).
                            Cuando se instala la aplicación, iOS hace una serie de comprobaciones: busca el fichero de provisión firmado por Apple, chequea los hashes en CodeResources utilizando la clave pública que viene en el certificado (asegurándose así que los ficheros no se han modificado durante el proceso).
                            Al ejecutar la aplicación, iOS vuelve a chequear el perfil de provisión y los hashes de todos los ficheros.

                            Para terminar...

                            Se necesitan dos certificados, uno para desarrollo y otro para distribución. Estos certificados se pueden utilizar para cualquier número de aplicaciones. Los certificados garantizan que la aplicación la ha desarrollado alguien reconocido por Apple, y además, garantizan que la aplicación no se ha modificado o corrompido.
                            El desarrollo de una aplicación para iOS tiene tres etapas:
                            1. Desarrollo
                            2. AdHoc
                            3. Distribución
                            Cada fase tiene tres partes (aunque no todas las partes se aplican a todas las etapas):
                            • Ficheros fuente
                            • Certificados
                            • Perfiles de provisión
                            Algunas de estas partes tienen elementos dentro de ellas:

                            • Nombres de desarrolladores: son los que desarrollan la aplicación y la firman
                            • UDIDs de dispositivos: son identificadores de dispositivos que se pueden utilizar para testear una aplicación (Apple permite un máximo de 100 dispositivos por desarrollador registrado).
                            • AppIDs de aplicación