martes, 24 de enero de 2012

Primera Aplicación. Parte 3

Cargando los datos en base de datos.

Para cargar los datos del fichero CSV en base de datos, es necesario añadir este fichero en el proyecto de Eclipse. Para ello es necesario importar este archivo en la carpeta assets del proyecto.

Para ello, hay que seleccionar "File>Import..." en el proyecto actual.

Posteriormente hay que seleccionar "File System":
Selecciono el directorio donde esta almacenado el fichero es-allcam.txt y se importa este fichero a la carpeta assets del proyecto. Una vez incluido este fichero en el proyecto, accedo a él para parsearlo e insertar la información en base de datos. El siguiente código accede al fichero es-allcam.txt, abre un flujo de lectura y parsea los datos fila por fila del fichero insertando los datos como una fila en la tabla de base de datos mediante el método insertRadar
 
 public boolean readCSV(String radarCSVFile) {
  try {
   InputStream is = context.getAssets().open("es-allcam.txt");
   InputStreamReader isr = new InputStreamReader(is);
   BufferedReader in = new BufferedReader(isr);
   in.readLine();
   String reader = "";
   String[] RowData;
   db.beginTransaction();
   while ((reader = in.readLine()) != null) {
    RowData = reader.split(",");
    Log.w(TAG, "Inserting... " + RowData[1] + " " + RowData[0]
      + " " + RowData[2] + " " + RowData[3] + " "
      + RowData[4] + " " + RowData[5] + " " + "...");
    
    insertRadar(RowData[1], RowData[0], RowData[2], RowData[3],
      RowData[4], RowData[5], "");

   }
   db.setTransactionSuccessful();

   db.releaseMemory();
   in.close();
  } catch (Exception e) {
   db.releaseMemory();
   e.printStackTrace();
  } finally {
   db.endTransaction();
  }
  return true;
 }

El método insertRadar luce como se muestra a continuación
 public void insertRadar(String latitude, String longitude,
   String radar_type, String speed, String direction_type,
   String direction, String postal_code) {
  rowSet[0] = latitude;
  rowSet[1] = longitude;
  rowSet[2] = radar_type;
  rowSet[3] = speed;
  rowSet[4] = direction_type;
  rowSet[5] = direction;
  rowSet[6] = postal_code;

  // return db.insert(DATABASE_TABLE, null, initialValues);
  db.execSQL(sqlInsertRadar, rowSet);

 
 }

Implemento unos cuantos métodos para tratar los datos de radar en tablas. El siguiente método actualiza los radars por id de radar en base de datos,

 // ---updates a Radar---
 public boolean updateRadar(long rowId, String latitude, String longitude,
   String radar_type, String speed, String direction_type,
   String direction, String postal_code) {
  Log.v(TAG, "update radar " + rowId);
  ContentValues args = new ContentValues();
  args.put(KEY_LATITUDE, latitude);
  args.put(KEY_LONGITUDE, longitude);
  args.put(KEY_RADARTYPE, radar_type);
  args.put(KEY_SPEED, speed);
  args.put(KEY_DIRECTION_TYPE, direction_type);
  args.put(KEY_DIRECTION, direction);
  args.put(KEY_POSTALCODE, postal_code);
  return db.update(DATABASE_TABLE, args, KEY_ROWID + "=" + rowId, null) > 0;
 }

Este método sirve para recuperar los radares que se encuentren cerca de cierta localización dada por un objeto Location. Este método se utilizará posteriormente para buscar radares en el momento de que se actualice la localización del móvil mediante su localizador GPS.

 public Cursor getRadarsByLocation(Location location) {

  String sConditional = KEY_LATITUDE + " BETWEEN "
    + String.valueOf(location.getLatitude() + 0.001) + " AND "
    + String.valueOf(location.getLatitude() - 0.001) + " AND "
    + KEY_LONGITUDE + " BETWEEN "
    + String.valueOf(location.getLongitude() + 0.001) + " AND "
    + String.valueOf(location.getLongitude() - 0.001);

  Log.v(TAG, sConditional);

  if (location != null) {

   Log.v(TAG, "get radar by location: " + location.getLatitude() + " "
     + location.getLongitude());

   mCursor = db.query(true, DATABASE_TABLE, new String[] { KEY_ROWID,
     KEY_LATITUDE, KEY_LONGITUDE, KEY_RADARTYPE, KEY_SPEED,
     KEY_DIRECTION_TYPE, KEY_DIRECTION, KEY_POSTALCODE },
     sConditional, null, null, null, null, null);
  }
  if (mCursor != null) {
   mCursor.moveToFirst();
  }
  return mCursor;

 }

domingo, 22 de enero de 2012

Primera aplicación. Parte 2

Obvio lo obvio, como bajarse el IDE Eclipse, instalar Android SDK y el ADT de eclipse.
Para una guia muy bien explicada

http://developer.android.com/sdk/index.html

Para los que además tienen un equipo con arquitectura de 64 bits.

http://developer.android.com/sdk/installing.html#troubleshooting

Comienzo con la base de datos.
Los datos de localización de los radares móviles los he sacado de la página SpeedCameraPOI.com de la que se puede bajar un fichero txt en formato csv con los datos de localización de los radares.


1:  lon,lat,TYPE,SPEED,DIRTYPE,DIRECTION
2:  -17.851917,28.653617,5,0,0,0
3:  -16.825796,28.198766,5,0,0,0
4:  -16.817533,28.265373,5,0,0,0
5:  -16.797592,28.168118,5,0,0,0
6:  -16.797476,28.241514,5,0,0,0
7:  -16.791524,28.147537,5,0,0,0
8:  -16.765271,28.183670,5,0,0,0
9:  -16.653410,28.394205,5,0,0,0
10:  -16.580407,28.391820,5,0,0,0
11:  -16.575469,28.061445,5,0,0,0
12:  -16.373555,28.355344,5,0,0,0
13:  -16.349598,28.489710,5,0,0,0
14:  -16.273584,28.443848,5,0,0,0
15:  ....
Una vez que tengo los datos de localización de los radares, y viendo la estructura que poseen, decido que la base de datos va a consistir de una sola tabla RADARLOCATION con seis columnas; LONGITUDE, LATITUDE, RADARTYPE, SPEED, DIRECTIONTYPE

De acuerdo. Ahora viene lo divertido, ¿Como accedo a una base de datos sqlite?

Para ello Android ofrece la clase abstracta android.database.sqlite.SQLiteOpenHelper con los métodos onCreate y onUpgrade. El método onCreate se llama la primera vez que se crea la base de datos, en mi caso, RADAR_LOCATION y con el método onUpgrade, se actualiza la base de datos, en caso de que modifiquemos la versión de esta.

 private static class DatabaseHelper extends SQLiteOpenHelper {
  DatabaseHelper(Context context) {
   super(context, DATABASE_NAME, null, DATABASE_VERSION);
  }

  @Override
  public void onCreate(SQLiteDatabase db) {
   Log.w(TAG, "Create database " + DATABASE_NAME);
   db.execSQL(DATABASE_CREATE);
  }

  @Override
  public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
   Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
     + newVersion + ", which will destroy all old data");
   db.execSQL("DROP TABLE IF EXISTS " + DATABASE_TABLE);
   onCreate(db);
  }
 }
La creación de la base de datos se realiza en el constructor de la clase DatabaseHelper que hereda SQLiteOpenHelper, llamando al constructor de la clase heredada, pasando como argumento el nombre de la base de datos, en este caso radars y la versión de la base de datos. DATABASE_CREATE es un String con la sentencia SQL para crear la base de datos:
 private static final String DATABASE_CREATE = "create table "
   + DATABASE_TABLE
   + " (_id integer primary key autoincrement, "
   + "latitude real not null, longitude real not null, radar_type integer not null, speed integer not null, direction_type integer not null, direction integer not null, postal_code text)";
En caso de que la versión de la base de datos se modifique, se ejecuta el método onUpgrade, que hace un drop de la tabla radar_location y vuelve a crearla. Queda por último crear la clase que hará uso de esta clase Helper, Para la siguiente entrada...

lunes, 16 de enero de 2012

Primera aplicación. Parte 1



He decidido realizar una aplicación avisadora de radar de carretera. Lo he decidido así porque se pueden tocar muchos palos con una aplicación como esta. Las funcionalidades de las que esta compuesta la aplicación son las siguientes:

Acceso a base de datos
API de localización GPS
Uso de servicios Android
API multimedia para el uso de sonidos.
Personalización de vistas

En esencia, la aplicación cargará en una base de datos sqlite los datos relativos a la posición de los radares que existen en la red de carreteras de España, y usará estos datos para compararlos con la posición GPS actual. En caso de que exista un radar de carretera en una distancia específica respecto a la distancia recogida por el teléfono móvil, notificará este evento al usuario mediante un mensaje en la pantalla del móvil y un sonido de alarma.

La aplicación correrá en background haciendo uso la clase del API de Android Service.



miércoles, 11 de enero de 2012

Comienzo de la aventura


Un nuevo blog ha dado a luz hoy, y espero que tenga recorrido en el poco tiempo libre que tengo. En este pequeño espacio espero plasmar los avances que realizo en el estudio sobre desarrollo de aplicaciones móviles sobre Android y espero que me cunda para iPhone, aunque esto implicaría aprender aprender Objetive-C, cosa que no me tienta mucho.

Espero que los que por aquí recaléis, obtengáis ayuda en este doloroso mundo que es el de la informática.