Mostrando entradas con la etiqueta ejemplo. Mostrar todas las entradas
Mostrando entradas con la etiqueta ejemplo. Mostrar todas las entradas

miércoles, 28 de agosto de 2013

Mi propio navegador web en Android

En uno de los artículos anteriores hicimos un navegador web con Python y PySide, así que en esta entrada vamos a hacer algo parecido con Android.

Primero lo primero, un nuevo  proyecto
Creamos un nuevo proyecto de Android, éste debe tener una actividad principal sobre la cual trabajaremos, en este caso el nombre de la actividad es Inicio.

Ahora, el diseño
En la carpeta layout abrimos el layout asociado a la actividad principal, en este caso su nombre es activity_inicio.xml

El layout debe tener un EditText para la url de  destino, y un WebView así:

Además de esto es necesario editar el archivo XML del menú, para poner los botones atrás y adelante.

Y final mente el código en Java:
public class Inicio extends Activity {

    ProgressDialog progressBar;
    private int progressBarStatus = 0;
    private Handler progressBarHandler = new Handler();
    EditText txtUrl = null;

    public final String HOME = "http://notoquesmicodigo.blogspot.com/";

    private class MiWebViewClient extends WebViewClient {

        private void iniciaCarga(WebView v) {
            if(progressBar==null){
                progressBar = new ProgressDialog(v.getContext());
            }
            if (progressBar != null && !progressBar.isShowing()) {
                progressBar.setTitle("Espere...");
                progressBar.setMessage("Cargando página...");
                progressBar.setProgressStyle(ProgressDialog.STYLE_SPINNER);
                progressBar.setCancelable(false);
                pbShow();
                progressBarStatus = 0;
                runOnUiThread(new Runnable() {

                    @Override
                    public void run() {
                    progressBarHandler.post(new Runnable() {
                    public void run() {
                        try {
                             progressBar
                              .setProgress(progressBarStatus++);
                        } catch (Exception e) {
                        }
                      }
                     });
                    }
                });
            }
        }

        private void pbCancel() {
            try {
                progressBar.cancel();
            } catch (Exception e) {
                Log.e("ERROR", e.getMessage());
            }
        }

        private void pbShow() {
            try {
                progressBar.show();
            } catch (Exception e) {
                Log.e("ERROR", e.getMessage());
            }
        }

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            iniciaCarga(view);
            if (txtUrl != null) {
                txtUrl.setText(url);
            }
            super.onPageStarted(view, url, favicon);
        }

        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
            pbCancel();
        }
    }

    private class MiChromeWebViewClient extends WebChromeClient {

    }

    WebView wv_pagina;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_inicio);
        wv_pagina = (WebView) findViewById(R.id.wv_pagina);
        txtUrl = (EditText) findViewById(R.id.txtUrl);
        wv_pagina.clearHistory();
        wv_pagina.clearCache(true);
        wv_pagina.setWebViewClient(new MiWebViewClient());
        wv_pagina.setWebChromeClient(new MiChromeWebViewClient());
        wv_pagina.getSettings().setJavaScriptEnabled(true);
        runOnUiThread(new Runnable() {

            @Override
            public void run() {
                wv_pagina.loadUrl(HOME);
            }
        });

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_inicio, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (wv_pagina != null) {
            switch (item.getItemId()) {
            case R.id.menu_back:
                if (wv_pagina.canGoBack()) {
                    wv_pagina.goBack();
                }
                break;
            case R.id.menu_forward:
                if (wv_pagina.canGoForward()) {
                    wv_pagina.goForward();
                }
                break;
            }
            return true;
        } else {
            return super.onOptionsItemSelected(item);
        }
    }

}

Ahora bien, debemos tener en cuenta varias cosas:

  • Para que nuestro navegador no lance otro de los navegadores del celular (como Chrome por ejemplo) debemos crear clases propias que hereden de WebViewClient y WebChromeClient.
  • La mayor parte del código esta en la clase MiWebViewClient para el ProgressDialog que usamos.
  • En la clase MiWebViewClient sobrecargamos los métodos onPageStarted y onPageFinished para poder lanzar el ProgressDialog y cambiar la URL en la caja de texto de la dirección.
  • En el evento onOptionsItemSelected ponemos los eventos de atrás y adelante filtrando los elementos menu_back y menu_forward.
El resultado es éste:


El código esta disponible en GitHub, si tiene alguna duda pueden preguntar en los comentarios.

jueves, 1 de agosto de 2013

Entendiendo Javascript (VI)


Hasta el momento todo lo abarcado en los artículos ha permitido entender un poco mejor muchos de los pormenores de este interesante pero complejo lenguaje, pero muy poco se ha hecho por entender cómo modificar lo que el usuario utiliza, qué es en esencia lo que más necesita un usuario JavaScript, por esto en esta entrega vamos a empezar con la exploración de el objeto donde se almacena el contenido de la página, el objeto document.

Peleando con el documento
Ya habíamos hablado acerca de que en el momento en el que el navegador carga una página web toma todo el contenido HTML y lo convierte en objetos, estos objetos en realidad son nodos "manipulables", que a su vez contienen otros nodos. A esto se le llama document. Es muy importante resaltar que todo lo que hay en el document es un nodo, a continuación vamos a ver un ejemplo de esto.
<html>
    <head>
        <title>El Documento...</title>
    </head>
    <body>
        <h1>El Documento</h1>
        <div>Este es un ejemplo...</div>
    </body>
</html>

Si hiciéramos un esquema a manera de árbol de cómo se ve este HTML tendríamos:
De esta manera vemos como el nodo html es el padre inmediato de head y body, head es el padre de title y title tiene una propiedad llamada text, cuyo valor es "El documento...". body es el padre de h1 y div, los cuales a su vez tienen cada uno como propiedad text "El Documento" y "Ejemplo de documento..." respectivamente.

Muy bonito pero...
¿Para qué nos sirve entender esto?, la idea de entender esto es poder desplazarnos por el árbol sin depender únicamente de los identificadores, las etiquetas o los nombres.

Esta bien, y ¿Cómo me desplazo?
Esa es la parte divertida, porque para desplazarnos el objeto document nos ofrece unas herramientas, a continuación vamos a ver algunas de estas:
Orden Descripción
document.getElementById(valor) Retorna el elemento que en el atributo id tenga el valor especificado.
document.getElementsByName(nombre) Retorna una lista de todos los elementos que tengan el nombre especificado.
document.getElementsByTagName(tag) Retorna una lista de todos los elementos hechos con con el tag especificado

Y Para Terminar...
Vamos a hacer un ejemplo de una función que busca el título de nuestra página y lo cambia, otra que cambia el contenido de un div y su color de fondo y cada una va a ser asociada a un botón. Después del código esta el ejemplo.

<html>
    <head>
        <title>El Documento...</title>
        <script>
             function cambiarTituloPor(nuevoTitulo){
                document.getElementsByTagName("title")[0].innerHTML=nuevoTitulo;
             }
             function cambiarContenidoPor(nuevoContenido){
                var elemento = document.getElementById("modificable");
                elemento.innerHTML=nuevoContenido;
                var estilo = document.createAttribute("style");
                estilo.value = "background-color:#1662A8;";
                elemento.setAttributeNode(estilo);
             }
        </script>
    </head>
    <body>
        <h1>El Documento</h1>
        <div id="modificable">Este es un ejemplo...</div>
        <button onclick="cambiarTituloPor(prompt('Nuevo Título','Hola Mundo!!!'))">Cambiar Título</button>
        <button onclick="cambiarContenidoPor(prompt('Nuevo Contenido','Estoy aprendiendo JavaScript...'))">Cambiar Div</button>
    </body>
</html>

Este es un ejemplo...

lunes, 29 de julio de 2013

Entendiendo Javascript (V)


En el post anterior se intentó dar un vistazo general a el entorno de trabajo en JavaScript dentro de un navegador, mostrando cuáles eran sus propiedades principales, teniendo en cuenta que al iniciar la aplicación el entorno de trabajo está compuesto por todo lo que compone un objeto window, pero no sabemos mucho acerca de qué métodos o funciones podemos usar. A continuación veremos un poco de esto.
Recordemos, los procedimientos mostrados a continuación son métodos del objeto ventana y pueden ser invocados de manera directa puesto que el contexto de inicio de los scripts que se ejecutan en el navegador es la ventana misma.

  • alert(mensaje): Es uno de los procedimientos más usados, éste despliega un diálogo con un mensaje específico
  • close(): Cierra la ventana
  • confirm(mensaje): Lanza un diálogo de confirmación y dependiendo de la respuesta retorna true o false
  • open(url, nombre, parámetros, reemplazar):  Crea una nueva ventana en la cual carga la url, con el nombre y los parámetros especificados, y dependiendo del último valor la url especificada reemplazará la url de la ventana actual.
  • print(): Imprime el contenido de la página actual.
  • prompt(mensaje, valor): Crea un diálogo con una caja de texto, el diálogo tiene un mensaje especificado en el primer parámetro y como valor inicial el valor (valga la redundancia) especificado en el segundo parámetro.
  • setInterval(funcion_o_expr, milisecs): Llama a una función o evalúa una expresión cada cierto intervalo de milisegundos. se detiene cuando la función clearInterval(id) es llamada. Ésta retorna un identificador.
  • clearInterval(id): Detiene la ejecución periódica de la acción creada con setInterval a la que está asociada el id entregado.
  • setTimeout(): Llama a una función o evalúa una expresión después de un intervalo de tiempo especificado en milisegundos. Ésta retorna un identificador y es detenida por la función clearTimeout(id).
  • clearTimeout(id): Detiene la ejecución de la acción lanzada por setTimeout asociada al id entregado.
Muy bien, todo esto es muy bonito, pero, ¿Para qué podría usar todo esto?. A continuación vamos a hacer un pequeño ejemplo en el cual vamos a usar solo un par de los procedimientos que fueron descritos anteriormente. Vamos a hacer un cronómetro.

A continuación está el código HTML:

<html>
  <head>
    <title>Mi Cronometro</title>
    <style>
      #reloj {
        font-size:4em;
      }
    </style>
    <script src="crono.js"></script>
  </head> 
  <body>
    <script>
        var cronometro = new Cronometro();
    </script>
    <button onclick="cronometro.iniciar()">Inicio</button>
    <button onclick="cronometro.detener()">Detener</button>
    <button onclick="cronometro.reiniciar()">Reiniciar</button>
    

    <div id="reloj">
      0:0
    </div>
</body>
</html>

Y el código JavaScript:
function Cronometro(lugarCarga){
  var self = this;
  self.interval = 0;
  this.upd = function(){
    var secs = self.interval/100;
    var milis = self.interval%100;
    self.lugarCarga.innerHTML = Math.floor(secs)+":"+milis;
  }
  this.paso = function(){
    self.interval = self.interval + 1;
    self.upd();
  }
  this.iniciar = function(){
    self.lugarCarga = document.getElementById('reloj');
    self.id_intervalo = setInterval(self.paso,10);
  };
  this.detener = function(){
    clearInterval(self.id_intervalo);
  };
  this.reiniciar = function(){
    self.interval = 0;
    self.lugarCarga.innerHTML = "0:0";
  };
}


Pueden encontrar los códigos de ejemplo en GitHub.

jueves, 25 de julio de 2013

Consoleando (II)

Después de aprender lo básico es hora de aprender cosas más interesantes, scripts.

¿Qué es un Script?
Un script es un archivo que contiene una secuencia de órdenes que facilitan alguna labor (es un programa).

Ejemplo de un Script
A continuación veremos cómo se hace un script básico, saludo.sh . La labor de éste script es escribir "buenos dias", "buenas tardes" o "buenas noches", lo anterior dependiendo de la hora.
Entonces:

#!/bin/bash
# la linea anterior se pone para que el sistema operativo
# sepa con que interprete debe ejecutar el script

### programa: saludo.sh
let HORA=`date +%H` # capturamos la hora del dia
if [ $HORA -ge 4 ] && [ $HORA -lt 12 ]; then
    echo 'Buenos Dias!!!'
fi
if [ $HORA -ge 12 ] && [ $HORA -lt 18 ]; then
    echo 'Buenas Tardes!!!'
else
    echo 'Buenas Noches!!!'
fi
### fin programa

En este bloque de código podemos ver muchas de las interesantes cosas que tiene el lenguaje bash, uno de los lenguajes usados en las consolas Linux, éste es simple y potente, además nos permite usar comandos del sistema como date, crear variables mediante la orden let, extraer información de los comandos del sistema (una de las formas de hacer esto es mediante las comillas invertidas [ ], las cuales interpretan el comando que esté dentro de las comillas y retornan esa cadena convertida en valor, lo cual puede ser almacenado o usado en nuestro programa), usar condicionales ( if, else, case), operadores lógicos ( && y | | ), escribir cadenas mediante la orden echo y muchas más cosas.
Algo que en principio es extraño para quienes hacen scripts es que no entienden qué es -lt o -ge, estos son los operadores de comparación, a continuación los veremos en una tabla con sus significados:

comandosignificado
-lt menor que
-le menor o igual que
-eq igual que
-ge mayor o igual que
-gt mayor que
-ne diferente a


Y, ¿Qué hacer con ese código?
Este código se guarda en un archivo de texto, por ejemplo saludo.sh (uso la extensión sh porque es un archivo del lenguaje bash, que es a su vez una mejora de sh), y luego en la consola hago que éste se pueda ejecutar mediante la orden chmod así:
chmod +x saludo.sh

Y, ¿Cómo lo ejecuto?
Para ejecutarlo escribimos en la consola la ruta completa del archivo si estamos en una carpeta diferente a la del archivo, si estamos en la misma carpeta  anteponemos un punto, así:
# si no estamos en la misma carpeta
/home/andres/saludo.sh
# y si estamos en la misma carpeta
./saludo.sh