jueves, 24 de mayo de 2012

Disculpenme


En esta ocasión, simplemente vengo a disculparme por mi falta de atención hacia el blog, pero a la misma vez, vengo a anunciar que dentro de poco retomo los temas dejados hace unas semanas atrás.

Espero que no hayan tenido ningún inconveniente con la realización de las mini apps que he publicado, seguiré mejorando para brindarles lo mejor de mi.

By

NayosX Ness

martes, 8 de mayo de 2012

Dos regalitos de EA Games para Ubuntu

Bueno, hace un  momento estaba leyendo los artículos de Google Reader y me encuentro con la noticia desde OmgUbuntu, en donde mencionan que los señores de EA Games han dejado dos joyitas de juegos para nosotros los Ubunteros (desde ayer me volví nuevamente Ubuntero, y me ha gustado mucho esta nueva versión),  se trata de Lord of Ultima y Command & Conquer Tiberium Alliances.


Si no sabes de que se trata he aqui un video de Command & Conquer Tiberium Alliances



Y el de Lord of Ultima


El precio de ambos juegos es de $0.00, así que aprovechemos esa oferta y a jugar se ha dicho y se pueden descargar de los siguientes enlaces, pero sin antes olvidar que dichos juegos se corren desde cualquier emulador con flash activo, al instalarlo simplemente nos proporcionan un link directo hacia dichos juegos (al dar clic sobre las imágenes se abrirá un mensaje solicitud de protocolo, así que denle clic en ejecutar aplicación y se abrirá el centro de sotfware de Ubuntu).

Lord of Ultima

Command & Conquer Tiberium Alliances


Algunas capturas








Via: OmgUbuntu
Gracias a: UbuntuLife

lunes, 7 de mayo de 2012

BDate Parte 6 - Re-editando la clase Crear.java

Ya que tenemos listo nuestro ListView, nos hace falta agregarle datos a la base de datos, para ello volvemos  a editar la clase Crear.java y dejamos al método guardarArchivo() de la siguiente manera

private void guardarArchivo() {
  // TODO Auto-generated method stub

//deben de crear una instancia DBAdapter llamada myAdapBD, al inicio del codigo
//junto con los botones y los edittext de esta clase
//de lo contrario generara errores ya que no encontraria esa instancia
//Dicha instancia se inicializa en el metodo inicializar() de la clase Crear.java
//asi que mucho ojo con ese detalle 


  try {
   myAdapBD.abrir();
   myAdapBD.insertarNotas(titu, nota.getText().toString());
   myAdapBD.cerrar();
  } catch (SQLiteException se ) {
         Log.e(getClass().getSimpleName(), "No se ha podido guardar la nota");
        }
  /*
  try
  {
   
   if(estado.equals(Environment.MEDIA_MOUNTED))
   {
    File ruta = Environment.getExternalStorageDirectory();
    File archivo = new File(ruta, titu);
    OutputStreamWriter save = new OutputStreamWriter(new FileOutputStream(archivo));
    save.write(nota.getText().toString());
    save.close();
    
    myAdapBD.abrir();
    myAdapBD.insertarNotas(titu, nota.getText().toString());
    myAdapBD.cerrar();
    
   }
  }
  catch(Exception e)
  {
   Toast.makeText(this, "No se pudo guardar el archivo: "+titu, Toast.LENGTH_LONG).show();
  }*/



//  
 }
Como veran ya no creamos un archivo en la memoria externa del dispositivo, sino que toda la informacion la guardamos dentro de la base de datos que hemos creado.

Ademas hay que volver a tocar el método onClick(), esto para intentar hacerlo lo mas profesionalmente posible, le agregaremos un tipo de alerta, el cual se crea cuando se pincha sobre el botón bGuardar, el código queda de la siguiente manera
public void onClick(View v) {
  // TODO Auto-generated method stub
  switch(v.getId())
  {
  case R.id.bGuardar:
   titu = titulo.getText().toString();
   if(! titu.equals(""))
   {
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setMessage("Estas seguro de guardar la nota o deseas seguir editandola")
           .setCancelable(false)
           .setPositiveButton("Guardar", new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int id) {
                guardarArchivo();//aqui se agrega el metodo 
                   Crear.this.finish();
               }
           })
           .setNegativeButton("Editar", new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int id) {
                    dialog.cancel();
               }
           });
    AlertDialog alert = builder.create();
    alert.show();
   }
   else
   {
    Toast.makeText(getApplication(), "No has agregado un titulo a la nota \nLa nota no se puede guardar aun", Toast.LENGTH_LONG).show();
   }
   
   break;
  case R.id.bCancelar:
   finish();
   break;
  }
 }
En el caso de bGuardar, se comienza dandole un valor a la variable titu (la que almacena lógicamente el titulo de la nota), luego con un if preguntamos si el titulo esta vació, de ser así nos avisa con un Toast, de lo contrario genera un AlertDialog.Builder llamado builder, no explicare cada uno de los métodos que se utiliza para crear y utilizar un Objeto de dicha clase, ya que es muy simple de entender y de utilizar, mas adelante quizás lo personalicemos, pero por el momento nos sobra y basta con saber que se crea dicho dialogo, luego se crea una instancia AlertDialog llamada alert a la que se le asigna el dialogo (es decir builder.create() ), para terminar se muestra la alerta con el método show().


El botón bCancelar sigue igual, no se le hace ningún cambio.

Ahora lo que tenemos que volver a editar es el texto del botón bLeer y de bCrear, de nuestra clase principal (main.xml) y editar un poco la clase BDateActivity.java, para que no nos lleve a la clase Leer.java (en otras palabras tocaremos en método onClick()), sino que nos lleve a la clase NotasList.java,

El boton cambia de :
A:



Y el código de la siguiente manera:
public void onClick(View arg0) {
  // TODO Auto-generated method stub
  Intent i; 
  switch(arg0.getId())
  {
  case R.id.bCrearA:
   i = new Intent(BDateActivity.this, Crear.class);
   startActivity(i);
   break;
  case R.id.bLeerA:
   i = new Intent(BDateActivity.this, NotasList.class);
   startActivity(i);
   break;
  }
El cambio que le hemos hecho es minimo, simplemente hemos reemplazado de
 i = new Intent(BDateActivity.this, Leer.class)
a
 i = new Intent(BDateActivity.this, NotasList.class)

Bueno eso es todo por esta ocasión, mas adelante tocaremos nuevamente las clases DBAdapter.java y NotasList.java

domingo, 6 de mayo de 2012

BDate Parte 5 - ListView con base de datos

Bueno ya casi estamos por terminar todo lo referente a la app, ya solo nos queda algunos cuantos pasos mas y tendríamos una app totalmente funcional.

Hemos trabajado los layout, codeamos las clases a usar y creamos una base de datos. Ahora pasaremos a crear un ListView para mostrar todas las notas que creemos, creamos una clase llamada NotasList.java.


Ya que tenemos la clase creada,  pasemos a mostrar el código usado
package com.nayosx.nl;

import java.util.ArrayList;

import android.app.ListActivity;
import android.database.Cursor;
import android.database.sqlite.SQLiteException;
import android.os.Bundle;
import android.util.Log;
import android.widget.ArrayAdapter;

public class NotasList extends ListActivity{
 private ArrayList resultados = new ArrayList();
 private DBAdapter myAdapBD;
 @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        abrirDBAdapter();
        
        mostrarResultados();
        
    }
 
 
 private void mostrarResultados() {
  // TODO Auto-generated method stub
  setListAdapter(new ArrayAdapter(this,
                android.R.layout.simple_list_item_1, resultados));
        getListView().setTextFilterEnabled(true);
 }
 
 
 
 private void abrirDBAdapter() {
  // TODO Auto-generated method stub
  try {
   myAdapBD = new DBAdapter(this);
   myAdapBD.abrir();
   Cursor c = myAdapBD.getAllNotas();
   if (c.moveToFirst())
   {
   do {
    addToLista(c);
   } while (c.moveToNext());
   }
   myAdapBD.cerrar();
  } catch (SQLiteException se ) {
         Log.e(getClass().getSimpleName(), "NO se ha podido acceder a la base de datos");
        }
 }


 private void addToLista(Cursor c) {
  // TODO Auto-generated method stub
  resultados.add(c.getString(1));
 }
 
 
 
}
//

Como lo notaran esta clase no hereda de Activity sino mas bien de ListActivity, ademas no hacemos uso de ningún layout, pero si sobre-escribimos el  método onCreate() ya que es el punto de partida de cualquier aplicación Android.

Dentro del método onCreate() agregamos dos métodos uno llamado abrirDBAdapter() y el otro mostrarResultados().

El método abrirDBAdapter() se encarga de consulta a nuestra clase DBAdapter, para recuperar toda la información de las notas (mas en especifico el titulo de ellas), adentro de este método se maneja una posible excepción, esto por si no se logra abrir la base de datos y ademas hacemos uso de un do-while para recuperar toda esa información, luego se pasa a un método llamado addToLista(), esto para agregarlo al ArrayList llamado resultados, el cual se encarga de llenar todo el ListView.


Ademas de lo mencionado anteriormente, es ahí donde terminamos creando nuestra instancia DBAdapter la cual se llama myAdapBD, esta instancia nos sirve para abrir la base de datos, para decirle al Cursor (llamado simplemente c), de donde recuperara datos y para cerrar la base de datos.


mostrarResultados() se encarga de formatear nuestro ListView, para ello hace uso del método setListAdapter(), en donde se crea una instancia ArrayAdapter() y dentro de sus parámetros se le dice de que contexto hacemos uso (this), el estilo que llevara (android.R.layout.simple_list_item_1) y un arreglo de objetos el cual sirve para crear la lista a desplegar (resultados).

Para terminar con esta clase, hay que agregarla al AndroidManifest, el cual nos queda de la siguiente manera


Bueno eso es todo por esta ocasión, luego seguiremos con el tutorial, espero que les guste.

BDate Parte 4 - Creando la base de datos

Ya trabajamos los layout y algunas clases de esta aplicación, en donde creábamos un archivo de texto y lo manejábamos mediante flujos (Stream), pero solo nos servia para crear y abrir un solo archivo (se podía mejorar eso, pero lo haremos mas eficiente aun). En esta ocasión haremos uso de una base de datos para guardar y recuperar información y de esta manera tener N cantidad de notas, así que manos a la obra.

Lo primero sera hacernos de una clase auxiliar y adaptarla a nuestras necesidades para que el manejo de los datos sea simple. Esta clase sera llamada BDAdapter.java


El código fuente de esta clase es el siguiente:
package com.nayosx.nl;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

public class DBAdapter {
 public static final String KEY_ROWID = "_id";
 public static final String KEY_TITULO = "titulo";
 public static final String KEY_NOTA = "nota";
 
 
 public static final String DATABASE_NAME = "DB_Notas_BDate";
 public static final String DATABASE_TABLE = "BDate";
 public static final int DATABASE_VERSION = 1;
 public static final String TAG = "DBAdapter";
 
 
 public static final String DATABASE_CREATE = "create table "+DATABASE_TABLE+"("+KEY_ROWID+" integer primary key autoincrement not null, "+
             KEY_TITULO+" text not null, "+KEY_NOTA+" text not null);"; 
 
 private final Context context;
 private DatabaseHelper DBHelper;
 
 private SQLiteDatabase db;
 
 public DBAdapter(Context ctx)
 {
  this.context = ctx;
  DBHelper = new DatabaseHelper(context);
 }
 
 
 public static class DatabaseHelper extends SQLiteOpenHelper{

  public DatabaseHelper(Context context) {
   super(context, DATABASE_NAME, null, DATABASE_VERSION);
   // TODO Auto-generated constructor stub
  }

  @Override
  public void onCreate(SQLiteDatabase db) {
   // TODO Auto-generated method stub
   try{
    db.execSQL(DATABASE_CREATE);
   }
   catch(SQLException e)
   {
    e.printStackTrace();
   }
  }

  @Override
  public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
   // TODO Auto-generated method stub
   Log.w(DBAdapter.TAG, "se ha actualizado la base de datos");
   db.execSQL("DROP TABLE IF EXIST"+DBAdapter.DATABASE_TABLE);
   onCreate(db);
  }

 }
 
 
 public DBAdapter abrir() throws SQLException
 {
  db = DBHelper.getWritableDatabase(); 
  return this;
  
 }
 public void cerrar()
 {
  DBHelper.close();
 }
 
 public long insertarNotas(String titu, String nota)
 {
  ContentValues initVal = new ContentValues();
  initVal.put(KEY_TITULO, titu);
  initVal.put(KEY_NOTA, nota);
  return db.insert(DATABASE_TABLE, null, initVal);
 }
 
 public Cursor getAllNotas()
 {
  String [] getMain = {KEY_ROWID,
       KEY_TITULO,
       KEY_NOTA
       };
  return db.query(DATABASE_TABLE, getMain, null, null, null, null, null);
 }
}


A continuación la explicación del código de esta clase:

Las constantes estáticas


 public static final String KEY_ROWID = "_id";
 public static final String KEY_TITULO = "titulo";
 public static final String KEY_NOTA = "nota";
 
 
 public static final String DATABASE_NAME = "DB_Notas_BDate";
 public static final String DATABASE_TABLE = "BDate";
 public static final int DATABASE_VERSION = 1;
 public static final String TAG = "DBAdapter";
 
 
 public static final String DATABASE_CREATE = "create table "+DATABASE_TABLE+"("+KEY_ROWID+" integer primary key autoincrement not null, "+
             KEY_TITULO+" text not null, "+KEY_NOTA+" text not null);"; 
 
 

Sirven para crear toda la base de datos, son muy simples de entender ya que ellas solas se explican, quizás la mas difícil de comprender sea la DATABASE_CREATE, pero simplemente se trata de una sentencia SQL en donde le indicamos la tabla que queremos crear, así como todos sus campos y la llave primaria de dicha tabla.



las demás variables y el constructor de la clase DBAdapter

 
 private final Context context;
 private DatabaseHelper DBHelper;
 
 private SQLiteDatabase db;
 
 public DBAdapter(Context ctx)
 {
  this.context = ctx;
  DBHelper = new DatabaseHelper(context);
 }
 

Bueno si han leido un poco la documentacion de Android sobre SQLiteOpenHelper, sabran que se necesita de un contexto (en este caso simplemente llamado context)en el cual actuar, por esta razón nuestro adaptador crea una variable que sera utilizada dentro del constructor de nuestra clase BDAdapter .

Ademas necesitamos crear una clase (llamada SQLiteDatabase y como instancia db) dentro de nuestra clase BDAdapter (no es necesario hacerlo así, pero para ahorrar tiempo y espacio lo deje de esa manera).
Dentro del constructor de nuestra clase BDAdapter, inicializamos el contexto y luego se lo asignamos al constructor de SQLiteDatabase (Esto para mandarselo a la clase padre de SQLiteDatabase, es decir para mandárselo al constructor de la clase SQLiteOpenHelper).

Se que suena confuso, pero esa es la forma adecuada de actuar con la clases SQLiteOpenHelper.


La clase SQLiteDatabase 

 public static class DatabaseHelper extends SQLiteOpenHelper{

  public DatabaseHelper(Context context) {
   super(context, DATABASE_NAME, null, DATABASE_VERSION);
   // TODO Auto-generated constructor stub
  }

  @Override
  public void onCreate(SQLiteDatabase db) {
   // TODO Auto-generated method stub
   try{
    db.execSQL(DATABASE_CREATE);
   }
   catch(SQLException e)
   {
    e.printStackTrace();
   }
  }

  @Override
  public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
   // TODO Auto-generated method stub
   Log.w(DBAdapter.TAG, "se ha actualizado la base de datos");
   db.execSQL("DROP TABLE IF EXIST"+DBAdapter.DATABASE_TABLE);
   onCreate(db);
  }

 }

Esta clase es la que realmente crea la base de datos, esta interna a nuestra clase DBAdapter, quizás muchos de ustedes ya hayan trabajado con ella. Su creación es simple, se comienza heredando de SQLiteOpenHelper la cual nos pedirá que creemos un constructor para comenzar a trabajarla, luego sobre escribimos los métodos onCreate() y onUpgrade(), los cuales nos permitirán crear y mejorar la base de datos.

El constructor simplemente inicializa el nombre de la base de datos así como su versión.
onCreate() se encarga de terminar el trabajo con el método execSQL() y como parámetro nuestra constante estática  DATABASE_CREATE, no confundir el parámetro db (que hace uso del metodo execSQL() ), con la instancia db, ambas son ajenas y la diferencia entre ambas es grande.

onUpgrade() se encarga de hacer los ajustes a la base de datos, en caso de que creemos un nuevo campo en algunas de las tablas, o que creemos alguna tabla extra, recordemos que solo tenemos una tabla y que no necesitaremos hacer eso, pero es recomendable dejarlo de esa manera.


Los métodos de ayuda de DBAdapter


 
 public DBAdapter abrir() throws SQLException
 {
  db = DBHelper.getWritableDatabase(); 
  return this;
  
 }
 public void cerrar()
 {
  DBHelper.close();
 }
 
 public long insertarNotas(String titu, String nota)
 {
  ContentValues initVal = new ContentValues();
  initVal.put(KEY_TITULO, titu);
  initVal.put(KEY_NOTA, nota);
  return db.insert(DATABASE_TABLE, null, initVal);
 }
 
 public Cursor getAllNotas()
 {
  String [] getMain = {KEY_ROWID,
       KEY_TITULO,
       KEY_NOTA
       };
  return db.query(DATABASE_TABLE, getMain, null, null, null, null, null);
 }


Creo que estos metodos no necesitaran mucha explicación, ya que casi todos estan en español

abrir() retorna Una instancia DBAdapter y simplemente le asigna a db el valor (o como querramos llamarlo) del método estático getWritableDatabase(), es decir le indica que queremos abrir nuestra base de datos.

cerrar() no creo que necesite explicación alguna.

insertarNotas() solamente esta esperando a que le mandemos valores, luego se encarga de insertarlos en la base de datos. Hace uso de ContentValue para luego mandarle todo el contenido al método insert().

getAllNotas() nos ayuda a obtener todos los valores de la base de datos, haciendo uso del método query()

Bueno hasta aquí lo que es referente a la base de datos, mas adelante le agregaremos otros métodos para eliminar, actualizar el contenido de ella (e implícitamente la de las notas).

La siguiente parte del tutorial tratara sobre el ListView con el que mostraremos las notas (recuperando todo el contenido de nuestra base de datos), así que pendientes

El Gimp 2.8

Luego de 3 largos años al fin sacaron la versión 2.8 de este gran programa, si ya se que lo sacaron hace unos días atrás, pero esta es la versión para windows, anteriormente solo estaba el puro code source. Yo llevo usándolo alrededor de unos 2 años (versión 2.6), al principio no lo podía usar ni pepa, quizás porque estaba muy acostumbrado a usar Photoshop CS no se que, ahora todas las ediciones las hago con el Gimp, luego de 1 hora viendo videos en youtube aprendí a usarlo.

Entre algunas de las novedades de esta versión están las siguientes características:


  • Venta única (no por defecto, se tiene que activar para que se vea al estilo Photoshop)
  • La función guardar ahora solo guarda con extensión propia del Gimp (.xcf)
  • Multi-Column Dock Windows (podemos tener varios agrupables en una ventana aparte)
  • Layer Groups (podemos agrupar muchos layout en un solo grupo)
  • On-Canvas Text Editing (la edición de texto se ve mucho mejor)
Esa solo son algunas de las tantas novedades que nos trae esta versión, a continuación algunas capturas de pantallas. 








Bueno eso es todo, para descargarlo simplemente hay que  dar clic en el siguiente enlace


Si no les parece, pueden visitar la pagina oficial de el  Gimp.