diumenge, 31 de gener del 2016

Animaciones y gráficos


Android nos permite trabajar a nivel gráfico de dos maneras, a nivel de cocina, que es con el ndk que puedes programar un mix entre java y c, para hacer gráficos de alto rendimiento, y con sdk, haciéndolo en android que hace llamadas a la cpu, depende con el nivel de gráficos que queramos trabajar.

Podemos coger una imagen y hacer una batería de imágenes, podemos definir por xml o programación este proceso.

Una misma animación se pude hacer de varias formas, podemos definir la durada de la animación, la interpolación (si el movimiento es lineal o hay un cambio), si se tiene que repetir la animación, si se tiene que reproducir al inreves, si son un conjunto animados de elementos, también podremos indicar fotogramas por segundo...
La clase ValueAnimator mantiene la pista de la animación (como por ejemplo, cuanto tiempo llevamos animando un objeto y el valor actual de la propiedad que se esta animando, esta clase encapsula TimeInterpolator, que se encarga de la interpolación de la animación y TypeEvaluator para determinar como se han de calcular los valores (enteros reales...)), con start se inicia.





Diferencia con ViewAnimation
ViewAnimation solo sirve para animar los objetos que heredan de View (ProgressBar, TextView, etc), como un canvas.
Además no expone todas las propiedades de estos objetos.

La mayoría de estas clases se encuentran en el paquete android.animation.
La clase Animator dispone de la infraestructura básica para crear animaciones, pero normalmente trabajamos con sus subclases:
  • ObjectAnimator: es una subclase de ValueAnimator que le permite establecer un objeto de destinación y la propiedad de un objeto que desea animar. Esta clase actualiza la propiedad en consecuencia cuando se calcula un nuevo valor para la animación. Podemos utilizar ObjetAnimator la mayor parte del tiempo, porque hace que el proceso de animación de los valores en objetos de destinación sean mucho mas fáciles. No obstante, hay veces que es mejor utilizar ValueAnimator directamente porque ObjetAnimator tiene mas restricciones, como la exigencia de métodos específicos accesorios en el objeto de destinación.
  • AnimatorSet: Proporciona el mecanismo para hacer un grupo de animaciones juntos, para que se ejecuten el uno con el otro. Podemos configurar animaciones de objetos juntos, de manera secuencial, o después de un retraso determinado. Es decir, determinar ejes X y Y.
  • ValueAnimator.
Los evaluadores dicen como se han de calcular los valores de las propiedades que se están animando. Disponen de IntEvaluator, para las propiedades int, float Evaluator para propiedades float, ArgbEvaluator para propiedades de color y TypeEvaluator que es una interficie.

Los interpoladores indican como se tienen que calcular los valores con el paso del tiempo. AccelerateDecelerateInterpolator, AccelerateInterpolator, LinearInterpolator, son ejemplos de interpoladores.

AccelerateDecelerateInterpolator

public float getInterpolation(float input){
   return (float) (Math.cos((input+1)*Math.PI) /2.0f) + 0.5f;
}

LinearInterpolator
pubic float getInterpolation(float input){
   return input;
}

ms Lineal acc/deacc
0 0 0
200 .2 .1
400 .4 .345
600 .6 .8
800 .8 .9
1000 1 1

Permite animar la propiedad que se le pasa como argumento.
Le ponemos set<propiedad>() y get<propietat> para obtener valores.
Si el objeto no tiene set, podemos añadirlo, podemos hacer una clase envoltorio o crear ValueAnimator. Si se especifica un solo valor, se entiende que es el final. El objeto tiene que tener un get<propiedad> para obtener el valor incial.
Ejemplo AnimatorSet:
AnimatorSet bouncer = new AnimatorSet();

bouncer.play(bounceAnim).before(squashAnim1);
bouncer.play(squashAnim1).with(squashAnim2);
bouncer.play(squashAnim1).with(stretchAnim1);
bouncer.play(squashAnim1).with(stretchAnim2);
bouncer.play(bounceBackAnim).after(stretchAnim2);

ValueAnimator fadeAnim = ObjectAnimator.ofFloat(pilota, "alpha", 1f, 0f);
fadeAnim.setDuration(250);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(bouncer).before(fadeAnim);

animatorSet.start();

Dispondremos de un conjunto de listeners para saber que esta pasando en la animación y programar si queremos callbacks, onAnimationStart(), onAnimationEnd(), onAnimationUpdate(), onAnimationRepeat(), etc. esto nos permitirá responder por ejemplo al final de una animación (onAnimationEnd()).

ValueAnimatorAnimator fadeAnim = ObjectAnimator.ofFloat(pilota, "alpha", 1f, 0f);
fadeAnim.setDuration(250);
fadeAnim.addListener(new AnimatorListenerAdapter() {
   public void onAnimationEnd(Animator animation) {
      pilotes.remove(((ObjectAnimator)animation).getTarget());
   }
}

La animación por llaves consiste en especificar llaves formadas por tiempo/valor. Cada valor tiene su propio interpolador para controlar el comportamiento de la animación en el intervalo definido.
Se hacen servir métodos ofFloat(), etc.

Keyframe kf0 = Keyframe.ofFloat(0f, 0f);
Keyframe kf1 = Keyframe.ofFloat(.5f, 360f);
Keyframe kf2 = Keyframe.ofFloat(1f, 0f);
PropertyValuesHolder rotacio = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2);
ObjectAnimator animacio = ObjectAnimator.ofPropertyValuesHolder(target, rotacio)
animacio.setDuration (5000ms);


Los objetos heredan de View (prácticamente todos los estudiados) disponen de propiedades translationX, translationY, rotation, rotationX, rotationY, alpha, etc... para ser manipulados con mayor facilidad. Por ejemplo:

ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f);

La clase ViewPropertyAnimator permite animar varias propiedades en paralelo, hay tres maneras de hacer lo mismo:
Con ObjetcAnimator:
ObjectAnimator animX = ObjectAnimator.ofFloat(myView, "x", 50f);
ObjectAnimator animY = ObjectAnimator.ofFloat(myView, "y", 100f);
AnimatorSet animSetXY = new AnimatorSet();
animSetXY.playTogether(animX, animY);
animSetXY.start();

Con PropertyValuesHolder:
PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x",50f);
PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 100f);
ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvyY).start();
Con ViewPropertyAnimator (los hace de forma simultanea):
myView.animate().x(50f).y(100f);

También podemos poner las animaciones en un XML en res/anim/, por ejemplo:
animacion.xml
<set android:ordering="sequentially">
   <set>
      <objectAnimator
         android:propertyName="x"
         android:duration="500"
         android:valueTo="400"
         android:valueType="intType"/>
      <objectAnimator
         android:propertyName="y"
         android:duration="500"
         android:valueTo="300"
         android:valueType="intType"/>
 </set>
      <objectAnimator
         android:propertyName="alpha"
         android:duration="500"
         android:valueTo="1f"/>
</set>


En el programa tendremos que poner:
AnimatorSet set = (AnimatorSet)
AnimatorInflater.loadAnimator(myContext,R.anim.animacion);
set.setTarget(myObject);
set.start();

Animaciones de vistas

Se puede utilizar el sistema de animaciones de vistas para realizar animaciones interpoladas de controles de vista.
Una animación de interpolación puede realizar una serie de transformaciones simples (posición, medida, rotación y transparencia) en el contenido de un objeto View. Por lo tanto, si por ejemplo tenemos un objeto TextView, se puede mover, girar, crecer o reducir la medida del texto. Si se tiene una imagen de fondo, la imagen de fondo será transformada juntamente con el texto. El paquete animation ofrece todas las clases que se utilizan en una animación de interpolación.
Una secuencia de instrucciones de animación define la animación de interpolación, definida por cualquier XML o código Java. Igual que con la definición de un diseño, se recomienda un archivo XML porque es mas facil de leer, reutilizable...
Las instrucciones de animaciones definen las transformaciones que se desean producir, cuando van a ocurrir y cuanto tiempo tienen que adoptar para la aplicación. Las transformacioens pueden ser secuenciales o simultanias, por ejemplo, puede hacer que el contenido de un TextView se mueva de izquierda a derecha y después girar 180 grados, o hacerlo de forma simultanea.
Cada transformación necesita un conjunto de parámetros específicos para esta transformación (medida inicial, angulo inicial, final del angulo, final de la medida final, etc.), y también un conjunto de parámetros comunes (por ejemplo, hora de inicio y de paro). Para hacer varias transformaciones que se sucedan simultaneamente, se les da la misma hora de inicio, pero para que sean secuenciales, hace falta calcular el tiempo de inicio más la durada de la transformación anterior.
El archivo de animación XML pertenece al res/anim/ directorio del projecto Android.
El archivo tiene que tener un elemento raiz, será único: <alpha>,<scale>,<translate>,<rotate>, elemento interpolador  o <set>, elemento que tiene grupos de elementos (que pueden incluir otro <set>). Por defecto, todas las instrucciones de animaciones se aplican simultaneamente. Para hacerlos se producen de forma secuencial, se tiene que especificar el startOffset atributo.
Por ejemplo:

set android:shareInterpolator="false">
   <scale
   android:interpolator="@android:anim/accelerate_decelerate_interpolator"

   android:fromXScale="1.0"
   android:toXScale="1.4"
   android:fromYScale="1.0"
   android:toYScale="0.6"
   android:pivotX="50%"
   android:pivotY="50%"
   android:fillAfter="false"
   android:duration="700" />
   <set android:interpolator="@android:anim/decelerate_interpolator">
      <scale
        android:fromXScale="1.4"
        android:toXScale="0.0"
        android:fromYScale="0.6"
        android:toYScale="0.0"
       android:pivotX="50%"
        android:pivotY="50%"
        android:startOffset="700"
        android:duration="400"
        android:fillBefore="false" />
      <rotate
        android:fromDegrees="0"
        android:toDegrees="-45"
        android:toYScale="0.0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:startOffset="700"

        android:duration="400" />
   </set>
</set>


Con este XML guardado como salto.xml en res/anim del directorio del proyecto, el siguiente código hará referencia a él y aplicará a una ImageView el objeto de la disposición.
ImageView imatge = (ImageView) findViewById (R.id.imatge);
Animation a = AnimationUtils.loadAnimation (això, R.anim.salt);
imatge.startAnimation (a);

Animaciones de recursos draw

Android permite cargar una serie de recursos Drawable uno tras otro, para crear una animación. Esta es una animación tradicional en el sentido que se crea con una secuencia de imagenes diferentes, como el rollo de una película. La clase AnimationDrawable es la base para las animaciones Drawable.
El archivo XML de este tipo de animaciones pertenece al directorio res/drawable/ del proyecto de android. En este caso, las instrucciones estan en orden y la duración para cada cuadro de animación.
El archivo XML consiste en un elemento <animation-list> como el nodo raiz y la serie de nodos hijos <item> que definen cada uno un marco: un recurso dibujable para el marco y la durada para cada frame.
fondo.xml
<animation-list
   xmlns:android="http://schemas.android.com/apk/res/android"
   android:oneshot="true">
   <item
      android:drawable="@drawable/rocket_thrust1"
      android:duration="200" />
   <item
      android:drawable="@drawable/rocket_thrust2"
      android:duration="200" />
   <item
      android:drawable="@drawable/rocket_thrust3"
      android:duration="200" />
</animation-list>

Código:
AnimationDrawable a;
public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.main);
   ImageView imatge = (ImageView) findViewById(R.id.imatge);
   imatge.setBackgroundResource(R.drawable.fons);
   a = (AnimationDrawable) imatge.getBackground();
}
public boolean onTouchEvent(MotionEvent event) {
   if (event.getAction() == MotionEvent.ACTION_DOWN) {
      a.start();
      return true;
   }
   return super.onTouchEvent(event);
}

4. Desarrolla una aplicación que muestre una animación en forma de secuencia repetitiva en la que un texto siga una forma de recuadro. Hazlo con programación Java y con código XML.

5. Crea una animación de una imagen que va rebotando dentro de un contenedor.

Soluciones (Cambiar el android manifest para las diferentes actividades).


PDF

Para mas detalles, consultad Android developers.




Utilización de librerias multimedia integradas Media Playback y Servicios

Media Playback

El framework multimedia de android incluye soporte para la reproducción de varios tipos de medios, de manera que se le puede integrar fácilmente audio, vídeo e imágenes en las aplicaciones.
Los recursos van en el directorio RAW.
El audio tiene más juego que el video... ¿Si se intenta hacer un streaming por bluetooth como marcas prioridad para el audio? Tenemos el AudioManager que permite manipular todo lo que afecta al tema de audio.

En ambos casos (audio o video) hay que poner permisos si queremos hacer streaming.
<uses-permission android:name="android.permission.INTERNET" />

Si la aplicación tiene que mantenerse en pantalla se puede usar MediaPlayer.setScreenOnWhilePlaying() o los métodos MediaPlayer.setWakeMode(), con sus permisos:
<uses-permission android:name="android.permission.WAKE_LOCK" />

La clase MediaPlayer permite obtener, decodificar y reproducir audio y video. Una URL internas, listas de audio, fotos... y URLs externas (streaming).

Los formatos soportados se pueden ver en:

Si queremos reproducir un fichero en local (RAW) tendremos que guardarlo en el directorio /res/raw:

MediaPlayer mediaPlayer = MediaPlayer.create(context, R.raw.audio1);
mediaPlayer.start();

Si queremos usar el tema del streaming, tendremos que poner:

String url = "http://........";
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDataSource(url);
mediaPlayer.prepare(); // puede tardar en cargar en el buffer.
mediaPlayer.start();

El método prepare() no se puede llamar nunca desde el hilo de la IGU (Interficie Grafica de Usuario). Imaginate que haces una sopa de letra y quieres música de fondo, si lo haces directamente en la activity bloquearía la interficie hasta que se cargue el buffer, la solución es meterlo en un servicio.

Hay un método llamado prepareAsync() que crearía un servicio de forma automática. Hará falta un listener, que llamará un callback y se disparará cuando este cargado.
El MediaPlayer funciona como una máquina de estados.

http://cfile23.uf.tistory.com/original/191F6F184C1E1BBE07D17F

Una vez se ha utilizado un medio, se necesita liberar con el método release(), es importante que se tenga en cuenta que cuando el usuario cambia la orientación se  vuelve a crear un objeto MediaPlayer, porque se vuelve a llamar a onCreate(), por eso se necesita liberar los recursos.

media.release();
media=null;

Si no queremos este comportamiento podemos guardar el estado y gestionarlo de manera manual.
Haciendo que cuando pasa un cambio de horientación o el teclado se oculta, entonces ejecuta el método por defecto que detecta cambios de configuración (onConfigurationChanged()) y se disparará teniendolo puesto en la activity. El objeto newConfig tendrá la información que podrás preguntar el estado.
Podiendo mirar la horientación podremos hacer condicionales y permite detectar que se disparará cuando hay un cambio.
Después llamará al onCreate().

Por ejemplo, para hacer un cambio de horientación:


















Código:

<manifest package="es.com.blogspot.fmesasc.cambiohorientacion">

<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme">

<activity android:name=".MainActivity" android:configChanges="orientation|keyboardHidden|screenSize" android:label="@string/app_name">

<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>

</activity>

</application>

</manifest>


Como se puede ver, hemos añadido android:configChanges="orientation|keyboardHidden|screenSize" para que detecte la rotación de pantalla o la ocultación de teclado en este caso, para que esto funcione tendremos que sobreescribir una función:

package es.com.blogspot.fmesasc.cambiohorientacion;
import android.content.res.Configuration;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
        } else if (newConfig.orientation ==
                Configuration.ORIENTATION_PORTRAIT){
            Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
        }
    }
}


onConfigurationChanged únicamente funcionará si esta declarado en el manifest, de esta manera, podemos comprobar la nueva orientación y la comparamos para saber si es horizontal o vertical (Landscape o Portrait). De esta manera mostramos el toast del ejemplo inicial indicando el tipo de orientación.

Descargar.

Servicios

Los servicios son componentes de una aplicación que realizan operaciones de larga duración que no requieren la interacción de un usuario, o que ofrecen funcionalidades para otras aplicaciones. Normalmente envian correos, sincronizan datos o reproducen medios.
Igual que hay una activity en el manifest, tendremos que declarar también los servicios en el manifest. La comunicación es similar al sistema de comunicación que tienen actividades, los intents. Los servicios heredan de services o subclase de este. No tienen nunca interficie.
Cada servicio se declarará en el AndroidManifest.xml con <service>.
Los servicios se inician con:
Context.startService() y Context.bindService().
Los servicios se ejecutan como hilo principal del proceso. Eso implica que si consume muchos recursos se recomiende hacer uno nuevo.
La clase IntentService es una implementación estandard de Service que funciona como un hilo propio.
Entonces, un servicio no es un proceso separado. Se ejecuta en el mismo proceso que la aplicación. Tampoco es un hilo separado.
Los servicios se utilizan para hacer tareas en segundo plano, notificando cuando esta realizado. Se inicia con Context.startService(). Este concepto es muy similar al de activityResult.
Existe la posibilidad de exponer a otras aplicaciones parte de una aplicación en concreto. Se utiliza el método de clase Context.bindService().
Podemos especificar que el servicio este asociado a un otro proceso con la anotación de dos puntos (:). Los dos puntos indican que el proceso será privado a la aplicación, sino será global para las aplicaciones.
Por ejemplo:
<service
   android:name="WordService"
   android:process=":proces1"
   android:icon="@drawable/icon"
   android:label="@string/nom_servei"
   >
</service>


Otro ejemplo:
public class ServeiMP extends Service implements
MediaPlayer.OnPreparedListener {
    private static final ACTION_PLAY = "com.example.action.PLAY";
    MediaPlayer mMediaPlayer = null;
     public int onStartCommand(Intent intent, int flags, int startId) {
     ...
     if (intent.getAction().equals(ACTION_PLAY)) {
     mMediaPlayer = ... // inicialització
     mMediaPlayer.setOnPreparedListener(this);
     mMediaPlayer.prepareAsync(); }
     }
     /** cridat quan MediaPlayer està llest */
     public void onPrepared(MediaPlayer player) {
     player.start();
     }
}

Será necesario controlar los errores que se producen de manera asíncrona.
En onStartCommand le pasamos un intent, con la pista de audio que queremos que suene, con el ACTION_PLAY tendremos que sabemos si esta sonando o no la música. Al pasarle el intent, este le envía la pista de audio que nosotros queremos reproducir. Una de lsa cosas a tener en cuenta que podemos tener errores, por lo que hay otra interfaz que se llama Media.Player.OnErrorListener, haciendo override en onError podremos configurarlo.

Puedes bajarte un ejemplo de un servicio que permite descargar:
Descargar.

public class Servei extends Service implements MediaPlayer.OnErrorListener{
   MediaPlayer mMediaPlayer;
   public void initMediaPlayer() {
      // inicia MediaPlayer
      mMediaPlayer.setOnErrorListener(this);
   }
 @Override
 public boolean onError(MediaPlayer mp, int what, int extra) {
      // The MediaPlayer esta en estado de error.
    }
}


Tendrá un boton que dice descargas, y un toast, mientras tanto podemos hacer lo que queremos, cuando este descargado, el servició terminará. Si le das otra vez el botón la descarga se vuelve a realizar.

Mira el código o descárgate el zip.

Primero tenemos el IntentService.
En el onCreate solo llamamos al layout.
En el onCLick hacemos un intent del servicio, creamos un mensaje que le pasamos un handler y este se encargará si esta descargado o no. Eso es porque el handle es asincrono, por lo tanto, no bloquea nada. Cuando reciba el mensaje se disparará el handleMessage, si el resultado esta bien saldrá correcto, solo cuando recibe.
En el intent le pasamos un mensaje y el mensajero, en el intent también le pasamos un setData, que se utiliza para obtener el nombre del fichero. El putExtra será precisamente para poder indicar el path para saber donde tiene que guardar.

El servicio tiene un entero, result, que si todo va bien le pondremos okey en vez de result_canceled. en el onHandleINtent, que es asincrono y obtenemos el urlpath y de esta manera ponemos el nombre del fichero y hacemo sun fichero output para guardar. sino lo borraremos.
La lectura la haremos con el inputStreamReader, en un principio a fluxEntrada y fos serán iguales. Técnicamente lo que hace es byte a byte escribirlos, cuando es -1 significa que hay que cerrar el archivo.

Ponemos la ruta, conexión, y el InputStreamReader va poniendo los bytes y los convierte en UNICODE. Si es pdf o algo hay que anular los readers que los convierten a UNICODE. Normalmente se llaman fis y fos.
Después tenemos un while que lee carácter a carácter y si no es igual a menos 1 escribe (Para un pdf necesitaremos eliminarlo).

Cuando acaba le ponemos result_ok y en el .java veremos que ha devuelto RESULT_OK. Si hay problemas hay un catch, y el finally se ejecuta porque finaliza correctamente o hay un fallo.

Cuando ya esta, cogemos el mensaje y le ponemos como argumento 1 que todo ha ido correctamente y como objeto le ponemos la ruta del objecto.
Si hay algún problema te envia la respuesta.

Un servicio puede estar encendido mientras la actividad esta en pause, pero la CPU funcionaria, el wifi no, entonces podemos programarle que queremos que haga. Para desactivarlo o cambiarlo tenemos que poner wifiLock.acquire() o wifiLock.release(); de esta manera controlamos si funciona o no. Se pondria setWakeMode para indicar que tiene que hacer.

Si queremos también se puede mostrar una notificación. Se programa con Notification, para hacerlo se tienen que enviar mediante un intent especial, con PendingIntent. Allí podremos poner la información.

Actividades:
  1. Desarrolla una aplicación para android que reproduzca una pista de música guardada en los recursos del dispositivo. La aplicación tiene que tener botones para parar, pausar y iniciar la pista de música. Tiene que mostrar el tiempo de reproducción.
    Solución 1.
    Solución profe.
  2. A partir del ejercicio anterior, crea un servicio en primer plano que realice la reproducción de música mostrando con una notificación de información al usuario en la barra de estado.
    Solución.


Apuntes.
Ejercicios.

Para más información, consultad:
http://developer.android.com/guide/topics/manifest/manifest-intro.html

dissabte, 23 de gener del 2016

Lectura de ficheros en Java


Los programas usan variables para almacenar información:
  • Los datos de entrada.
  • Los resultados calculados.
  • Los valores intermedios generados a lo largo del cálculo. 
Toda esta información es efímera: cuando acaba el programa, todo desaparece. Pero para muchas aplicaciones, será importante poder almacenar datos de manera permanente.
Un archivo o fichero lo podriamos definir como:
"Un conjunto de bits almacenados en un dispositivo, y accesible a través de un camino de acceso (pathname) que lo identifica."

Esta versión de bajo nivel, si bien es completamente cierta, es demasiado simple...
Por ello definiremos varios criterios para distinguir diversas subcategorías de archivos. Estos tipos de archivo se diferenciarán desde el punto de vista de la programación: cada uno de ellos proporcionará diferentes funcionalidades (métodos) para su manipulación.
El criterio de contenido:
Sabemos que es diferente manipular números que Strings, aunque en el fondo ambos acaben siendo bits en la memoria del ordenador. Por eso, cuando manipulamos archivos, distinguiremos dos clases de archivos dependiendo del tipo de datos que contienen:
  • Los archivos de caracteres (o de texto)
  • Los archivos de bytes (o binarios)
Un fichero es aquel formado exclusivamente por caracteres y que puede crearse y visualizarse usando un editor. Las operaciones de lectura y escritura trabajarán con caracteres. Por ejemplo, los ficheros con código java son ficheros de texto. En cambio un fichero binario ya no está formado por caracteres sino que los bytes que contiene pueden representar otras cosas como números, imágenes, sonido...
El criterio del modo de acceso.
Existen dos modos básicos de acceso a la información contenida en un archivo:
  • Secuencial.
  • Acceso directo.
En el modo secuencial la información del archivo es una secuencia de bytes (o caracteres) de manera que para acceder al byte (o carácter) i-ésimo (se nombra de esa manera cuando estamos hablando de un caso general y que por lo tanto no conocemos el número exacto) se ha de haber accedido anteriormente a los i-1 anteriores.
En el modo de acceso directo nos permite acceder directamente a la información del byte i-ésimo. Un ejemplo muy conocido de acceso directo lo tenemos con los vectores (arrays).

Primero podremos observar un ejemplo de código que escribe en modo stream:


import java.io.FileInputStream; 
import java.io.FileOutputStream; 
import java.io.IOException;
/** * Clase que lee y escribe el fichero en modo Stream */
public class Stream {
   public static void main(String[] args) throws IOException {
        FileInputStream in = null; 
        FileOutputStream out = null;
        try{
            in = new FileInputStream("entrada.txt"); 
            out = new FileOutputStream("salida.txt"); 
            int c;
            while ((c = in.read()) != -1) {
                System.out.println(c);                 
                out.write(c);             
            }
        }finally {
            if (in != null) {
                in.close(); 
            }
            if (out != null) {
                out.close();             
            }
        }



    }
}
Descargar.

Otra opción es ir cargandolo en memoria:


import java.io.BufferedReader; 
import java.io.FileReader;
 import java.io.FileWriter; 
import java.io.PrintWriter;
 import java.io.IOException;
/** * Clase que lee y escribe el fichero en memoria */ 
public class ReaderWritter {
    public static void main(String[] args) throws IOException {
        BufferedReader inputStream = null;
        PrintWriter outputStream = null;
        try {
            inputStream = new BufferedReader(new FileReader("entrada.txt")); 
            outputStream = new PrintWriter(new FileWriter("salida.txt"));
            String l;
            while ((l = inputStream.readLine()) != null) {
                System.out.println(l); 
                outputStream.println(l); 
            }
        } finally {
            if (inputStream != null) {
                inputStream.close();
                }
            if (outputStream != null) {
                outputStream.close();
                }
        }
    }
}
Descargar.


Descarga todo.

divendres, 22 de gener del 2016

Diagramas de implementación

El diagrama de implementación lo podemos dividir básicamente en:
  • Diagrama de paquetes.
  • Diagramas de componentes.
  • Diagramas de despliegue.
Todos nos servirán para especificar de alguna manera como ha de ser llevada la implementación del resultado del analisis del dominio que estamos tratando.

El diagrama de componentes forma parte, junto al diagrama de paquetes, de la vista de implementación.
Los diagramas de componentes representan las dependencias entre varios componentes físicos del sistema. Muestra la organización (contención de unos dentro de otros) y las dependencias entre componentes de software.
Un componente representa un fichero fuente, una libreria o un ejecutable. Los componentes son artefactos (elementos fabricados) que forman parte de la implementación del sistema. Un componente se representa gráficamente como un rectangulo con una elipse pequeña y dos rectangulos pequeños que sobresalen del lado.
Normalmente se consideran componentes de software de tres niveles:
  • Código fuente.
  • Librerias.
  • Ejecutables.
El nivel de código fuente muestra las dependencias de compilación entre ficheros.
En c++ serian las dependencias del include, por ejemplo.
En c# serian las dependencias del using.
En java serian las dependencias del import.
Cada clase del modelo lógico se puede realizar en el diagrama de componentes de código fuente en dos componentes: la especificación y el cuerpo. En C++, por ejemplo, una especificación corresponde a un archivo con un sufijo .hxx y un cuerpo corresponde a un archivo con sufijo .cxx.

El nivel de tiempo de ejecución muestra el mapeo de las clases a librerias en tiempo de ejecución.
La siguiente figura ilustra que la libreria Trade (Trade.dll) depende de la clase Slate (Slate.cls) y la clase Trade (Trade.cls).
El nivel de ejecutables muestra las interficies y las dependencias de las llamadas entre programas ejecutables.

Esta figura muestra que el ejecutable Trade se comunica con el ejecutable Contracts a través de la interficie TradeContract. También se comunica con la libreria Trade con la interficie TRade.

Los diagramas de despliegue (deployment) muestran la configuración del sistema en tiempo de ejecución a partir de ilustrar como los varios procesos se distribuyen en procesadores, ordenadores o otros dispositivos diferentes.
La vista de despliegue muestra la configuración de nodos de procesamiento en tiempo de ejecución y los componentes, procesos y objetos que viven dentro.
El diagrama de despliegue contiene básicamente:
  • Nodos: Un objeto en tiempo de ejecución que representa un recurso computacional (que generalmente tiene como mínimo memoria, y a menudo capacidad de procesar). Los esteriotipos permiten precisar la naturaleza del equipo, dispositivos, procesadores, memoria...
  • Conexiones: Muestra el camino de comunicación entre varios nodos. La asociación puede tener un esteriotipo que indica la naturaleza de la comunicación (como por ejemplo, el tipo de canal o red).


1. El entorno de ejecución de una empresa que presta los servicios a internet se compone de tres servidores y dos clientes. El servidor lógico de negocio 1 contiene un componente llamado Jar1 que contiene la lógica del negocio de una aplicación web. El servidor lógica de negocio 2 contiene el mismo componente, y el tercer servidor, que se encarga de la capa web, se llama servidor aplicación web y contiene el componente War1. Este componente utiliza la interficie InterfícieJar1 implementada por Jar1 en los dos servidores que contienen el componente.
Los clientes web contienen un navegador y utiliza la interficie InterfícieWar1 del componente War1. El cliente "rich client" tiene un componente ClientJar1 que utiliza la interfície del módulo Jar1 del servidor lógico del negocio 1 mediante su interfaz.
a) ¿Para representar esta situación que tipo de daigrama UML utilizarias?
Diagrama de despliegue.
b) Dibujalo.

diumenge, 17 de gener del 2016

Diagramas de interacción

Introducción

Una interacción es la especificación del comportamiento de un caso de uso o de una operación en terminos de secuencia de mensajes entre objetos. Estos mensajes contienen estimulos que pueden ser peticiones de ejecución de operaciones o señales. Se llama hilo de ejecución a una secuencia de imagenes.

Colaboraciones

Una colaboración es un conjunto de papeles, de clasificadores o de instancias, y de papeles de asociaciones entre los objetos que intervienen en una interacción. Las colaboraciones se utilizan por coherencia entre las clases y asociaciones definidas en el modelo estático y las asociaciones y los objetos definidos en el caso de uso. Las colaboraciones se pueden definir a partir de clasificadores o de instancias.
A veces nos interesará representar multiobjetos, que representan un conjunto de objetos de un papel con multiplicidad más grande que 1 dentro de una asociación.
UML ofrece 3 diagramas para representar interacciones y colaboraciones:

  • El diagrama de comunicación, pone énfasis en la descripción de la colaboración.
  • El diagrama de secuencia, que pone énfasis en la sucesión temporal de mensajes en una interacción.
  • El diagrama de actividades, que sirve para describir el estado de una actividad.

Diagrama de comunicación

El diagrama de colaboración es la representación de una interacción.
Parte del diagrama estático, sobre el cual se representan los mensajes de la interacción.
Cada mensaje tiene la siguiente especificación:
PREDECESORES GUARDA EXPRESIONES_SECUENCIA VALORES_RETORNO FIRMA
PREDECESORES: Lista mensajes predecesores '('NUM_SEQ, NUM_SEQ ')'
GUARDA: Condición que se tiene que cumplir para que se envíe el mensaje.
EXPRESIONES_SECUENCIA: Num_seq '['RECURRENCIA''],...,':'
RECURRENCIA: '*' '['CLAUSULA_ITERACIÓN']'
VALORES_RETORNO: Valores de retorno como consecuencia del proceso activado por el mensaje VALORES_RETORNO ',' VALORES_RETORNO ... ':='
FIRMA: Nombre estímulo y lista de argumentos.
Se puede indicar también la creación de objetos (new), destrucción (destroyed) y enlaces (transient).
Mensajes simples: corresponden a una simple ejecución dentro de un hilo de ejecución.
Mensajes asíncronos: estos mensajes se dan cuando el cliente envía un mensaje al subministrador y este acepta el mensaje. La clase que emite se espera a recibir el resultado de la operación asociada al mensaje.
Mensajes asíncronos: en este caso, la clase emisora envía un mensaje al subministrador y se continua ejecutando sin esperar que llegue el resultado de la clase receptora. En estos casos habitualmente la clase receptora pondrá en cola la ejecución de la petición recibida.
Mensaje de respuesta:
<- - - - - - - - - - - - -

Diagramas de secuencia

A diferencia de los diagramas de colaboración, los de secuencia no representan explicitamente el papel de las asociaciones. En cambio, si que representan el paso del tiempo y la durada de los mensajes.
El tiempo se representan hacia abajo, y no esta necesariamente a escala.
El horizontal, y en franges sucesivas, se representan los diferentes papeles de los clasificadores que participan en la interacción.
Los mensajes circulan de izquierda a derecha y las respuestas al revés.
Se llama línea de vida a un elemento que simboliza la existencia del papel en un cierto periodo de tiempo. Se representa por una línea vertical discontinua que va de la creación hasta la destrucción del objeto.
Para representar la destrucción de un objeto se pone una x al final de la línea de vida.
Durante la vida de un objeto pueden haber varios constructores según las condiciones que emite el mensaje.
Una activación es una parte de la línea de vida durante la cual un determinado papel ejecuta una acción o bien otros papeles ejecutan otras acciones como consecuencia de una acción ejecutada por el primero.
Las activaciones coinciden con el envío de un mensaje y la recepción de una respuesta.
Si haces llamadas reflexivas, estas se representan con otro recuadro ligeramente desplazado.
Los mensajes pueden ser del mismo tipo que los diagramas de colaboración, y las flechas se representan igual.
El orden de ejecución se representa de arriba a abajo en el tiempo.
No se identifican los números de secuencia porque están implícitos.
Pueden salir dos flechas de un mismo punto de activación si se envían dos mensajes a la vez.
Los mensajes de retorno se representan con una línea discontinua.

Concreciones y ejemplos:
Los diagramas de casos de uso, se presentan una vista externa del sistema. Los diagramas de interacción, que incluyen los de secuencia, describen como los casos de uso se realizan (se hacen realidad) como interacción entre conjuntos de objetos.
Los diagramas de secuencia muestran el flujo de mensajes (events) entre diversas instancias al largo del tiempo. De hecho, ofrecen una manera formal de especificar un escenario.
Se puede ver inmediatamente la orden en que se envían los mensajes porque el tiempo es una dimensión explícita del diagrama (eje vertical).
Cada instancia se representa mediante un recorrido vertical diferente.
Es una vista gráfica de un escenario (un camino concreto de un diagrama de casos de uso) que ilustra las interacciones entre objetos como secuencia temporal. De hecho, se puede crear a partir del caso de uso que se describe.
Actores y objetos: son los elementos que se comunican. Como tanto los objetos como los actores, son instancias, se hace uso de la nomenclatura del objeto con dos puntos y el nombre subrayado.
Lineas de vida:  son unas lineas que representan la vida de los objetos (o actores) a lo largo del tiempo. El tiempo va de arriba hacia abajo. La línea se hace gorda cuando este objeto esta ejecutando una operación. Decimos que el objeto es activo en ese momento. A menudo, los objetos dejan de existir. Para indicar el punto donde un objeto se destruye, se pone un aspa o cruz al final de la línea.
Mensajes: se representan con flechas que van de emisor a receptor y están etiquetadas con el mensaje que envían. La recepción de un mensaje hace que el objeto inicie su actividad. El retorno de la llamada se indica con una flecha a trozos. Sólo es necesario ponerlo si queremos hacer explicito lo que se devuelve. Si no, se puede suponer que devuelve cuando la zona activa del receptor acaba.
Los diagramas de secuencia permiten hacer uso de algunas estructuras de control, que van muy bien para simplificarlos.
Cuando hacemos uso de estructuras de control no estamos representando sólo un escenario concreto, sino que estamos generalizando.
Ejemplo de mensaje entre dos objetos:
Ejemplo de ejecución condicional del diagrama de secuencia.
El diagrama indica dos maneras de expresar alternativas. Una haciendo una parte de la vida condicional y otra condicionando el envío del mensaje con una guarda.

Si hiciese falta un mensaje a cada uno del conjunto de objetos, podemos simplificar el diagrama representando el conjunto de objetos con un objeto múltiple como se muestra en la figura superior.

A veces un objeto puede crear o eliminar otro objeto.
Esto se puede representar como mensajes especiales.
Un mensaje de creación no apunta a una zona activa de la línea de vida, sino que apunta al objeto mismo (Tiene que estar mas abajo que los otros).
El mensaje de destrucción apunta hacia un aspa al final de la línea de vida que representa el final de la vida del objeto.
Ejemplo de creación, destrucción y llamadas a métodos propios.
Diagramas de secuencia vs colaboración
El diagrama de colaboración es, como el diagrama de secuencia, otra realización de los casos de uso. Son una combinación de los diagramas de objetos y los de secuencia. Muestra el flujo de sucesos entre objetos.
Ejemplo de diagrama de colaboración:
Recordamos que el diagrama de colaboración muestra como los objetos trabajan los unos con los otros enviando mensajes y intercambiando datos. Los diagramas de colaboración y secuencia son dos vistas diferentes de las interacciones entre objetos. Las dos vistas representan exactamente la misma información.
El diagrama de secuencia refuerza la vista temporal, pero es necesario seguir el diagrama para saber quien relaciona con quien.
El diagrama de colaboración refuerza las relaciones que se establecen entre los objetos, pero hace falta seguir el diagrama para saber el orden de los mensajes.


Diagrama de actividades

El diagrama de actividades es una variante del diagrama de estado y del diagrama de interacción porque sirve para describir el estado de una actividad que es el conjunto de acciones secuenciales o concurrentes en la cual pueden intervenir varios clasificadores.
Estos diagramas tienen muchos elementos en común con los diagramas de colaboración y con los estados. Los conceptos de transición, estado, evento, señal, flujo de control y objetos son el mismo.
Los elementos específicos son:

  • Estados de acción.
  • Flujos de objetos.
  • Estados de flujos de objetos.
  • Estados de subactividades.
  • Swimlanes
  • Iconos de control.

Los diagramas de actividades se utilizan para capturar flujos de actividades y secuencias de decisiones. Son ideales para representar el comportamiento interno:

  • de un método (la realización de una operación).
  • de un caso de uso.
  • de un proceso de negocio (workflow).
Se pueden entender como una extensión de los diagramas de estado, donde cada estado se caracteriza por estar ejecutando una actividad y, donde todas las transiciones son automáticas cuando se acaba la actividad. Ahora bien, se enriquece de otros elementos:
  • Puntos de decisión: condiciones que cambian el flujo de las acciones.
  • Caminos de ejecución concurrentes.
  • Señales, con puntos de envío y recepción explícitos.
  • Objetos afectados por las acciones.
En UML 2.0 es posible representar condiciones, sincronizaciones, señales, tokens...

Las actividades se enlazan mediante transiciones automáticas, y a través de estas pasarán de una actividad a otra.
Cuando una actividad acaba, se desencadena el paso a la siguiente actividad, automáticamente.
Las actividades no tienen transiciones internas ni transiciones desencadenadas por eventos. Podríamos decir que las transiciones se disparan de manera automática, cuando finaliza una actividad.
Es una variación de una máquina de estados en la cual los estados representan la ejecución de acciones o subactividades y las transiciones se disparan por la finalización de las accioens o subactividades.
El diagrama de actividades representa la máquina de estados de un procedimiento.

Ramificaciones y fusiones:
Una ramificación (branch) es una división del flujo de actividades en dos hilos alternativos. Cada vez que se ejecute el diagrama, se optará por uno o otro dependiendo de la condición.
La condición esta especificada como guarda a cada una de las conexiones que salen.
Una fusión (merge) es la unión de dos hilos alternativos en un solo hilo.
Las ramificaciones y las fusiones se representan con un rombo vacío.

Divisiones y uniones:
Las barras de sincronización permiten, igual que las ramificaciones y fusiones, dividir el flujo de actividades en varios hilos y después adjuntarlos de nuevo. La diferencia esta en que ahora no son hilos alternativos, sino hilos concurrentes. Eso quiere decir que siempre se ejecutaran los dos hilos y siempre se ejecutaran a la vez.
La barra que separa los hilos la llamamos barra de fork, y la barra que adjunta los hilos la llamamos barra de join. Hace falta decir que la barra de join tiene una consecuencia, si un hilo llega antes que el otro al punto de join, necesitará esperar a que el otro llegue, entonces es un punto de sincronización.
Carriles o swimlanes
Los carriles sirven para separar las actividades que realizan diferentes objetos o actores. Unas lineas gordas a modo de corchea, dividen en carriles el diagrama. A cada carril le pondremos solamente las actividades que hará el actor o objeto al cual pertenece el carril.
Flujo de objetos: Entradas y productos
A menudo, las actividades requieren de la existencia de objetos o generan objetos o cambian su estado. Estos objetos se pueden añadir al diagrama con las convenciones del diagrama de objetos. Podemos relacionar los objetos con las actividades haciendo uso de flechas que indican el flujo del objeto.





1. Partiendo del siguiente diagrama de secuencia, responde a las preguntas:
a) ¿Qué objetos (nombre y clasificador) intervienen en el diagrama?
Objeto: Q1:C1
  • Nombre: Q1
  • Clasificador: C1
Objeto: Q2:C2
  • Nombre: Q2
  • Clasificador: C2
Objeto: Q3:C3
  • Nombre: Q3
  • Clasificador: C3
Objeto: :C4
  • Nombre: / Qualsevol
  • Clasificador: C4
b) ¿Qué objetos son creados y destruidos durante la interacción?
Creados: Q2:C2
Destruidos: Q3:C3

c) Dibuja el diagrama de comunicación equivalente.


2. 
a) Que tipo de diagrama UML es?
Diagrama de actividades.
b) Segun lo que se representa en el diagrama, en el caso que se produzca un error en el procesamiento de una comanda, que puede hacer el usuario? Que le pasa al sistema?
El usuario no puede hacer nada.
c) Dibuja el diagrama de estados de una comanda a partir de la información representada en este.



Diagramas de casos de uso

Introducción

Los diagramas de casos de uso de UML sirven para mostrar las funciones de un sistema de software desde el punto de vista de sus interacciones con el exterior y sin entrar en la implementación detallada de las funciones en cuestión. Estos diagramas se utilizan en la recogida de documentación y en la fase de análisis.

Actores

La finalidad de un software es proporcionar información a personas, máquinas o dispositivos externos en general. Un actor es un conjunto de papeles de una entidad exterior en relación con el sistema de software considerado. Para ser actor, una entidad exterior tiene que cumplir dos condiciones:

  • Ser autónomo respecto al software (Por ejemplo: un motor eléctrico, pero no una CPU).
  • Tener una relación directa con el software o con entidades exteriores que esten subordinadas a este software.
Un actor es un clasificador pero no es un estereotipo. Si un conjunto de entidades exteriores hacen el mismo papel las representaremos con un mismo actor. Los actores pueden tener relaciones de especialización o generalización mediante herencia (un actor A es una especialización de un actor B si hace al menos todos los papeles de B).
Un caso de uso representa una interacción entre el software y un actor o más. La interacción tiene que ser una función autónoma dentro del software. Los casos de uso son un caso particular de clasificadores, pueden tener atributos y operaciones. Entre casos de uso y actores hay asociaciones que representan el papel del actor en relación del caso de uso, pero no representan ningún flujo de datos. El actor principal es el que pide la función del software. Hay tres tipos de relaciones:
  • Relación de extensión: Se dice que el caso de uso A extiende a B si dentro de B se ejecuta A, cuando se cumple una condición determinada.
  • Relación de inclusión: Un caso de uso A esta dentro de los casos de uso de B, C..., si es una parte del proceso común a todos estos. El caso de uso no es autónomo, es decir, no tiene actor primario, por lo tanto, siempre se enciende desde otro caso de uso. Permite la reutilización.
  • Relación de generalización y especialización: Un caso de uso A es una especialización de B si A hace todo lo que hace B más algún proceso especifico.
Representación básica:

Representación de una especialización/generalización:

Normalmente no se utilizan los símbolos de clasificadores. Los esteriotipos extend y include se utilizan para las relacoines de extensión y de inclusión, respectivamente:
Podemos crear las asociaciones convenientes entre actores y casos de uso.
Si nos conviene, y en el caso que representemos todos los casos de uso de un sistema, los podemos enmarcar o bien con un cuadrado y un título, o bien con un óvalo, para el sistema contenedor de los casos de uso, como se muestra a continuación:
 Ejemplo de cajero automático:

1. Este diagrama de casos de uso representa la funcionalidad de una aplicación de alquiler de películas de un cajero automático.


 a) ¿Del diagrama se puede deducir que una persona sea responsable del cajero no puede alquilar películas?
No, puede actuar con el rol de cliente también.

 b) ¿Si se cambia el sistema de tal manera que la forma de añadir los materiales es diferente, esto afectaria a las personas con rol de cliente?
No.

 c) Mejora el diagrama teniendo en cuenta que los casos de uso de añadir DVD y añadir BR tienen partes en común. Explica tu decisión.
 d) Supongamos que se mejora el sistema para que los clientes puedan recomendar los DVDs que más les gusta. Esta tarea se puede llevar de manera autónoma, pero también cuando alquilan DVDs. Representa en el diagrama estos requerimientos nuevos.
 e) Se podria considerar el cajero automático como un actor?
Sí, es un sistema externo de la aplicación.


2. Teniendo en cuenta las respuestas a las siguientes preguntas del famoso juego del buscaminas, especifica el diagrama de casos de uso:

Recuerda que necesitaremos preguntarnos para realizar el diagrama...
En este caso podemos suponer que estos són todos los casos de uso del juego.
Preguntas habituales para especificar los casos de uso de un sistema serían:
¿Qué casos de uso identificamos?
  • Iniciar una nueva partida.
  • Descubrir una casilla.
  • Marcar la casilla.
¿Quién realiza estos casos de uso?
  • El jugador.


3. En la empresa donde trabajais han encargado un nuevo videojuego llamado Sokoban. Como analistas que sois, se pide que especifiqueis el diagrama de casos de uso del juego, teniendo en cuenta los siguientes requerimientos funcionales:
  • Sokoban es un juego de varios niveles.
  • Cada nivel esta compuesto por un jugador, cajeros, repisas i muros.
  • El objetivo del juegador es empujar todas las cajas sobre las repisas.
  • Cuando esto sucede el jugador pasa al siguiente nivel.
  • Para mover una caja, el jugador tiene que situarse al lado y empujarla. Si la casilla hacia la que esta empujando esta libre, la caja se moverá.
  • Si el jugador se queda bloqueado. Es decir, no puede acabar el nivel, puede reiniciar el nivel perdiendo una vida.
  • Cuando el jugador pierde todas las vidas, la partida se acaba.