lunes, 26 de agosto de 2019

Cambiar el color a un checkbox de Android

Aunque no lo parezca, cambiarle el color a un checkbox es muy difícil (de encontrar la solución), pero muy fácil de implementar:

Después de mucho buscar en stackoverflow di con las siguientes instrucciones:

if (Build.VERSION.SDK_INT < 21) {
    CompoundButtonCompat.setButtonTintList(checkbox, ColorStateList.valueOf(color));} else {
    checkbox.setButtonTintList(ColorStateList.valueOf(color));}

Donde checkbox es la view y color es un recurso obtenido a través de uno de los colores de color.xml
color = context.getResources().getColor(R.color.SALUD);

Cabe mencionar que dependiendo la versión de android que se elija, es uno u otro.
Yo recomiendo poner ambos casos para máxima compatibilidad.

Saludos.

Listview personalizado.

Hoy vamos a hacer una lista personalizada.
El ejemplo que haremos será una lista con un texto, una imagen y un checkbox para marcar o desmarcar. Servirá como una lista de favoritos, si el check está marcado, se marca como favorito.

Necesitamos:

1. Layout de la lista.
2. Adaptador de la lista.

1. Layout de la lista.
Irá en la carpeta res/layout, utilizaremos Linear Layout por su simplicidad.

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:orientation="vertical"    >    <View        android:layout_width="match_parent"        android:layout_height="1dp"        android:background="@android:color/darker_gray"/>
    <LinearLayout    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:orientation="horizontal"    >
        <CheckBox            android:id="@+id/checkBoxFavorito"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:layout_weight="3"            android:layout_gravity="center"            android:layout_marginLeft="15dp"            android:buttonTint="@color/rojoWaifu"        />
        <ImageView        android:id="@+id/imageView"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_gravity="center"        android:layout_weight="3"        />
    <TextView        android:id="@+id/textView"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:textColor="#000000"        android:textSize="18sp"        android:layout_weight="1"        android:layout_marginRight="10dp"        android:shadowColor="#606060"        android:shadowDx="1.3"        android:shadowDy="1.1"        android:shadowRadius="1.4"        />    </LinearLayout>
</LinearLayout>

Tenemos un checkbox, un imageview y un text view

2. El Adapter:

public class ListaNormasAdapter extends ArrayAdapter<Norma> {
    private Context context;    private int resourceId;    private List<Norma> items;    private NormasAdapterObserver observer = null;    public static final String TAG = "ListaNormasAdapJass";
    public ListaNormasAdapter(@NonNull Context context, int layoutACargar, ArrayList<Norma> items) {
        super(context, layoutACargar, items);        this.items = items;        this.context = context;        this.resourceId = layoutACargar;
        //El observador necesario para notificar que los objetos/items de la lista han cambiado.        if(context instanceof  NormasAdapterObserver){
            this.observer = (NormasAdapterObserver) context;        }
    }

    @NonNull    @Override    public View getView(final int position, @Nullable View convertView, @NonNull ViewGroup parent) {
        ArrayList<Integer> normasFavoritas = Preferencias.getFavoritos(context, Preferencias.NORMA);        View view = convertView;        try {
            if (convertView == null) {
                LayoutInflater inflater = ((Activity) context).getLayoutInflater();                view = inflater.inflate(resourceId, parent, false);            }

            final Norma normaACargar = getItem(position);
            TextView descripcionNorma = (TextView) view.findViewById(R.id.textView);
            //Establecemos lo que queremos hacer cuando cliqueen en el texto.            descripcionNorma.setOnClickListener(new View.OnClickListener() {
                @Override                public void onClick(View v) {
                    abrirNorma(normaACargar);                }
            });
            ImageView imageView = view.findViewById(R.id.imageView);            //Establecemos lo que queremos hacer cuando cliqueen en la imagen.            imageView.setOnClickListener(new View.OnClickListener() {
                @Override                public void onClick(View v) {
                    abrirNorma(normaACargar);                }
            });

            imageView.setImageResource(normaACargar.getImagen());
            final CheckBox checkbox = view.findViewById(R.id.checkBoxFavorito);
            if(normasFavoritas.contains(normaACargar.getNumeroNorma())){
                checkbox.setChecked(true);            }
            else{
                checkbox.setChecked(false);            }

            checkbox.setOnClickListener(new View.OnClickListener() {
                @Override                public void onClick(View v) {
                    CheckBox checkbox = (CheckBox)v;                    if(!checkbox.isChecked()){
                        Preferencias.borrarFavoritos(context, Preferencias.NORMA,normaACargar.getNumeroNorma());                    }
                    else{
                        Preferencias.agregarAFavoritos(context, Preferencias.NORMA,normaACargar.getNumeroNorma());                    }
                    //Se puso un observer porque se ocupaban hacer más cosas en la activity de la lista, pero no es necesario si pueden manejar el cambio de datos aquí.
                    //Sólo recuerden llamar a setItems y a notify para que les actualice la vista.
                    if(observer != null)
                    {
                        observer.actualizarLista();                    }
                }
            });
            descripcionNorma.setText(normaACargar.getDescripcion());            //Dependiendo el grupo de norma, podemos cambiar los atributos dentro de los elementos de la lista como su color.            int color = 0;            if (normaACargar.getGrupo().equals(Constantes.GRUPO_SALUD)) {
                color = context.getResources().getColor(R.color.SALUD);            }
            else if (normaACargar.getGrupo().equals(Constantes.GRUPO_ORGANIZACION)) {
                color = context.getResources().getColor(R.color.ORGANIZACION);            }
            else if (normaACargar.getGrupo().equals(Constantes.GRUPO_SEGURIDAD)) {
                color = context.getResources().getColor(R.color.SEGURIDAD);            }
            else if (normaACargar.getGrupo().equals(Constantes.GRUPO_ESPECIFICAS)) {
                color = context.getResources().getColor(R.color.ESPECIFICA);            }
            else if (normaACargar.getGrupo().equals(Constantes.GRUPO_PRODUCTO)) {
                color = context.getResources().getColor(R.color.PRODUCTO);            }
            //Asignamos el color del texto y de los checkbox:
            descripcionNorma.setTextColor(color);            if (Build.VERSION.SDK_INT < 21) {
                CompoundButtonCompat.setButtonTintList(checkbox, ColorStateList.valueOf(color));            } else {
                checkbox.setButtonTintList(ColorStateList.valueOf(color));            }

        } catch (Exception e) {
            e.printStackTrace();        }
        return view;    }

    @Nullable    @Override    public Norma getItem(int position) {
        return items.get(position);    }

    @Override    public int getCount() {
        return items.size();    }

    @Override    public long getItemId(int position) {
        return position;    }

    private void abrirNorma(Norma norma){
        //Hacemos cosas con el objeto que cliqueó el usuario...
        //En este caso, abriremos otra actividad, pero podría ser cualqier cosa.
        Intent intent = new Intent(context, VisorPDFActivity.class);        intent.putExtra(Constantes.NUMERO_DE_NORMA, norma.getNumeroNorma());        context.startActivity(intent);    }

    public void setItems(List<Norma> items) {
        this.items = items;    }
}

3. El observer:
No es necesario, pero puede ser útil si necesitan desplegar un anuncio o algo así desde la activity que controla la lista de objetos. En este caso nada más lee de nuevo las normas favoritas y las asigna al adapter para que actualice la vista con los elementos agregados o quitados.

@Overridepublic void actualizarLista() {
    ArrayList<Norma> normasAMostrar = new ArrayList<Norma>();    for (Norma norma : normasCompletas) {
        for (int normaFavorita : Preferencias.getFavoritos(this,Preferencias.NORMA)) {
            if (norma.getNumeroNorma() == normaFavorita) {
                normasAMostrar.add(norma);            }
        }
    }
    normaAdapter.setItems(normasAMostrar);    normaAdapter.notifyDataSetChanged();}

Y el resultado sería este:



Al quitar el checkbox, si la activity que responde al evento es un NormasAdapterObserver, se eliminaría el elemento de la vista.
Por otro lado, si no es de tipo NormasAdapterObserver, podemos elegir que solamente borre de las preferencias los datos, sin quitarlo de la lista.

Espero que les sirva.
¡Saludos!

viernes, 16 de agosto de 2019

Guardar ArrayList de Strings o ints en SharedPreferences

Hola, hoy creamos un método que guarde un ArrayList de Strings o números en las preferencias.
Necesitaremos:

1. Clase estática que contenga las constantes a utilizar.

Yo creé una clase que se llama GuardarPreferences, es necesario que sea estática porque la idea es que pueda se llamada desde cualquier parte de nuestra App con solo enviarle un contexto, pues las shared preferences requieren uno.

Las constantes indicarán qué tipo de campo quiero guardar, en este caso "NORMAS" significa que quiero guardar un número de norma x, podrían ponerle por ejemplo, NOMBRES, COLORES, o lo que ustedes quieran, más que nada es para identificar qué cosa voy a guardar.
la variable numeroDeNorma, es el valor a guardar.

El apartado de IDENTIFICADOR, no es más que un string para saber qué shared preferences abrirá, podrían poner el nombre de su paquete, o cualquier otra cosa que tenga sentido para ustedes.

Las preferences no pueden guardar ArrayList, pero sí un HashSet, por eso indicaba que podíamos guardar strings o enteros, porque podemos cambiarlos fácilmente.

En este ejemplo guardaré Strings, pero recibiré enteros, para demostrar la conversión.
El código completo:

public class GuardarPreferences {

    public static final String NORMA = "NORMAS";
    private static final String IDENTIFICADOR  = "Normas favoritas";
    public static void agregarAFavoritos(Context contexto, String campo, int numeroDeNorma){
        SharedPreferences preferencias = contexto.getSharedPreferences(IDENTIFICADOR,Context.MODE_PRIVATE);        SharedPreferences.Editor editor = preferencias.edit();
        ArrayList<String> normasFavoritas = new ArrayList<String>();
        if(campo.equals(NORMA)){
            normasFavoritas = new ArrayList<String>(preferencias.getStringSet(NORMA, new HashSet<String>()));            if(!normasFavoritas.contains(numeroDeNorma)) {
                normasFavoritas.add(numeroDeNorma + "");                editor.putStringSet(NORMA,new HashSet<String>(normasFavoritas));      editor.clear();
          editor.commit();            }
        }

    }

    public static void borrarFavoritos(Context contexto, String campo, int valor){
        SharedPreferences preferencias = contexto.getSharedPreferences(IDENTIFICADOR,Context.MODE_PRIVATE);        Set<String> normasFavoritas = preferencias.getStringSet(campo, new HashSet<String>());        normasFavoritas.remove(valor+"");        SharedPreferences.Editor editor = preferencias.edit();        editor.putStringSet(NORMA,new HashSet<String>(normasFavoritas));    editor.clear();
    editor.commit();    }

    public static ArrayList<Integer> getFavoritos(Context contexto, String campo){
        SharedPreferences preferencias = contexto.getSharedPreferences(IDENTIFICADOR,Context.MODE_PRIVATE);
        Set<String> normasFavoritas = preferencias.getStringSet(campo, new HashSet<String>());        ArrayList<Integer> normasFavoritas2 = new ArrayList<Integer>();        for(String normaGuardada:normasFavoritas){
            normasFavoritas2.add(Integer.parseInt(normaGuardada));        }
        return normasFavoritas2;    }

}

Para guardar otro dato, sólo tenemos que crear una constante nueva y agregarla al IF, por ejemplo para guardar nombres, podemos hacer un nuevo método igual, que en vez de recibir un int en numeroDeNorma, contenga String nombre, y nos ahorramos el casteo.

Usando los métodos desde una clase de tipo Activity:

GuardarPreferences.agregarAFavoritos(this,NORMA,15);GuardarPreferences.borrarFavoritos(this,NORMA,15);GuardarPreferences.getFavoritos(this,NORMA);

¡Recuerden siempre llamar a editor.clear();de lo contrario las preferencias se resetearán si la app se fuerza a cerrar o se reinicia el teléfono!

Espero que les sirva.
¡Saludos!

viernes, 23 de octubre de 2015

Cuatro tipos archivos esenciales de todo desarrollo web.

Hola amigos, últimamente he estado desarrollando muchos proyectos de php y platicando con algunos colegas me he dado cuenta que a veces por hacer rápido algo luego al modificarlo tardamos demasiado tiempo buscando dónde estaba cada cosa, cambiando nombres de variables, etc. Dedicaré este espacio para los que van empezando con el desarrollo web.

Archivos de configuración.
Los archivos de configuración constan de cualquier dato de autenticación, rutas a directorios, puertos, etc. Esto incluye por ejemplo usuario y password de la base de datos, los puertos que utilizará la aplicación. La ruta hacia las imágenes o documentos subidos.
Un ejemplo podría contener lo siguiente:

<?php

//variables de conexion a la bd
$servidor = "localhost";
$usuario = "root";
$password = "1234";
$database = "edmx";

//URL's
$url_alta_tipo_equipos="registro_tipo_equipos.html";
$url_alta_usuarios="alta_users.php";
$url_imagenes="/storage/images/";
?>

Esquema de la base de datos.
En este archivo se especifican los nombres de las bases de datos, las tablas y los campos, esto con el fin de que si el diseño de la base llega a cambiar, basta con modificar el archivo de esquema para actualizar todas las dependencias, además también deberíamos almacenar las sentencias para la creación de la base de datos desde cero y un par de inserts predefinidos por si ocupamos borrarla.

Un ejemplo podría contener lo siguiente:

//TABLAS
$tabla_tipo_de_equipo="tipo_equipo";
$tabla_asesores="asesores";
$tabla_equipos="equipamiento";

//campos
$campo_id_equipo="id_equipo";
$campo_ventas_por_mes="venta_mensual";

Manejadores de la base de datos, de sesión, etc.
Es conveniente crear un archivo que contenga métodos para acciones comunes como inserción, actualización, borrado y selección (CRUD). Otra buena idea es crear un manejador de las operaciones sobre una sesión, en caso de haberla.

Un ejemplo podría contener lo siguiente, nótese que estamos usando las variables de configuracion, y algunas variables de la definición del esquema de la base de datos.

function consulta_simple($sql){
include("config.php");
$conn = new mysqli($servidor, $usuario, $password, $base);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$result = $conn->query($sql);
$resultado=array();
if ($result->num_rows > 0) {
while($row = $result->fetch_row()) {
array_push($resultado, $row);
}
}
else {
}
$conn->close();
return $resultado;
}

function consultarModelos($id_tipo, $marca){
include("config.php");
$sql = "SELECT id_equipo, modelo FROM $tabla_equipos WHERE id_tipo=$id_tipo AND marca='$marca' ORDER BY modelo;";
$marcas=consulta_simple($sql);
return $marcas;
}


Hojas de estilo base.
Crear un archivo de estilos con un diseño "default" nos permitirá modificar las propiedades visuales de muchas páginas con un solo cambio. Aprovechemos la característica de cascada para sobre-escribir los estilos necesarios y mantengamos los que sean más comunes.

Un ejemplo podría contener:

body{
background-color:black;
background-image: url("catbox.jpg");
background-size: 100%;
color:white;
}

//un encabezado genérico
.header{
background:yellow;
width:480px;
height:150px;
border: 2px solid;
    border-radius: 25px;
    border-color:blue;
}

/*contenedor genérico*/
.container{
position:relative;
left:50%;
transform: translate(-50%, 0%);
background:#084D88;
width:350px;
    border-radius: 20px;
    padding:8px;
}

Seguramente hayan usado uno o más de estos tipos de archivos, así que ya sea un recordatorio o algo nuevo, ¡úsenlos que son muy útiles!

miércoles, 21 de octubre de 2015

Guía de mejores monitores económicos 2015

Hola amigos, con la novedad de que he querido actualizar mi monitor a uno que pueda tener al menos 3 ventanas visibles al mismo tiempo me di a la tarea de encontrar monitores relativamente económicos con las mejores características para la multitarea.

Tengo que puntualizar que la tecnología escogida en todos los monitores es IPS, debido a mis requerimientos de color y visualización desde diferentes ángulos, prefiriendo los monitores de tipo "matte" debido a que reflejan menor cantidad de luz.

Las opciones no tienen un orden específico, simplemente trataré de agruparlos por tarea o utilidad, otra cosa por mencionar es que como yo casi siempre compro en amazon por la seguridad que me han proporcionado, pondre los enlaces a su sitio (no, no me dan comisión :( ).

Monitores Ultra Wide: WFHD con un formato 21:9 y resolución 2560 x 1080 son la mejor opción para mantener al menos 3 documentos abiertos al mismo tiempo. Existen diversas opciones, pero estos son los más asequibles:

Para los usuarios de monitores de 19 pulgadas o menos, el salto menos drástico es a un monitor de 25 pulgadas como el siguiente:



LG Electronics UM57 25-Inch Screen LED-lit Monitor:
Luminosidad: 250 cd.
Conectores:  2 entradas HDMI.
Controlador dual (puedes visualizar 2 entradas de video, por ejemplo una pc y un xbox al mismo tiempo) y, este monitor es una buena opción.
Precio: entre los 170 y los 200 usd en Amazon.

Si podemos aumentar nuestro presupuesto hasta el rango de los 300 usd, encontramos monitores de 29 pulgadas como:



AOC Q2963PM 29-inch IPS (21:9) LED-Lit Monitor.
Luminosidad: 300 cd.
Conectores: VGA, DVI-D HDCP, HDMI (MHL), Display Port.
2 bocinas estéreo de 3W integradas.
Montaje VESA para utilizar diferentes bases, es una excelente opción, este tamaño es ideal para los usuarios acostumbrados a monitores de 24 pulgadas.
Precio: 330 usd en Amazon.



Otro modelo asequible es el hermano mayor del monitor de 25 pulgadas, se trata del monitor
LG Electronics 29UM67 29-Inch Screen LED-lit Monitor: Con 300 cd de luminosidad, con un puerto DVI extra a los HDMI del modelo de 25 pulgadas, cabe mencionar que este monitor deberá utilizarse la base que ya tiene incorporada.
Precio: 350 USD en Amazon.


A pesar de que los monitores WFHD proveen de un área de trabajo extendida, muchos usuarios no logran acostumbrarse a ese aspecto, por lo que regresando a los monitores clásicos 16:9 consideramos la siguiente lista:

Los monitores WQHD con resolución 2560x1440 nos brindan hasta 50% más espacio de trabajo que un monitor full hd, por lo que los detalles serán mejor perceptibles. En estos modelos, el tamaño ideal es el de 25 pulgadas, con relación de aspecto 16:10, cambiando el tamaño común de 24 y 27 pulgadas que se suelen utilizar en los full hd, esto debido a la mayor densidad de píxeles que se pueden contener en los monitores de 25 y 27 pulgadas.

El modelo más económico de este tipo de monitores es el


Acer G257HU smidpx 25-Inch WQHD
Luminosidad: 350 nit.
Conectores: 1 conector DVI (HDCP), 1 HDMI y 1 Display Port.
Es una actualización económica desde un monitor full hd. Cuenta con 2 altavoces integrados.
Precio: entre 240 y 260 USD en Amazon.

Por otra parte, con un poco más de presupuesto, podemos adquirir el monitor


Monitor Dell UltraSharp de 25 pulgadas - U2515H. Este monitor cuenta con un panel que cubre el 99% de colores sRGB, por lo que es especialmente útil para trabajos de diseño gráfico o animación, cuenta con garantía de 3 años y es extensible hasta 5 años.

Luminosidad: 350cd.
Conectores: 2 conectores HDMI (MHL), 1 Mini DisplayPort, 1 DisplayPort (versión 1.2), 1 salida de DisplayPort (MST), 1 salida de línea de audio, 5 puertos USB 3.0: Flujo descendente (1 con carga de batería) y 1 puerto USB 3.0 de subida
Montaje VESA.
Base de altura ajustable, inclinación, movimiento giratorio y pivotante.
Precio: entre 4700 y 5000 pesos en DELL México. En mi opinión, el mejor monitor de 25 pulgadas que se puede adquirir en este rango de precio.

Mención especial

A pesar de que este artículo está dedicado a monitores con resoluciones mayores a 1080p debo mencionar que he adquirido un monitor Full HD del que no he tenido queja alguna. El monitor en cuestión es económico al punto de no haber competidores en su rango de precio, tal vez agarré una oferta, o no lo sé pero me salió en 2400 pesos con envío incluido. Se trata de:

Monitor AOC de 23 pulgadas i2369V
Luminosidad: 250cd.
Conectores: DVI-HDCP RGB D-Sub.
Precio: entre 2400 y 2700 pesos en Amazon México.


viernes, 12 de junio de 2015

Simular eventos, acciones, entradas y comandos en un emulador Android,

Cuando comienzas con nuevos proyectos, muchas veces no tienes los dispositivos físicos para hacer las pruebas o no quieres arriesgar información valiosa en tu dispositivo, por lo que tienes que recurrir a emuladores. Además, si tienes un pc potente, puede que incluso sea más cómodo realizar las pruebas en emuladores.

Pues bien, para realizar esto basta con ejecutar nuestra aplicación, seleccionar el AVD (Android virtual device, alias el emulador) que querramos y dentro de android studio ir a la pestaña de terminal.


Después de eso, deberán utilizar el comando

telnet localhost 5554

Si la consola les marca un error de que no se reconoce el comando, es porque no tienen telnet activado en su windows, para lo cual sigan los siguientes pasos

Para instalar el cliente Telnet

  1. Haga clic en el botón InicioImagen del botón Inicio, haga clic en Panel de control y, a continuación, en Programas.
  2. En Programas y características, haga clic en Activar o desactivar las características de Windows. Se requiere permiso de administrador Si se le solicita una contraseña de administrador o una confirmación, escriba la contraseña o proporcione la confirmación.
  3. En el cuadro de diálogo Características de Windows, active la casilla Cliente Telnet.
  4. Haga clic en Aceptar. La instalación puede durar varios minutos.
Una vez conectados podemos usar distintas funciones emuladas en nuestro dispositivo virtual como por ejemplo la función:

geo fix 19.282754, -99.676644

Que simulará que el dispositivo se encuentra en esas coordenadas (Facultad de Ingeniería de la UAEMex) por ejemplo, para utilizar en una applicación de geolocalización.

O por ejemplo una simular una llamada del 123-4567

gsm call 1234567

Entre otras funciones. Saludos.

Consultar estructura de las tablas en una base de datos de Android

Qué tal, les cuento que ahora que estuve realizando el tutorial de udacity, me atoré con un problema de llaves primarias, según el tutorial que seguí de la BD, se recomendaba poner la llave primaria en autoincrementar, y como ya saben que me gusta llevarle la contra a todo, yo hice mi tabla sin el autoincremento, simplemente agregando filas sin el id a ver qué pasaba.

Por alguna razón insensata de mi parte, supuse que los registros empezaban de 0, y cuando hacía querys para ver mi información pues me tiraba errores, sin embargo la consola marcaba que era la tabla la que no existía y no el registro, así que me pasé algunas horas peleando con por qué no aparecía la tabla si yo la creaba como debía.

Para no hacer el cuento largo, android usa bases de datos sqlite, por lo que para hacer pruebas me bajé el sqlite3 de acá.

http://sqlite.org/2015/sqlite-shell-win32-x86-3081002.zip

En esta aplicación basta con utilizar el comando .schema para ver la sentencia SQL con la que se han creado las tablas de nuestra base, sin embargo, si intentan hacer este query desde android, les va a dar error, el query respectivo para lograr esto es:

  1. String queryschema = "SELECT sql FROM (SELECT * FROM sqlite_master UNION ALL SELECT * FROM sqlite_temp_master) WHERE type!='meta' ORDER BY tbl_name, type DESC, name";
  2. Cursor cursor = db.rawQuery(queryschema , null);




Con este query simplemente tendrán que utilizar el método de rawquery y listo, tendrán la estructura de las tablas de su BD.

Hay que recordar que la trabla de sqlite_master contiene toda la información de nuestra BD, por lo que podemos obtener otro tipo de información aparte de las tablas.

Saludos.

Primeros pasos con Android

Atemorizado, pero a la vez emocionado en mi nuevo viaje a los confines de Android, me decidí a bajar un IDE en el cual trabajar, sabía que eclipse era una buena opción, estoy acostumbrado a utilizarlo y ya tengo muchos plugins muy útiles, sin embargo, pensé, a estas alturas debería hacer un IDE especial para Android, ¿no? Y así fue como fui a dar con Android Studio.

Como saben, yo utilizo windows la mayoría del tiempo por mis jueguitos, así que me bajé esa versión.

Pueden descargarla de acá:

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

Una vez que bajé el IDE, me propuse a explorar qué opciones conocidas tenía, ya saben, cómo es la estructura, cuáles son los comandos rápidos básicos, etc.

Acto seguido de esto, dije, y bueno, ¿ahora cómo empiezo? Buscar videos... Blogs conocidos... entre otros... A lo que encontré una página excelente para comenzar, esta se llama Udacity, yo no la conocía quizás ustedes sí, el chiste es que tiene muchos cursos gratis (aunque hay que registrarse... a algunos no les gustará, pero bueno) y encontré un cursillo de introducción el cual me dio las herramientas para comenzar. El curso en cuestión es este:

https://www.udacity.com/course/developing-android-apps--ud853

Y para no tener problemas con el control de versiones y atiborrar mi carpeta de proyectos de "Este si es el bueno" "Este es el final" "Este es mejorado" etc... también me decidí a tomar el cursito de GitHub.

https://www.udacity.com/course/how-to-use-git-and-github--ud775

Todos los cursos están en inglés y los videos a veces tienen subtítulos en español, a veces no... Pero siempre puedes ponerle los subs en inglés, aunque sean autogenerados, por aquellos como yo que estén sordos y no se les de bien escuchar el inglés jejeje.

Y bueno, de momento creo que es suficiente para que vayan adentrándose en el mundillo este de Android. Así que los veo en otra publicación. Saludos.

Comenzando con un desarrollo en Android

Hace unos días estaba desayunando con mi hermano, y me comentó ciertos problemas que tenía en la empresa en la que trabaja, a lo que me dijo, pues... ¿Tú programas no? ¿No me puedes ayudar con unos programitas o algo? A lo que contesté que a pesar de que ya tengo tiempo de programar "en serio" iba a tomar la propuesta y desarrollar alguna solución para dispositivos Android, él tiene un Iphone, y de hecho casi todos los de la compañía igual... Pero bueno, me encanta llevarle la contraria así que le dije que Android o nada... Jajaja, ya luego buscaré el desarrollo con algún framework que exporte en diversas plataformas, pero de momento, quiero programar "como se debe" y explorar desde sus raíces a Android.

Así pues, empezaré a publicar algunos problemas, consejos y tips que se me vayan cruzando en el camino del desarrollo de las aplicaciones que pretendo realizar.

Saludos, ¡nos vemos en otra publicación!

lunes, 29 de diciembre de 2014

Guía de estudio de Instalación, Configuración y Comunicación de Sistemas Operativos

Hola amigos, les traigo una guía que utilicé para el examen de ICCSO, espero que a alguien más le pueda servir. Saludos!

https://sites.google.com/site/jassfiuaemex/home/iccso/Acordeon%20Final%20ICCSO.docx?attredirects=0&d=1

Les sugiero que hagan otro archivo con las mismas preguntas, le borren las respuestas y lo guarden, y cada que quieran estudiar, lo rellenan y nada más no guardan el archivo, así le hice yo :D

lunes, 16 de diciembre de 2013

Guía de estudio de Diseño de Sistemas

A todos nos ha pasado que tenemos razones de peso para no poder estudiar para los exámenes parciales, ya sea que tenemos demasiadas materias, que estamos enfermos o que se acerca el final de la tercera temporada de League of Legends y es imperiosamente necesario subir a oro para recibir las recompensas.

Más común entonces es que los profes, tan mala onda y sin tomar en cuenta nuestras vidas tan ocupadas y poco felices, toman la imperdonable decisión de mandarnos a extraordinario sin siquiera tener la oportunidad de presentar examenes ordinarios.

Es así que su servidor, debido a todas las razones anteriores tuvo la necesidad de apoyar a las víctimas de Diseño de sistemas, realizando una guía que a mi parecer está bastante completa y cubre en su mayoría las preguntas de los exámenes tanto parciales como ordinarios, extraordinarios y títulos de suficiencia.

Para no extenderme más, les dejo el link de descarga, es un word con extensión docx. Si lo requieren en PDF, conviértanlo y enviénme el archivo y con gusto lo subo al rincón de los archivos perdidos de la facultad de ingeniería.

Guía de diseño de sistemas

sábado, 7 de diciembre de 2013

Tareas de administración de recursos informáticos.

Ya que la de administración de recursos informáticos me puso peros hasta el final, y atiborrándome de trabajos sólo porque me aburría en su clase, aquí dejo todas las tareas que dejó en el semestre, esperando le sirvan a más de uno.

También incluyo cuestionarios para los exámenes ;D
Saludos a todos :P

martes, 12 de marzo de 2013

Comenzamos a liberar código fuente

Bueno, como el público lo pidió, estaré subiendo código fuente de los proyectos, no está bien documentado pero espero que con el tiempo pueda tener aunque sea el código comentado.

Sin más preámbulos les dejo el sitio donde estaré subiendo los archivos:

https://sites.google.com/site/jassfiuaemex/

Ahí encontrarán el apartado que dice clases variadas.

domingo, 3 de marzo de 2013

Guía Instalación JFlex en eclipse.

Pues siguiendo con la línea de tutoriales, hoy le toca a JFlex.
Que es lo mismo que Flex pero para java, porque a mí no me gusta C.

Todos deben saber para qué sirve, creo yo...

Primero, descargamos la última versión disponible, a la fecha de publicación es la 1.4.3.

http://jflex.de/jflex-1.4.3.zip

Dentro del programa tiene instrucciones de instalación, pero como nunca les entendí, así que les enseñaré a integrarlo a eclipse.

En eclipse, creamos un proyecto nuevo, luego seleccionamos java project y le ponen el nombre que quieran, yo le puse JFlex

Ahora le dan clic a la carpeta del proyecto para que les salga la carpeta de src, ahí le dan clic derecho, luego new y luego File.

A ese archivo le ponen el nombre que quieran pero tiene que terminar con flex, yo le puse Lexer.flex, pueden dejarlo vacío, este archivo será la especificación léxica con la que trabajará nuestro JFlex..

Ahora crearán otro archivo, pero este se llamará entrada.txt, o lo que quieran ponerle de nombre, a diferencia del Lexer.flex que pusimos en src, el archivo entrada.txt lo haremos en la carpeta principal, es decir, ahora daremos clic derecho en JFlex en vez de en src.

El nuevo archivo debe aparecer debajo de JRE System Library.

Ahora tienen que irse al menú de eclipse, donde dice RUN, luego External Tools, y luego External Tools Configuration.

Seleccionan donde dice Program, luego le dan click derecho y le dan NEW

En nombre le dan el nombre que quieran, yo le puse JFlex.

En location, vamos a poner la ruta hasta el archivo de java.exe, denle browse file system, y luego ya saben, nuestra querida carpeta del JDK, luego a bin y ahí lo buscan.

En working directory le ponen browse Workspace, luego le dan a JFlex [así se llama mi proyecto] luego a src y aceptar, tiene que salir algo como esto: ${workspace_loc:/JFlex/src} [o si quieren copien y peguen y nomás le cambian JFlex por como le pusieron ustedes.

En los argumentos le ponen:
-cp C:\Users\Jass\Documents\Escuela\Compiladores\jflex-1.4.3\lib\JFlex.jar JFlex.Main -nobak Lexer.flex

Sustituyendo obviamente su carpeta para que coincida a donde descomprimieron el zip que bajaron al principio.

Ahora vayan a la pestaña de Refresh y seleccionen la opción de  "Refresh resources upon completion"
Y seleccionan The entire Workspace.
También pongan palomita en Recursively include subfolders.

Y listo, denle Apply y cierren la ventana, si le dan run va a tirar error porque nuestro archivo no tiene nada.

Ahora vamos a probar que funcione.
Rellenen el archivo con lo siguiente...


/*Aquí van los import*/
%%
%standalone
DIGITOS = [0-9]
/*Aquí van las especificaciones de Tokens*/
%%
/*Aquí van las acciones al encontrar tokens*/
{DIGITOS} {System.out.println("Digito");}

Denle a donde está el botoncito de compilar, pero el que tiene una cajita de herramientas de color rojo, es el de la derecha, ahí tiene una flechita, denle y debe salir JFlex.

Si hicieron todo bien, debería generarse una clase llamada Yylex.java en su default package.

Ahora, váyanse a la pestaña Run de eclipse de nuevo, pero esta vez seleccionaremos la opción de Run Configurations,  sale una ventana, denle donde dice Java Application y busquen la clase YyLex y selecciónenla, ahora a la derecha hay pestañas, váyanse donde dice Arguments y en el cuadro pónganle entrada.txt y denle Apply, ahora sí, denle RUN.

Si no tira errores, ya está bien configurado.

De ahora en adelante simplemente editaremos el archivo de entrada.txt o el de Lexer.flex, dentro del mismo eclipse te permite hacerlo.

Para probarlo, editen el archivo de entrada.txt y póngale números y espacios y cosas...

Ya que lo editan, le dan al botón de compilar [el rojito] y luego a compilar el normal, y les debería aparecer "Digito" "Digito" y así, si le pusieron otras cosas al archivo, se imprimirán tal cual ya que lo que JFlex no reconoce, lo imprime en pantalla. 



Yo sé que al manual le faltan imágenes y cosas así...

Yo saqué esta información de este enlace:
http://www.lsi.us.es/docencia/get.php?id=5840

Así que dense una vuelta, usan una versión diferente de eclipse, pero no deberia ser problema ajustar las cosas con lo que expliqué anteriormente.
¡Saludos!

martes, 25 de diciembre de 2012

JMagick

Hola amigos, como he visto que existen un poco de problemas a la hora de instalar y usar ImageMagick para java, vamos a ver una sencilla guía para instalarlo en eclipse.

Lo primero que tenemos que hacer es bajar los DLL de ImageMagick, recordemos que en un principio está diseñado para tratamiento de imágenes en C, y lo único que lograremos con JMagick es poder usar ciertas funciones de esas librerías, en lenguaje Java.

¿Por qué usar JMagick? Porque el formato que puede leer ImageMagick en imágenes es muy basto, sirve para PNG, JPG, incluso PGM, todo lo pasa a una matriz de píxeles con el espacio de color RGB, en caso de que sean blanco y negro, los 3 canales tienen la misma intensidad.

Lo que tenemos que descargar es lo siguiente:


El paquete de DLL's
http://downloads.jmagick.org/6.3.9/ImageMagick-6.3.9-0-Q16-windows-dll.exe

La interfaz de JMagick
http://downloads.jmagick.org/6.3.9/jmagick-win-6.3.9-Q16.zip

Ojo que tienen que checar que la versión de DLL corresponda con la versión de JMagick, la última que encontré fue la 6.3.9

Ahora, en eclipse, simplemente tenemos que agregar en el build path el jar que viene de JMagick.

Esto es:
En el proyecto actual, click derecho y luego propiedades.
Cliqueamos en Java Build Path y damos add external JAR.
Buscamos el jar que bajamos de Jmagick, de preferencia pongan el jar en el classpath de su JDK.

El mío es por ejemplo:

C:\Program Files (x86)\Java\jre7\lib

Ahí adentro aventamos el archivo de jmagick.jar

Ahora, el DLL jmagick.dll del comprimido se manda a la carpeta de binarios, en mi caso:

C:\Program Files (x86)\Java\jre7\bin

Ahora, después de agregarlo en el proyecto, le vamos a picar, a la flechita que saldrá de despliegue, teniendo seleccionado el jmagick.jar en la misma ventana de propiedades sale una barrita que dice Native Libraries Location, en esa damos doble clic y donde está el boton external folder, vamos a buscar donde descomprimimos el contenido de los DLL de ImageMagick, en mi caso lo aventé en C:/Windows/System32/ para que no haya broncas.

Finalmente damos aceptar.

Listo ya tenemos funcionando el JMagick.
Pronto les dejaré una pequeña clase que transforma una imagen leída de imagemagick a un bufferedImage de java para que lo puedan usar en etiquetas o lo que les dé en gana.

miércoles, 19 de diciembre de 2012

Continuación de la Quinta Fase...

Continuamos otra vez con el proyecto del ensamblador después de jugar un poco con el Jmagick...

Pues bien, para la quinta fase requerimos saber las direcciones de memoria de las variables, así como de las instrucciones de código, calcular desplazamientos, etc.

Nos valdremos de la clase TablaSimbolos y de su método getPropiedad para obtener estos datos.

Para calcular los desplazamientos requerimos saber el tamaño de variable, es decir DB o DW y los elementos declarados, para las cadenas se multiplica la longitud de la cadena [sin contar las comillas dobles o simples que pudiera tener].

Agregado a esto, tenemos la nueva restricción de validar las etiquetas, que deberán ser definidas antes de ser usadas, esto con el objetivo de agregarlas a la tabla de símbolos.

Así pues, la tabla contendrá un nuevo tipo de dato que será "etiqueta".

Quedando los tipos como "constante" "variable" y "etiqueta".

Además, aumentamos que se puede especificar una cantidad para dup en hexadecimal, binario o decimal.

Todas estas modificaciones aumentan la complejidad del analizador de instrucciones, ya que ahora no sólo necesitaremos saber si la instrucción es correcta, sino qué tipo de instrucción se analizó y varios datos que son de interés.

Crearemos una nueva clase llamada Instruccion, que contendrá métodos para:
Saber si es válida o inválida.
actualizar estado en caso de requerir buscar una variable o etiqueta.
Obtener el tamaño de sus  elementos.
Obtener los elementos.
Obtener el elemento en espera.

Esto no es más que un modelo para las instrucciones y sus elementos son seteados por el controlador cuando no han podido ser seteados en el constructor, como es el caso de tener que buscar una variable o una etiqueta en la tabla de símbolos.

Sólo resta realizar la sexta y última fase que consiste en codificar las instrucciones...

viernes, 7 de diciembre de 2012

Cuarta y quinta fase

Pues como ya no he escrito avances, este será uno corto que tratará de explicar cómo hemos ido avanzando.

Pues bien, hasta ahora tengo una clase que se llama Separador simple que no hace más que separar líneas en un vector de elementos.

Ya que tenemos elementos separados, los podemos pasar por la clase Identificador, esta clase tiene métodos para identificar si un string dado es un registro, símbolo, etiqueta, etc...

Otra de las clases es TamanoDato, la cual se encarga de decir si un string tiene un tamaño DB o DW, los strings pueden incluir cadenas de texto debidamente formateadas, enteros, caracteres, etc.

Por otro lado, tenemos una clase llamada tabla de símbolos, la cual se encarga de guardar todas las variables que estén debidamente codificadas, obviamente ya han sido comprobadas por el identificador en orden y sintaxis. Esta clase, tiene métodos para acceder a los atributos de cada una de las variables, y además es capaz de generar un vector de vectores, simulando una matriz.

Esto es:

Vector.get(0) nos devolverá un vector con los atributos de la primera variable.

Para obtener por ejemplo del nombre de la tercera variable tendríamos...

VectorSimbolos().get(2).get(0);

Y así... todo esto está oculto en el método getPropiedad, el cual funciona enviándole un nombre de variable en lugar de un index, porque es más cómodo decir "dame el tamaño de la variable pancho" que decir, dame el tamaño de la variable 4...

En base a la clase de TablaSimbolos tenemos a la VentanaTablaSimbolos, que no es nada más que la vista del modelo contenido en la clase TablaSimbolos, la ventana simplemente recibe un vector de vectores creado a través del método  crearVectorSimbolos() de tablaSimbolos.

Esto es debido al uso de DefaultTableModel que requiere vectores de filas para trabajar.

Finalmente tenemos el comprobador de instrucciones del cual hablamos en la publicación pasada, que simplemente le pregunta a las demás clases si los elementos recibidos son correctos.
Algunas comprobaciones que hace son con elementos de etiquetas, registros, variables en memoria y su tamaño, y además constantes numéricas.

Pues bien, creo que va quedando bastante bien el ensamblador, al final del semestre subiré todo el código fuente para que puedan entender mejor las ideas que quedan volando.

sábado, 1 de diciembre de 2012

Tercera fase del ensamblador

En la tercera fase tenemos que analizar el segmento de datos.
Las especificaciones son las siguientes:


La Fase 3 del proyecto cubre la fase del análisis sintáctico y semántico de los segmentos de datos y pila, es decir, analizar los elementos que integran las líneas del programa fuente que se encuentran en las definiciones de los segmentos de datos y pila para verificar que son los correctos y que están en el orden correcto, conforme a la siguiente sintaxis.

data segment (pseudoinstrucción que identifica el inicio de la definición del segmento de datos)
símbolo db constante caracter
símbolo db constante numérica byte
símbolo db constante numérica dup (constante caracter byte)
símbolo db constante numérica dup (constante numérica byte)
símbolo dw constante numérica palabra
símbolo dw constante numérica palabra dup(constante numérica palabra)
símbolo equ constante numérica palabra
ends (pseudoinstrucción que identifica el fin de la definición de un segmento)

stack segment (pseudoinstrucción que identifica el inicio de la definición del segmento de pila)
dw constante numérica palabra dup(constante numérica palabra)
ends (pseudoinstrucción que identifica el fin de la definición de un segmento)

Esta fase del proyecto debe cubrir la característica de desplegar la línea del programa fuente analizada y frente a ella el resultado de la verificación con la frase Correcta o Incorrecta, según sea el caso.

En esta fase del proyecto se debe comenzar a llenar la tabla de símbolos (considerar el llenado de los cambos símbolo, tipo, valor y tamaño).

Esta fase es relativamente fácil...

Lo único que tenemos que hacer es:

Leer cada una de las líneas del archivo.
Analizar la secuencia arriba mostrada, y determinar si es correcta o incorrecta.

En un principio parecía que las fases no iban a servir demasiado... Pero no es así, bien podemos darle uso.

¿Recuerdan el Separador Simple y nuestro mapa de Strings? Pues simplemente vamos a utilizar los elementos que regrese la función del separador [en mi caso un vector de Strings] y compararlos con el mapa de strings.

Vamos a plantear una bandera que determine cuándo es que se abre y cuándo se cierra un segmento dado, ya sabemos que no puede haber más de 1 definición de cada uno así que podemos controlarla con un simple entero.

0 es que no ha habido ninguna definición, 1 que ya se inicio el segmento de datos, 2 que ya se cerró, 3 que inicio segmento de pila, 4 que se cerró, 5 que inició segmento de código y 6 que se cerró.

Esto corresponde al ciclo del data segment....

En pseudocódigo...

Si línea leída es "data segment"
    estado=1
Si no
    seguir leyendo líneas.

Si estado=1 y lineaLeida != vacío.
    si primer elemento es símbolo.
        si segundo elemento es db
            si tercer elemento es un número entero o una serie de caracteres...
                imprime linea es correcta.
                si es un entero y después existe un dup(...)
                    si el dup está bien formulado.
                        escribe linea es correcta
                    si no
                        imprime linea es incorrecta
            si no
                imprime linea es incorrecta
        si es dw
            si la definicion del elemento es correcta
                imprime linea es correcta.
            si no
                imprime linea es incorrecta.
        otro
            imprime linea es incorrecta

Verificar si es db implica comprobar tanto que el número de veces que se desea duplicar un elemento es válido, como los elementos que se desean duplicar.

    VAR5 db 5 dup('(')
Es correcta

    VAR5 db a dup('(')
Es incorrecta

Bien, el diseño de esto es simple, vamos a crear una clase que reciba un elemento y nos devuelva su tamaño...

Es decir, si enviamos "Ya voy amigos!" nos devuelva DB, y si le enviamos 50000 nos devuelva DW...
Con esto podemos comprobar dos cosas, la primera es que cuando queramos hacer un DUP se verifique que el tamaño del interior corresponda a la definición de la variable, y además, que podamos usarla con los operadores que nos asignarán en las siguientes fases del proyecto.

Nos podemos ayudar de los comprobadores de tamaño hexadecimal y decimal, ya que el ejemplo que puse antes era con signo o sin signo, podemos cambiar ese parámetro a 1 para db o 2 para dw... dependiendo cómo definimos nuestras variables estáticas en la clase del identificador, y saber si corresponde al tamaño.

jueves, 22 de noviembre de 2012

Fase 2... Análisis léxico del ensamblador

Pues bien, después de un largo rato de no hacer nada más que jugar League of Legends, decidí empezar con la fase 2 del proyecto que consiste en:

Identificar todos y cada uno de los elementos del programa fuente como elementos validos del lenguaje (pseudoinstrucción, instrucción, registro, símbolo, constante [numérica decimal, numérica hexadecimal, numérica binaria, caracter]). Esta fase del proyecto debe cubrir la característica de desplegar frente a cada elemento de la lista resultado de la fase 1, el tipo de elemento de que se trate. De no identificar a un elemento como válido, se debe desplegar e mensaje "Elemento no identificado" o "Elemento invalido".

Los subconjuntos de doce instrucciones a identificar por cada equipo son los siguientes. Recuerden que es restricción del proyecto el que únicamente identifiquen las instrucciones asignadas y se tomará como símbolos las instrucciones no asignadas.


EquipoInstrucciones a identificar
1AAALAHFPOPFSTOSBINTPUSHCMPTESTJAEJLJOLOOPZ
2AADCMPSBPUSHASTOSWLDSDECMOVXCHGJBJLEJNGJA
3AAMCMPSWLAHFXLATBLEADIVORXORJBEJMPJNGEJP
4AASCWDLODSBPUSHFLESIDIVRCLADCJCJNAJNLJS
5CBWDAALODSWRETDECIMULRORADDJCXZJNAEJNLEJZ
6CLCDASMOVSBSCASWDIVMULSARANDJEJNBJNOLOOP
7CLDHLTMOVSWSTCIDIVNEGADCCMPJGJNBEJNPLOOPE
8CLIINTONOPSTDIMULNOTADDSHLJGEJNCJNSLOOPNE
9CMCIRETPOPASTIINCPOPANDSUBJAJNEJNZLOOPNZ



Pues bien, vamos a suponer que somos el equipo 7, porque dicen que el 7 trae buena suerte.

Esta fase no es nada complicada y sólo tenemos que analizar el elemento que nos ha devuelto la fase 1.

Para esta fase, podemos hacer un HashMap de strings.
Esta clase de java nos permite manejar conjuntos de objetos como si fuera un vector, pero en lugar de índices numéricos, podemos usar palabras.

La idea es hacer una lista como por ejemplo:

CLD:INSTRUCCIÓN
HLT:INSTRUCCIÓN
MOVSW:INSTRUCCIÓN
AX:REGISTRO
BX:REGISTRO
...

Y así, por lo que cuando busquemos por una instrucción válida, nos regresará el string instrucción o registro según corresponda.

Si el mapa no devuelve ninguna de estas cosas, aplicaremos la expresión regular para los símbolos...


if(linea.matches("[a-zA-Z][\\w]*")){


Algo así... donde tamano es el tamaño que queremos aceptar como máximo para nuestros símbolos, no es posible poner variables en las expresiones regulares, por lo tanto o lo hardcodean, o hacen un if con un length del string y una variable int estática...


HashMap<String, Integer> tipoElementos = new HashMap<String, Integer>();
tipoElementos.put("CLD",Identificador.INSTRUCCION);

tipoElementos.put("AX",Identificador.REGISTRO);

Así quedaría el mapa, obviamente con más elementos...


Finalmente reconocer las constantes numéricas y demás, es sencillo, dejo uno para identificar números hexadecimales con o sin signo acá...


private static boolean isHex(String elemento, boolean signo) {
elemento=elemento.replace("h", "");
elemento=elemento.replace("H", "");

try{
if(signo==true){
if( (Integer.parseInt(elemento,16) > -129) && (Integer.parseInt(elemento,16)<128) ){
return true;
}
}
else{
if( (Integer.parseInt(elemento,16) > -1) && (Integer.parseInt(elemento,16)<256) ){
return true;
}
}
}
catch(Exception e){
return false;
}
return false;
}