Usuario:ManuelRomero/Android2/Interfaz

De WikiEducator
< Usuario:ManuelRomero‎ | Android2
Revisión a fecha de 23:29 21 may 2013; ManuelRomero (Discusión | contribuciones)

(dif) ← Revisión anterior | Revisión actual (dif) | Revisión siguiente → (dif)
Saltar a: navegación, buscar

Contenido

Descripción general de la aplicación y programa principal

Realizaremos una pequeña api en android para ver diferentes funcionalidades.

Para ello la actividad principal nos visualizará las diferentes funcionalidades en una lista y se encargará de invocar a cada una de ellas cuando la seleccionemos

A continuación una lista a priori de las funcionalidades que queremos realizar  

  • "CicloVida",
  • "SingleTouch",
  • "MultiTouch",
  • "Teclas",
  • "Acelerómetro",
  • "Asset",
  • "AlmacenamientoExterno",
  • "Sonido",
  • "Video",
  • "Ventana Completa",
  • "RenderView",
  • "image",
  • "Bitmap",
  • "Fuente"
  • "SurfaceView"

En el programa principal usaremos un ListActivity.

Qué es un ListActivity

Es una clase que extiende de Activity y está especializada en trabajar con listas.

Es una actividad que muestra una lista de elementos cuyos valores se toman de algún origen de datos como una matriz o un cursor, y nos ofrece los controles de eventos cuando el usuario selecciona un elemento.

La propia clase implementa un layout contenedor que contiene un ListView, por lo que no necesitamos declararlo, ni asociar la actividad con ningún layout.

Esto implica que dentro de la activdad principal ListActivity, no necesitamos usar el callback SetContentView(..)

ListView

Un ListView es una clase que pertenece al grupo de ViewGroup (view contenedores)  que tienen alguna funcionalidad añadida que le permite al usuario interactuar  con ella.

Otras clases de este tipo (Gallery, GridView, ImageSwitcher, ScrollView, TabHost) .

Muestra una serie de View como una lista, otorgando al usuario la capacidad de navegar entre ellos utilizando la característica de desplazamiento vertical.

Para obtener los datos del array o cursor y asociarlos al ListView necesitamos un la clase Adapter

Debemos definir un Adapter(ArrayAdapter, CursorAdapter o SimpleCursorAdapter),  para asignar al ListView de la ListActivity los valores que queramos visualizar. Para ello debemos usar el método setAdapter() de la clase ListView o como en el caso de nos ocupa usar el método setListAdapter de la clase ListAdapter

 

ArrayAdapter adaptadorValores;

adaptadorValores=newArrayAdapter<String>( this,

                                          android.R.layout.simple_list_item_1,

                                          aplicaciones

                                         )

 

Vemos tres parámetros al construir el ArrayAdapter

ü  this è Es el context de la actividad, es decir la propia actividad

ü  android.R.layout.simple_list_item_1 è Es un layout predefinido que incorpora un ListView con el id android:list para incorporar en una lista de valores

ü  aplicaciones è Es la lista de valores

Para asignar al ListView del ListActivity  los valores que queremos visualizar, en este caso el contenido de la variable aplicaciones,  invocamos al método setListAdapter y le pasamos el adapter previamente definido

setListAdapter(adaptadorValores);

1.1.2     Gestionando eventos de selección

La clase ListActivity tiene un método protegido onListItemClick()  el cual es invocado al seleccionar un elemento.

    @Override

protected void onListItemClick(ListView valores, View vista, int pos, long id){

      super.onListItemClick(valores, vista, pos, id);

       . . .

       . . .

}

Este método recibe 4 parámetros

Ø  valores è Es el contenedor ListView que contiene la lista de view donde ha ocurrido el evento

Ø  vista è  es el view del listView que ha sido cliqueado

Ø  pos è es la posición en el vector del elemento del ListView seleccionado

Ø  id è el id de la fila que ha sido seleccionada

Lo primero que debemos hacer es invocar al método del  la clase ListActivity

Y ahora lo que queremos es que se invoque a la clase que realice la acción seleccionada

Para ello usaremos un Intent, como ya sabemos. El nombre de la clase será el contenido del texto del elemento seleccionado. El código que habla por sí sólo quedará como sigue:

. . .

String app = aplicaciones[pos];

try{

    Class accion = Class.forName("com.example.api_juegos."+app);

    Intent i =new Intent(this,clase);

    startActivity(i);

}catch(ClassNotFoundException e){

e.printStackTrace();

}

1.2       Combinando con más componentes View

Si queremos más controles View entonces sí que nos creamos un layout para ello; En este caso debemos definir también un ListView   con el identificador android:id=”@android:list”

Podemos usar un TextView identificado @android:id/empty y si la lista está vacía se mostrará el contenido de este TextView.

 

package com.example.api_juegos;

 

import android.app.ListActivity;

import android.content.Intent;

import android.os.Bundle;

import android.util.Log;

import android.view.View;

import android.widget.ArrayAdapter;

import android.widget.ListView;

 

public class Api extends ListActivity {

      String aplicaciones []={

                  "CicloVida",

                  "SingleTouch",

                  "MultiTouch",

            "Key",

            "Acelerómetro",

            "Asset",

            "Almacenamiento Externo",

            "Sonido",

            "Video",

            "Ventana Completa",

            "RenderView",

            "Shape",

            "Bitmap",

            "Fuente",

            "SurfaceView"};

 

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        Log.i("DEBUGANDI","Antes de setListAdapter");

        setListAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,aplicaciones));

      

    }

    @Override

    protected void onListItemClick(ListView valores, View vista, int pos, long id){

      super.onListItemClick(valores, vista, pos, id);

      String app = aplicaciones[pos];

      try{

            Class clase = Class.forName("com.example.api_juegos."+app);

            Intent i =new Intent(this,clase);

            startActivity(i);

      }catch(ClassNotFoundException e){

            e.printStackTrace();

      }

     

}   

  Concepto de Listas ListView Adaptar (ArrayAdapter) y método Adapter.setAdaptaer

    ListView vistaLista = (ListView)findViewById(R.id.listaActividades);

        Log.i("DEBUGANDO", "he llamado al super de oncreate");

       

        Log.i("DEBUGANDO", "definido vistaLista");

       ArrayAdapter <String> listaAdaptada = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,aplicaciones);

        Log.i("DEBUGANDO", "Hecho arrayAdapter");

        vistaLista.setAdapter(listaAdaptada);

        Log.i("DEBUGANDO", "adaptada lista");

ListView è es un View que muestra cada control View  como un elemento  de una lista otorgando al usuario la capacidad de navegar entre ellos utilizando la característica de desplazamiento vertical.

Adapter è   es un objeto  que va a leer datos de alguna fuente y va a genera datos  para un control ListView,. Las clases Adapter más comunes son

            ArrayAdapter è Los datos los cojo de un array

            CursorAdapterè Los datos los cojo de una base de datos como resultado de una consulta

AdapterViewè Un conjunto de controles View que muestran datos de alguna fuente

O usar directamente una subclase ListActivity que ya está preparada para visualizar con un ListView como en el ejemplo

1.3     Primera actividad : Ciclo de vida

Nuestra primera actividad de nuestro api es mostrar un ciclo de vida de una actividad.

En el wiki tenemos una pequeña explicación de los estados en los que se puede encontrar una actividad, y los métodos que se ejecutan al pasar de un estado a otro

Esta imagen está en la página de developer de android. La siguiente muestra los estados de las actividades

Se pretende que me muestre el estado en el que se encuentra la actividad y el instante en el que se ha producido.

La actividad debe mostrar el estado en el que se encuentra y el instante en el que se pasó a esa actividad.

Una posible idea es tener un método información al que le pasamos el  nombre del estado y nos visualizará dicho string junto con el instante de tal acción

package com.example.api_juegos;

 

import java.text.SimpleDateFormat;

 

import android.app.Activity;

import android.os.Bundle;

import android.util.Log;

import android.widget.TextView;

 

public class CicloVida  extends Activity{

      StringBuilder builder = new StringBuilder();

      TextView texto;

       long fecha;

       SimpleDateFormat df;

       

     

      private void informacion (String text){

             fecha = System.currentTimeMillis();

            df = new SimpleDateFormat("h-m-s");

            String curTime = df.format(fecha);

            Log.d("CicloVida ",text);

            builder.append(curTime+"-"+text);

            builder.append('\n');

            texto.setText(texto.getText()+builder.toString());

      }

     

      public void onCreate(Bundle estado){

            super.onCreate(estado);

            texto = new TextView (this);

            texto.setText(builder.toString());

            setContentView(texto);

            informacion("ejecución");

      }

     

      protected void onResume(){

            super.onResume();

            log("detenido");

           

      }

      protected void onPause(){

            super.onPause();

            log("pausado");

            if(isFinishing()){

                  log("terminado");

            }

           

      }

 

}

1.4     Segunda actividad : SingleTouch

Ahora pasamos a la segunda actividad

El evento singleTouch es un evento que se genera cuando se recibe un toque en la pantalla. La pantalla al ser  táctil  al pulsar o tocar en ella se genera este evento

Implementa la interfaz OnTouchListener

Esta interfaz sólo tiene un método abstracto que habrá que implementar

public abstract boolean onTouch(View vista, MotionEvent evento);

Para asociar el Listener a un objeto de tipo view y recoger los eventos de toque en dicho objeto se usa el método

View.setOnTouchListener()

La clase MotionEvent tiene tres métodos importantes

float getX() è Coordenada x

float getY() è Coordenada y

getAction() ètipo de evento táctil. Tenemos los siguientes posibles eventos

MotionEvent.ACTION_DOWN

MotionEvent.ACTION_MOVE

MotionEvent.ACTION_CANCEL

MotionEvent.ACTION_UP

 

Hacer el programa para que cuando toque con el dedo ponga el tipo de evento y la posición en la que se ha producido

public class SingleTouch extends Activity implements OnTouchListener{

 

            StringBuilder texto = new StringBuilder();

            TextView cajaTexto;

 

           

            public void onCreate(Bundle instancia){

                  super.onCreate(instancia);

                  cajaTexto = new TextView(this);

                  cajaTexto.setText("Multiple toque en pantalla");

                  cajaTexto.setOnTouchListener(this);

                  setContentView(cajaTexto);

            }

   @Override

       public boolean onTouch(View v, MotionEvent evento) {

            texto.setLength(0);//Borramos lo que había en el texto

            switch (evento.getAction()){

            //Presionamos un dedo

                  case MotionEvent.ACTION_DOWN:

                        texto.append("Down, ");

                        break;

                  case MotionEvent.ACTION_UP:

                        texto.append("Up, ");

                        break;

                        case MotionEvent.ACTION_CANCEL:

                        texto.append("Cancel, ");

                        break;

                  case MotionEvent.ACTION_MOVE:

                        texto.append("Move, ");

                        break;

            }

                  texto.append(", ");

                  texto.append(evento.getX());

                  texto.append(", ");

                  texto.append(evento.getY());

                  texto.append("\n");

                  cajaTexto.setText(texto.toString());

                  return true;

            }

           

      }

1.5  Tercera actividad : MultiTouch

El evento que se produce, la interfaz y el método abstracto son iguales que en el caso anterior,  pero a diferencia de él, éste incorpora más eventos, ya que puedo presionar hasta con 10 dedos, dependiendo de lo que implemente el dispositivo. Normalmente dispositivos móviles no suele tener mucho sentido que implementen más de 5 toques

Aquí aparecen además de los eventos anteriores dos más con lo que en total tendremos

MotionEvent.ACTION_POINTER_DOWN

MotionEvent.ACTION_POINTER_UP

Ahora un único MotionEvent puede tener datos para varios eventos. De hecho los eventos anteriores ocurren cuando presionamos o levantamos un toque que no sea el primero.

Para saber cuántos eventos está gestionando un MotionEvent tenemos el método

MotionEvent.getPointerCount();

En el propio evento MotionEvent.getAction() nos viene codificado el tipo de evento y el índice de qué toque es el que en un momento dado está produciendo el evento si no es el primero

Para quedarnos sólo con el tipo de evento invocamos al método MotionEvent.getActionMasked()

Respecto con el resto de toques que no sean el primero se gestionan en un vector.

Podemos acceder al índice y al identificador

int MotionEvent.getActionIndex()

int MotionEvent.getPointerIdentified()

1.5.1     Identificador e Indice

int indice = MotionEvent.getActionIndex()

int identificardor = MotionEvent.getPointerIdentified(inidice)

Índice es un valor que corresponde a un índice de los arrays internos de MotionEvent, por lo que no corresponde con el toque después de primer 0,1,2,…

identificador es un entero que retorna el identificador del puntero del dedo, en este caso sí que corresponde al toque 0,1,2,…

package com.example.api_juegos;

import android.app.Activity;

import android.os.Bundle;

import android.util.Log;

import android.view.MotionEvent;

import android.view.View;

import android.view.View.OnTouchListener;

import android.widget.TextView;

 

public class MultiTouch extends Activity implements OnTouchListener{

      StringBuilder texto = new StringBuilder();

TextView cajaTexto;

float[]x = new float[10];

float[]y = new float[10];

boolean[]tocado = new boolean[10];

     

public void onCreate(Bundle instancia){

      super.onCreate(instancia);

      cajaTexto = new TextView(this);

      cajaTexto.setText("Multiple toque en pantalla");

      cajaTexto.setOnTouchListener(this);

      setContentView(cajaTexto);

}

private void actualizaCajaTexto(){

      texto.setLength(0);//Borramos lo que había en el texto

      for (int i = 0; i<10; i++){

            texto.append(tocado[i]);

            texto.append(", ");

            texto.append(x[i]);

            texto.append(", ");

            texto.append(y[i]);

            texto.append("\n");

      }

      cajaTexto.setText(texto.toString());

}

@Override

public boolean onTouch(View v, MotionEvent evento) {

//Primero obtenemos el tipo de evento

      int accion = evento.getActionMasked();

      int indiceToque = evento.getActionIndex();

      int idToque = evento.getPointerId(indiceToque);

      switch (accion){

      //Presionamos un dedo

            case MotionEvent.ACTION_DOWN:

            case MotionEvent.ACTION_POINTER_DOWN:

                  tocado[idToque]=true;

                  x[idToque]=(int)evento.getX(indiceToque);

                  y[idToque]=(int)evento.getY(indiceToque);

                  break;

            case MotionEvent.ACTION_UP:

            case MotionEvent.ACTION_POINTER_UP:

            case MotionEvent.ACTION_CANCEL:

                  tocado[idToque]=false;

                  x[idToque]=(int)evento.getX(indiceToque);

                  y[idToque]=(int)evento.getY(indiceToque);

                  break;

            case MotionEvent.ACTION_MOVE:

                  int contadorToque=evento.getPointerCount();

                  for(int i=0;i<contadorToque;i++){

                     indiceToque=i;

                     idToque=evento.getPointerId(indiceToque);

                     x[idToque]=(int)evento.getX(indiceToque);

                     y[idToque]=(int)evento.getY(indiceToque);

                  }

                  break;

                                              

            }

            actualizaCajaTexto();

            return true;

      }

}

 

1.6  Cuarta actividad: el Teclado

Estos eventos se generan cuando la aplicación detecta acciones sobre el teclado. Estos eventos pueden ser del teclado, de la pantalla  (soft ), teclado hard, si el dispositivo lo tiene o entradas del sistema.

Interfaz OnKeyListener con un único método onKey().

public boolean onKey (View vista, int keyCode, KeyEvent evento)

Los parámetros

·         vista  es la vista sobre que recibe el evento del teclado

·         keyCode es el código de la tecla que he presionado; este código corresponde  a una constante de la clase KeyEvent (Por ejemplo la tecla Z corresponde a la constante KeyCode.KEYCOD_Z

·         evento es el propio evento que se ha generado.

 

 

 

1.6.1     Eventos de la clase

La clase KeyEvento tiene dos métodos

KeyEvent.getAction

KeyEvent.getUnicodeChar()

En el primer caso nos devuelve el tipo de evento generado, pudiendo ser uno de los siguientes

KeyEvent.ACTION_DOWN

KeyEvent.ACTION_UP

KeyEvent.ACTION_MULTIPLE

El Segundo método nos retorna el código Unicode de la tecla presionada para poder, por ejemplo escribirla.

1.6.2     Trabajar con eventos del teclado sobre la vista

View.setFocusableInTouchMode(true);

View.requestFocus();

A continuación el código para conseguir este funcionamiento

Para poder ver el funcionamiento, debemos tener visible el teclado

Para ello vamos a ver el siguiente código

   InputMethodManager teclado =

   (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);

   teclado.toggleSoftInput(InputMethodManager.SHOW_FORCED,

                    InputMethodManager.HIDE_IMPLICIT_ONLY);

Obtenemos una referencia de la clase que administra los métodos de entrada y la instanciamos a partir del servicio del sistema que nos informa de cual es el servicio del sistema para insertar datos por el teclado

Posteriormente llamamos al método toggleSoftInput que lo que hace es cambiar el método de entrada (teclado ) que se visualiza por la pantalla

void toggleSoftInput( int showFlags, int hideFlags)

Le pasamos dos flag tiene el siguiente valor que nos indica cuando cambiar de modo de visualizar a modo oculto

·         InputMethodManager.SHOW_FORCED  è Se ha forzado que aparezca el teclado y no desaparecerá hasta que explícitamente se indique

·         InputMethodManager.HIDE_IMPLICIT_ONLY è El teclado solo debe de estar oculto si el usuario lo indica de forma explícita

1.7  Quinta actividad  Acelerómetro

Es una funcionalidad que está muy de moda y es un reclamo muy interesante para el mundo de los juegos, y muchas aplicaciones interesantes.

El acelerómetro es un sensor que nos facilita la ubicación espacial del dispositivo respecto a un eje de tres coordenadas

 

 

El acelerómetro utiliza la interfaz SensorEventListener

Esta interfaz tiene dos métodos

public void onSensorChage(SensorEvent evento)

public void onAccurrencyChanged(Sensor sensor, int accurrency)

El primer método se invoca cuando se cambia la posición del móvil respecto a la última que tenía

Entre otros métodos y datos del SensorEvent tenemos la nueva posición que nos la da un vector

evento.values[0 ]

evento.values[1 ]

evento.values[2 ]

El segundo cuando cambian el número de sensores de acelerómetro que tiene el dispositivo.

A la hora de hacer la aplicación, primero debemos verificar que el dispositivo tenga acelerómetro, y en caso de que exista asociar el listener de este evento al Adminstrador del sistema de sensores

//Verificamos que el dispositivo tenga acelerómetros

SensorManager sm =(SensorManager) getSystemService (SENSOR_SERVICE);

List<Sensor>listaAcelerometros = sm.getSensorList(Sensor.TYPE_ACCELEROMETER);

if (listaAcelerometros.size()>0)

//Registramos el acelerómetro para recoger los eventos

sm.registerListener(this,listaAcelerometros.get(0),SensorManager.SENSOR

_DELAY_GAME);

 

Una vez que hemos hecho esto  ya solo queda juntar todo y nos quedará el siguiente código

 

 

 

 

package com.example.api_juegos;

 

import java.util.List;

import android.app.Activity;

import android.hardware.Sensor;

import android.hardware.SensorEvent;

import android.hardware.SensorEventListener;

import android.hardware.SensorManager;

import android.os.Bundle;

import android.util.Log;

import android.view.KeyEvent;

import android.view.View;

import android.widget.TextView;

 

public class Acelerometro  extends Activity implements SensorEventListener{

      StringBuffer texto = new StringBuffer();

      TextView cajaTexto;

      public void onCreate(Bundle estado){

            super.onCreate(estado);

            cajaTexto = new TextView (this);

            cajaTexto.setText("Controlando el acelerómetro");

            //Verificamos que el dispositivo tenga acelerómetros

            SensorManager sm =(SensorManager) getSystemService (SENSOR_SERVICE);

            List<Sensor> listaAcelerometros = sm.getSensorList(Sensor.TYPE_ACCELEROMETER);

            if (listaAcelerometros.size()>0)

                  //Registramos el acelerómetro para recoger los eventos

      sm.registerListener(this,listaAcelerometros.get(0),SensorManager.SENSOR_DELAY_GAME);

            setContentView(cajaTexto);

      }

     

      @Override

      public void onSensorChanged(SensorEvent evento) {

            // TODO Auto-generated method stub

            texto.setLength(0);

            texto.append("X=");

            texto.append(evento.values[0]);

            texto.append("Y=");

            texto.append(evento.values[1]);

            texto.append("Z=");

            texto.append(evento.values[2]);

            String t = texto.toString();

            Log.d("KeyText",t);

            cajaTexto.setText(t);

      }

 

      @Override

      public void onAccuracyChanged(Sensor sensor, int accuracy) {

            // TODO Auto-generated method stub

      }

}    

 

 

 

 

1.8  Sexta actividad: Assets

Queremos acceder a ficheros ubicados en un almacenamiento externo, generalmente una tarjeta SD

En android los ficheros que incorporamos a nuestra aplicación y que con ella los queremos distribuir pueden estar ubicados en res/  o en assets/

Los ficheros ubiados en res/ deben cumplir ciertas restricciones, no siendo así en los ubicados en assets/

Queremos trabajar con ficheros que vamos a ubicar en assets/

Necesitmos un objeto de la clase AssetManager

Para instanciar  obtenemos una referencia del método getAssets()  la interfaz Context

AssetManager fileAdmin = context.getAssets();

Con este objeto podemos acceder a los ficheros. Para abrir los ficheros

InputStream file = fileAdmin.open(“datos.txt”);

La ubicación del fichero estará dentro del directorio assets.

Una vez que hemos abierto el fichero de manera tan sencilla ahora tenemos que leerlo. Si trabajamos con ficheros que ubicamos en nuestra aplicación hemos de saber que sólo se pueden abrir en modo de lectura, y no de escritura

Ahora nos queda leer los datos del fichero

Para ello trabajaremos con la clase ByteArrayOutputStream, y usaremos el método read() de la clase  InputStream

ByteArrayOutputStream byteStream = new ByteArrayOutputStream();

byte[] bytes = new byte[4096];

int len = 0;

while((len = fa.read(bytes))>0){

      byteStream.write(bytes,0,len);

String texto = byteStream.toByteArray();

En nuestro api haremos que se visualice el contenido de un fichero llamado datos.txt que estará dentro de la capeta assets/datos.txt

A continuación el código

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

package com.example.api_juegos;

 

import java.io.ByteArrayOutputStream;

import java.io.IOException;

import java.io.InputStream;

import android.app.Activity;

import android.content.res.AssetManager;

import android.os.Bundle;

import android.util.Log;

import android.widget.TextView;

 

public class Asset  extends Activity {

      StringBuffer texto = new StringBuffer();

      TextView cajaTexto;

     

      public void onCreate(Bundle estado){

            super.onCreate(estado);

            cajaTexto = new TextView (this);

            InputStream file=null;

            AssetManager adminAsset = getAssets();

            setContentView(cajaTexto);

            Log.i("ASSETS","Antes de abrirlo el fichero");

            try{

                file = adminAsset.open("datos.txt");

                Log.i("ASSETS","Fichero abierto");

                String texto = leeFichero(file);

                cajaTexto.setText(texto);

            }catch(IOException e){

                  cajaTexto.setText("No puedo cargar el fichero”);

            }finally{

                  if (file!=null)

                        try{

                             file.close();

                        }catch(IOException e){

                             cajaTexto.setText("No puedo cerrar el fichero");

                            

                        }

            }

      }

      private String leeFichero(InputStream fa) throws IOException{

            ByteArrayOutputStream byteStream = new ByteArrayOutputStream();

        byte[] bytes = new byte[4096];

            int len = 0;

            while((len = fa.read(bytes))>0)

                  byteStream.write(bytes,0,len);

            Log.i("ASSET","justo antes de retornar");

            return new String(byteStream.toByteArray());

      }

}

 

 

 

 

 

1.9       Septima actividad  AlmacenamientoExterno

En este caso queremos almacenar la información en la tarjeta SD en lugar de almacenarlo junto a la aplicación y distribuirlo.

En este caso ya sí que podemos  realizar operaciones de lectura y escritura

Para acceder a este dispositivo debemos tener permiso para acceder a este dispositivo de almacenamiento externo <uses-permission>. Para el acceso a la tarjeta SD

<user-permission android.name= ”android.permission.WRITE_EXTERNAL_STORAGE” >

Posteriormente debemos comprobar que existe o tenemos disponible dicho dispositivo

String estado = Enviroment.getExternalStorageState()

La clase Enviroment define entre otras cosas la constante Enviroment.MEDIA_MOUNTED Si el método anterior nos retorna dicho valor, implica que tendremos acceso en lectura y escritura a dicho dispositivo

Ahora nos queda obtener la ubicación de este dispositivo, es decir el directorio donde esté montado

File directorioSD= Enviroment.getExternalStorageDirectory()

En estos momentos podemos disponernos a abrir el fichero

File fichero = new File(directorioSD.getAbsolutePath()+File.separator+ "texto.txt");

Ahora a usar las clases de java de I/O para leer y escribir en ficheros.

El código de esta actividad completa se muestra a continuación

 

package com.example.api_juegos;

 

import java.io.BufferedReader;

import java.io.BufferedWriter;

import java.io.File;

import java.io.FileReader;

import java.io.FileWriter;

import java.io.IOException;

 

import android.app.Activity;

import android.os.Bundle;

import android.os.Environment;

import android.widget.TextView;

 

 

 

 

 

public class AlamcenamientoExterno  extends Activity {

      StringBuffer texto = new StringBuffer();

      TextView cajaTexto ;

 

      public void onCreate(Bundle estado){

            super.onCreate(estado);

            cajaTexto = new TextView (this);

            setContentView(cajaTexto);

            String  estadoSD = Environment.getExternalStorageState();

            if (!estadoSD.equals(Environment.MEDIA_MOUNTED)){

                  cajaTexto.setText("No está disponible la tarjeta SD");

            }else{

            File directorioSD= Environment.getExternalStorageDirectory();

            File fichero = new File(directorioSD.getAbsolutePath() +

                                     File.separator + "texto.txt");

            try{

               escribeTexto(fichero,"Esto es una línea que quiero escribier

                             en mi fichero");

                  String t = leeTexto(fichero);

                  cajaTexto.setText(t);

            }catch(IOException e){

                  cajaTexto.setText("Error accediendo "+e.getMessage());

            }

      }

           

 }

      private String leeTexto(File fichero) throws IOException {

            // TODO Auto-generated method stub

            BufferedReader r = new BufferedReader( new FileReader(fichero));

            StringBuilder texto = new StringBuilder();

            String linea;

            while ((linea=r.readLine())!=null){

                  texto.append(linea);

                  texto.append('\n');

            }

            r.close();

            return r.toString();

      }

      private void escribeTexto(File fichero, String texto) throws

                                                                IOException {

            BufferedWriter w = new BufferedWriter( new FileWriter(fichero));

            w.write(texto);

            w.close();

      }

}

 

 

1.10              "Sonido"

1.11              "Video",

1.12              "Ventana Completa",

1.13              "RenderView",

1.13.1Programación básico de gráficos

Librería  Skia

1.13.1.1 Desbloquear la pantalla

la pantalla bloqueada pierde el brillo con el objetivo de economizar.

Por software podemos crear un bloqueo  para que esto no ocurra y asignarlo a la aplicación.

Para hacerlo por software debemos dar permisos a la aplicación; Para que la aplicación solicite permisos cuando se instala (antes de estar ejecutándose), hay que especificarlo en el fichero Manifest  con el elemento uses-permission

<uses-permission>

android.permission.WAKE_LOCK

</uses_permission>

Este permiso permite el uso de objetos PowerManager y WakeLock para evitar que el procesador deje de funcionar al 100% cuando no hay eventos en el sistema con el objetivo de ahorrar energía.

Son muchos los permisos que puede solicitar la aplicación al sistema antes de instalarse . ver http://developer.android.com/reference/android/Manifest.permission.html

Una vez hecho esto ya podemos definer un objeto de la clase WakeLock y un objeto de la clase PowerManager.

A partir del sistema context obtenemos un objeto de la clase PowerManager y con el método nextWakeLock  instanciamos un objeto de la clase WaleLock.

Este método genera un wake lock (bloqueo para que no se duerma el sistema) según los dos parámetros que le pasemos:

1.      El tipo de bloqueo que lo pasamos con una constante, en este caso queremos un bloqueo completo (que no se duerma aunque no haya eventos en el sistema) PowerManager.FULL_WAKE_LOCK

2.      Un  tag (etiqueta que pongamos a ese bloqueo para identificarlo) ¿??

PowerManager power ;

WakeLock bloqueo ;

 

power = (PowerManager) getSystemService(Context.POWER_SERVICE);

bloqueo = power.newWakeLock(PowerManager.FULL_WAKE_LOCK,"My bloqueo");

Una vez creado el bloqueo (en realidad el desbloqueo) hay que cargarlo con el método acquire() Y cuando la actividad finalice hay que desactívalo, o liberar el bloque con el método release(). Ambos métodos de la clase WaleLock Recordar que debemos invocarlo en los callback onResume() {… objetoWakeLock.acquire()…} y  onPause{… objetoWakeLock.release()…}

1.13.1.2 Pantalla completa

 Consiste en eliminar del espacio visual elementos ajenos a nuestra aplicación o que formen parte de ella pero no de la vista principal como el barra del título, o menus o barra de notificación.

Especialmente en juegos queremos disponer de toda la pantalla

Para ello realizaremos las siguientes llamadas

      //Haciendo la pantalla completa y sin los meús o títulos

requestWindowFeature(Window.FEATURE_NO_TITLE);

            getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,

                     WindowManager.LayoutParams.FLAG_FULLSCREEN);

Vemos como el primer método quita la barra de título

El segundo se encarga que nuestra actividad ocupe toda la pantalla completa y no use la barra de notificación

1.13.1.3 El código

Para probar la aplicación completa, reescribimos el método SingleTouch  

package com.example.api_juegos;

 

 

 

import android.app.Activity;

import android.content.Context;

import android.os.Bundle;

import android.os.PowerManager;

import android.os.PowerManager.WakeLock;

import android.util.Log;

import android.view.MotionEvent;

import android.view.View;

import android.view.View.OnTouchListener;

import android.view.Window;

import android.view.WindowManager;

import android.widget.TextView;

 

public class SingleTouch extends Activity implements OnTouchListener{

 

StringBuilder texto = new StringBuilder();

TextView cajaTexto;

 

PowerManager power ;

WakeLock bloqueo;

public void onCreate(Bundle instancia){

super.onCreate(instancia);

//desbloqueo

power = (PowerManager)getSystemService(Context.POWER_SERVICE);

bloqueo = power.newWakeLock(PowerManager.FULL_WAKE_LOCK,"Mi bloqueo");

                 

                 

//Pantalla completa

requestWindowFeature(Window.FEATURE_NO_TITLE);

            getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,

                     WindowManager.LayoutParams.FLAG_FULLSCREEN);

 

                 

                 

cajaTexto = new TextView(this);

cajaTexto.setText("Multiple toque en pantalla");

cajaTexto.setOnTouchListener(this);

setContentView(cajaTexto);

  }

@Override

protected void onPause() {

            super.onPause();

            bloqueo.release();

            Log.d("SINGLETOUCH","On Pause");

}

@Override

protected void onResume() {

            super.onResume();

            bloqueo.acquire();

            Log.d("SINGLEtOUCH","On resume");

}

@Override

      public boolean onTouch(View v, MotionEvent evento) {

          // Igual que antes, no ha cambiado nada

      }

1.13.2Dibujando en la interfaz de usuario

Hasta ahora dibujábamos (escribíamos) en un view que era una caja de texto que se dibujaba en la pantalla cuando invocamos a setContentView()

Ahora vamos a crear nuestra propia vista

Para ello tenemos que crear una clase que extienda de View

class RederView extends View{

 //Codigo

}

 

La clase View tiene un método que se llama onDraw(Canvas lienzo) que android lo  invonca siempre que el view se tenga que dibujar

protected void onDraw (Canvas miLienzo){

//dibujar lo que quiero que aparezca en miLienzo….

}

Para que se redibuje a sí sola usamos el método invalidate().

De esta manera se volverá a dibujar una y otra vez, pero lo hará en el mismo hilo de ejecución, pues no hemos creado ningún thread

Canvas es una clase muy especial que engloba una api llamada Skia.

Con Canvas vamos a poder dibujar tanto formas, mapas de bits como texto

Canvas  en este caso dibuja dentro del espacio que ocupa View, no dibuja directamente en la pantalla, sino dentro de algún mapa de bit.

Vamos a hacer en nuestra api una aplicación que me muestre como el método invalídate() da una frecuencia de ejecución al método onDraw() como si de un bucle en un programa principal se tratara.

Para ello usaremos el método de Canvas

Canvas.drawRGB( int red, int green, int blue) que da un color  de fondo a la pantalla según los colores que le pasemos

demosle colores aleatorios

canvas.drawRGB(rand.nextInt(256),rand.nextInt(256),rand.nextInt(256));

Observemos el código completo y ejecutalo (cuidado, no te marees).

intenta relentizar la ejecución

//package e imports igual que en el caso anterior ... creo…

 

public class RenderView  extends Activity {

 

PowerManager power ;

WakeLock bloqueo ;

//Creamos nuestra propia view

class MiRender extends View{

         Random rand = new Random();

         public MiRender(Context contexto){

               super (contexto);

         }

         protected void onDraw(Canvas canvas){

                       canvas.drawRGB(rand.nextInt(256),

                                      rand.nextInt(256),

                                      rand.nextInt(256));

                     invalidate();

         }

}

@Override

protected void onCreate(Bundle estado) {

super.onCreate(estado);

           

//Desbloqueando la pantalla configurando

power = (PowerManager) getSystemService(Context.POWER_SERVICE);

bloqueo = power.newWakeLock(PowerManager.FULL_WAKE_LOCK,"Mi bloqueo");

 

//Haciendo la pantalla completa y sin los meús o títulos

requestWindowFeature(Window.FEATURE_NO_TITLE);

getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,

                     WindowManager.LayoutParams.FLAG_FULLSCREEN);

 

setContentView(new MiRender(this));

    }

@Override

protected void onPause() {

            super.onPause();

            bloqueo.release();

            Log.d("SINGLETOUCH","On Pause");

}

@Override

protected void onResume() {

            super.onResume();

            bloqueo.acquire();

            Log.d("SINGLEtOUCH","On resume");

}

}

 

1.14              "image",

1.15              "Bitmap",

1.16              "Fuente"

1.17  "SurfaceView"