lunes, 29 de mayo de 2017

Apache cordova. Primeros pasos

¿Qué es?

Se trata de un framework que nos va a permitir crear aplicaciones para distintas plataformas a través de tecnologías web (html, css, javascript...)

Instalación en Windows

¿Qué necesitamos para instalar Apache Cordova? Inicialmente nos basta con tener instalado Node.js, sin embargo hay otros elementos que nos harán falta a posteriori.
  1. JDK de java. Si no la tienes previamente instalada puedes descargarla aquí.
  2. Node.js. Node.js se trata de in interprete de javascript del lado servidor cuya finalidad es permitir construir aplicaciones escalables y que atende peticiones de modo asíncrono, permitiendo servir gran cantidad de peticiones de modo concurrente sin un alto coste. Podemos descargarlo desde aquí.
  3. Ant. Puedes encontrarlo aquí.
  4. Android SDK.
  5. Finalmente instalamos Apache Cordova
Para la instalación de Apache Cordova nos apoyaremos en Node.js. Para ello debemos ejecutar en un terminal de comandos lo siguiente:
npm install -g cordova

Crear un proyecto Apache Cordova

Ir a la carpeta donde queremos generar el nuevo proyecto y ejecutar el siguiente comando:
cordova create NombreProyecto com.blog.ljlg.cordova "Hola LJ"
Donde:
  • NombreProyecto. Carpeta donde se crea el proyecto.
  • com.blog.ljlg.cordova. Paquete de clases base del proyecto
  • "Hola Luis". título de la aplicación a mostrar.
Se deben generar la siguiente estructura de directorios:
  • merges
  • platforms
  • plugins
  • www
En este momento no tendremos nada dentro d ela carpeta platforms, pues aun no hemos incluido ninguna plataforma para desarrollar
¿Cómo indico para que plataforma quiero crear la aplicación?
Una vez que tenemos el proyecto podemos añadirle plataformas para las cuales se quiere generar el proyecto, así por ejemplo para añadirle la plataforma Android iremos a la carperta del proyecto y ejecutaremos lo siguiente:
cordova platform add android
En este caso se nos añadirá contenido a la carpeta platforms, así mismo

Compilar el proyecto.

cordova build
Finalmente podemos probar nuestro proyecto sobre un emeulador:
cordova emulate android

domingo, 25 de diciembre de 2016

Java - Leer archivo desde la carpeta de recursos

Leer archivos desde la carpeta de recursos
Dentro de un proyecto java podemos tener alamcenados recursos: imagenes, documentos de texto, etc. Para ello existe la carpeta de recursos. En la siguiente imagen puede verse la extructura d eun proyecto con su carpeta de recursos.

Para acceder a la carpeta de recursos debemos hacerlo a través del ClassLoader. El ClassLoader se encarga de cargar las distintas clases en la Maquina Virtual de Java.

Suponiendo que tengamos una clase llamada App entonces podremos acceder a su class loader del siguiente modo

// getClass() nos retorna la clase y a partir de ella se obtendrá el ClassLoader
ClassLoader loader = getClass().getClassLoader();

// Si estamos en una función estática en vez de getClass() podemos acceder directamente a la clase
ClassLoader loader = App.class.getClassLoader();

El loader tiene una función getResource(String name) que nos rectorna la URL asociada al recurso a partir de la cual podremos acceder al recurso. A continuación se muestra un ejemplo completo:

package ljlg.blog.classloader;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.stream.Collectors;

/**
 *
 *
 */
public class App {
  
    public static void main(String[] args) throws IOException {
        App.leerArchivoRecursos();
    }

    public static void leerArchivoRecursos() throws IOException {

        ClassLoader loader = App.class.getClassLoader();
      
        InputStream stream = loader.getResource("datos.txt").openStream();
      
        try (BufferedReader buffer = new BufferedReader(new InputStreamReader(stream))) {
            System.out.println(buffer.lines().collect(Collectors.joining("\n")));
        }
    }
}

domingo, 6 de marzo de 2016

Android NDK (Native Development Kit - Sistema de Desarrollo Nativo)

NDK nos va a permitir llamar a librerías escritas en C y C++ desde nuestra aplicacióna través de JNI (Java Native Interface). Aunque para la mayoría de las aplicaciones no es necesario existen casos en los que necesaitaremos usar esta funcionalidad. Por ejemplo si queremos realizar aplicaciones con gran carga de gráficos en cuyo caso será mejorar el tiempo de respuesta de nuestra aplicación.
En cualquier caso no debemos usar NDK por simple gusto pues la programación podría resultar mas compleja y aumentar la posibilidad de cometer errores.
A continuación veamos un ejemplo de como crear una aplicación que use NDK. Lo primero es tener instalada junto con la SDK de Android la NDK.
Ahora creamos nuestro proyecto, en este caso he creado un sencillo proyecto con un texto y un botón, cuando pulsemos el botón se sustituirar el texto por uno devuelto por una librería creada en C.
La definición de la pantalla sería la siguiente:
<? xml version= "1.0" encoding= "utf-8" ?> 
< RelativeLayout xmlns: android = "http://schemas.android.com/apk/res/android"  
xmlns: tools = "http://schemas.android.com/tools"  
  android :layout_width= "match_parent"  
  android :layout_height= "match_parent"  
  android :paddingBottom= "@dimen/activity_vertical_margin"
  android :paddingLeft= "@dimen/activity_horizontal_margin"  
  android :paddingRight= "@dimen/activity_horizontal_margin"
  android :paddingTop= "@dimen/activity_vertical_margin"
  tools :context= "com.losga.ndkexample.MainActivity">
    < TextView  
      android :layout_width= "wrap_content"  
      android :layout_height= "wrap_content"  
      android :text= "Mensaje"  
      android :layout_alignParentRight= "true"  
      android :layout_alignParentEnd= "true"
      android :layout_alignParentLeft= "true"  
      android :layout_alignParentStart= "true"  
      android :id= "@+id/textView" />
  < Button  
     android :layout_width= "wrap_content"  
     android :layout_height= "wrap_content"
     android :text= "Pulsa aquí"
     android :id= "@+id/button"  
     android :layout_below= "@+id/textView"  
     android :layout_centerHorizontal= "true"  
     android :layout_marginTop= "29dp" />
 </RelativeLayout>
y la clase de nuestra actividad tendrá el siguiente contenido:

package com.losga.ndkexample;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;  
import java.util.Date;

public class MainActivity extends AppCompatActivity {

  native String getMensaje(Date fecha);

  @Override  
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);  
      final TextView texto = (TextView) findViewById(R.id. textView);
      final Button button = (Button) findViewById(R.id. button);
      button.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
          texto.setText(getMensaje(new Date()));
        }
      });
    }
  }
En esta clase vemos que está la siguiente línea:
native String getMensaje(Date fecha);
Con el modificador native estamos indicando que dicha función es una llamada a una librería en C, que posteriormente vamos a crear.
A continuación vamos a crear una carpeta con el nombre jni, en Android Studio ya tenemos dicha opción.
El siguiente paso es crear un archivo con el nombre Android.mk dentro de la carpeta que acabamos de crear con el siguiente contenido:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := jniUtils
LOCAL_SRC_FILES := jniUtils.c
include $(BUILD_SHARED_LIBRARY)
A continuación usaremos JavaH para crear la cabecera que tendremos que incluir en nuestra clase, previamente debemos hacer un build del proyecto pues javaH necesitará de la clase java donde se encuentra la llamada a jni. La línea a ejecutar es:
javah -jni -classpath <ruta_donde_este_el_archivo>/android.jar;<ruta_proyecto>/build/intermediates/classes/debug com.losga.ndkexample.MainActivity
como vemos s enos creará un archivo con la definición de la función nativa, en este caso el archivo se llama com_losga_ndkexample_MainActivity.h y que tendrá el siguiente contenido:
/* DO NOT EDIT THIS FILE - it is machine generated */
 #include <jni.h>  
/* Header for class com_losga_ndkexample_MainActivity */
#ifndef _Included_com_losga_ndkexample_MainActivity
#define _Included_com_losga_ndkexample_MainActivity  
#ifdef __cplusplus extern "C" {  
#endif  
/* 
 * Class: com_losga_ndkexample_MainActivity
 * Method: getMensaje
 * Signature: (Ljava/util/Date;)Ljava/lang/String;  
 */
 JNIEXPORT jstring JNICALL Java_com_losga_ndkexample_MainActivity_getMensaje
    (JNIEnv *, jobject, jobject);
#ifdef __cplusplus
}
#endif  
#endif
A continuación debemos crear el archivo en C que tendrá la implementación de la función:

#include <jni.h>
#include "jniUtils.h"
#include <com_losga_ndkexample_MainActivity.h>
JNIEXPORT jstring JNICALL Java_com_losga_ndkexample_MainActivity_getMensaje
        (JNIEnv *env, jobject obj1, jobject obj2)
{
    return (*env)->NewStringUTF(env, "Buenos días " );
}

El siguiente paso es añadir al path la localización del ndk-build, para ello debemos modificar la variables de entorno de nuestro sistema.
Normalmente nuestro ndk estará junto a la sdk de Android:
<Ruta_de_lasdk>\sdk\ndk-bundle
Ahora nos vamos a la carpeta jni y ejecutamos lo siguiente:
ndk-build
vemos entonces que se generan una serie de archivos, en este caso se nos generan las carpetas libs y obj, en este momento tenemos que crear una carpeta con el nombre jniLibs y copiar el contenido de obj\local\ tal como vemos en la imagen.
Antes de compilar nuestro proyecto ahora debemos modificar el archivo gradle.properties y añadirle la siguiente línea:
android.useDeprecatedNdk= true
finalmente modificamos el archivo build.grade para añadir lo siguiente:
... 
sourceSets {
    main {
        jni.srcDirs = []
    }
}
...
Debemos de tener en cuenta que si modificamos nuestro archivo en C deberemos volver a ejecutar el ndk-bunble y volver a copiar las librerías en la carpeta jniLibs.

viernes, 19 de junio de 2015

Resetear el usuario y password de admnistración en Weblogic

Es posible que en algún momento olvidemos cual es la clave de nuestro dominio en weblogic para resetear nuestro usuario y password se deben llevar a cabo unos sencillos pasos:

  1. En caso de encontrarse arrancado debemos parar el dominio.
  2. Renombrar la carpeta carpeta_dominio/server/data a  carpeta_dominio/server/data-old.
  3. Ejecutamos el script carpeta_dominio/bin/setDomainEnv
  4. Vamos a la carpeta: carepta_dominio/security
  5. Ejecutamos java weblogic.security.utils.AdminAccount <nombre_usuario> <clave>.
  6. Editamos el archivo carpeta_dominio/servers/AdminServer/security/boot.properties
  7. En dicho archivo cambiamos username=<nombre_usuario> y password=<clave>.
Arrancamos el servidor y ya tendremos cambiada la clave.

martes, 9 de junio de 2015

PL/SQL Oracle: "Warning: compiled but with compilation errors"

Es posible que no hayamos encontrado alguna que otra vez con este error cuando estamos creando un procedimiento o función en Oracle y que no nos muestra más información que la indicada en el título.
En estos casos lo que debemos hacer es ejecutar la siguiente sentencia SQL:
SELECT * FROM USER_ERRORS
En el resultado de esta consulta nos aparecerá el error por el cual no se ha compilado al que hace referencia el mensaje anterior.

martes, 28 de abril de 2015

Android - Usar una base de datos existente

Es normal que para nuestras aplicaciones queramos trabajar con una base de datos previamente creada con datos insertados. Los pasos a seguir serán los siguientes:
  1. Crear la base de datos SQLite e insertar los datos que queramos. Podeís usar para ello alguna herramienta como SQLite Studio.
  2. Copiamos la base de datos creada a la carpeta de nuestro proyecto Android assets.
  3. Ahora en la clase que vamos a usar para interactuar con la base de datos lo que se va a hacer es lo siguiente:
    1. Verificar si ya existe la base de datos. Si esto ociurre ya ha sido creada por lo que no será necesario crearla de nuevo. En este caso debemos tener en cuenta que la ruta a la base de datos de nuestra aplicación viene dada por "context.getApplicationInfo().dataDir + "/databases/" + DATABASE_NAME" tal y como podeís ver en el código de ejemplo.
    2. Si no existe simplemente copiaremos el archivo que previamente hemos colocado en la carpeta assets en la ruta vista con anterioridad.
A continuación tenéis el código de ejemplo:


package com.losga.pedidos.com.losga.db;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.content.res.AssetManager;
import android.util.Log;

import com.losga.pedidos.dto.Entity;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Timestamp;
import java.util.Arrays;
import java.util.Date;
import java.util.Scanner;

/**
 * Created by Luis J. L.G. 
 */
public class DBHelper extends SQLiteOpenHelper {

    private Context context;
 
    // Nombre de la base de datos
    private static final String DATABASE_NAME = "ljlg.db";
 
    // Ruta donde se encuntra la base de datos
    private static String path;

    private static final int DATABASE_VERSION = 1;

    public DBHelper(Context context)
    {
         super(context, DATABASE_NAME, null, DATABASE_VERSION);
         try {
             this.context = context;
             // Ruta donde va a estar la base de datos en Android
             path = context.getApplicationInfo().dataDir + "/databases/" + DATABASE_NAME;
             copyDB();
         } catch (IOException e) {
             e.printStackTrace();
         }
     }

    @Override
    public void onCreate(SQLiteDatabase db) {
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    }

    private void copyDB() throws IOException {

        // Verificar si ya existe la base de datos
        File dbArchivo = new File(path);
        if (!dbFile.exists()) {
            InputStream inputStream = context.getAssets().open("MiDB.db");
            // Se crea el archivo para la base de datos
            OutputStream outputStream = new FileOutputStream(path);
            byte[] buffer = new byte[4096];
            int length;
            while ((length = inputStream.read(buffer)) > 0) {
                outputStream.write(buffer, 0, length);
            }
            outputStream.flush();
            outputStream.close();
            inputStream.close();
        }
    }
}

lunes, 16 de febrero de 2015

Cisco anyconnect: "VPN ​Failed to initialize connection subsystem"

Hoy cuando me he ido a conectar a una VPN resulta que me he encontrado con el mensaje: "VPN ​Failed to initialize connection subsystem". 

Pues bien parece ser que el problema se produce debido a alguna de las útlimas actualizaciones de Windows 8. En mi caso Windows 8.1.

La solución es bastante sencilla en este caso: Nos vamos a la carpeta donde se encuentra instalado el programa que normalmente será "C:\Program Files (x86)\Cisco\Cisco AnyConnect Secure Mobility Client" y aquí nos colocamos sobre "vpnui.exe" y pulsamos sobre "Solucionar problemas de compatibilidad" y posteriormente seleccionamos "Probar configuración recomendada". Con esto queda solucionado el problema.

lunes, 9 de febrero de 2015

Weblogic. Copiar dominios

Es muy común y sobre todo si nos dedicamos al desarrollo que en algún momento queramos duplicar un dominio de nuestro servidor de aplicaciones en otra máquina distinta, esto conlleva crear de nuevo todos los pool de conexiones, instalar aplicaciones, etc.

En el caso de WebLogic si en algún momento has intentado copiar directamente la carpeta del dominio esto no funciona.

Pero la solución es sencilla. Existen dos comandos pack y unpack que nos permiten crear una plantilla del dominio que deseemos, de modo que podamos posteriormente crear un nuevo dominio en el que se incluirá la configuración de nuestro dominio de origen y de las aplicaciones que se encuentren instaladas en el mismo.

Si ejecutamos el siguiente comando:

{ruta_servidor}\common\bin\pack -domain={ruta_servidor}\user_projects\domains\local -template={ruta_salida}\mi_dominio.jar -template_name=mi_domino -log=mi_log.log -log_priority=INFO

donde {ruta_servidor} será la ruta donde tengaos nuestro weblogic instalado y {ruta_salida} donde queremos que se genere la plantilla. 

Se nos generará un archivo mi_dominio.jar el cual ya podremos usar como plantilla para crear nuevos dominios. Para ello podemos usar el comando unpack.

unpack -template={rruta_donde_tengamos_la_plantilla}/mi_dominio.jar -domain={ruta_servidor}/user_projects/domains/nuevo_dominio




domingo, 18 de enero de 2015

Depuración remota en JAVA

Si deseamos depurar una aplicación java en un servidor remoto debemos de activar la depuración en remoto en la máquina virtual de java. Para ello sólo debemos de añadir las siguientes opciones de java:

-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=1277

-Xdebug indica a la máquina virtual que debe activar el modo depuración.

-Xrunjdwp <options> Nos permite definir las características de como se va a realizar la conexión.

Las opciones en este caso son:
  • transport=dt_socket. Indica que la conexión se va a realizar a através de un socket
  • address=1277. Le indica a la máquina virtual a través de que puerto debe escuchar.
  • suspend=n Si está puesto como as 'y' la JVM comienza en modo suspendido y espera en este modo hasta que nos conectemos para depurar.
Estas opciones debemos añadirlas en el arranque del servidor de aplicaciones sobre el que deseemos depurar.

jueves, 16 de octubre de 2014

Spring - Primera Aplicación

Lo primero que vamos a hacer es descargar eclipse, si no los tenemos ya instalado, desde la misma página de spring podemos hacer esto. Podemos descargarlo aquí.

A continuación y desde eclipse vamos a la opción del menú Help -> Eclipse Markeplace, tal y como vemos en la imagen




Ahora realizamos una búsqueda para por la palabra Spring e instalamos la versión que se corresponda con nuestra versión de eclipse.


Tras esto se nos pedira que reiniciemos el eclipse y ya podemos empezar a trabajar. Creamos un nuevo proyecto del tipoSpring.


 En la siguiente pantalla vamos a seleccionamos "Simple Java".






A continuación vamos a descargarnos las librerías de spring desde la suigiente url: http://maven.springframework.org/release/org/springframework/spring.

Desde donde descargaremos la versión mas reciente.

Debemos añadir al proyecto las siguientes librerías (la parte final del nombre variará en función de la versión que se hay descargado):
  • spring-aop-4.1.1.RELEASE.jar 
  • spring-aspects-4.1.1.RELEASE.jar 
  • spring-beans-4.1.1.RELEASE.jar 
  • spring-context-4.1.1.RELEASE.jar 
  • spring-context-support-4.1.1.RELEASE.jar 
  • spring-core-4.1.1.RELEASE.jar 
  • spring-expression-4.1.1.RELEASE.jar 
  • commons-logging-1.2.jar 
 Ahora vamos a crearnos dos clases:

package com.ljlg.blog.spring;

public class HolaMundo {
   
    private String mensaje;
   
    public void setMensaje(String mensaje)
    {
        this.mensaje = mensaje;
    }
   
    public void mostrarMensaje()
    {
        System.out.println(mensaje);
    }
}



package com.ljlg.blog.spring;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class HolaMundoApp {

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");      
        HolaMundo bean = (HolaMundo)context.getBean("holaMundo");       
        bean.mostrarMensaje();      
    }
}


A continuación creamos un archivo Beans.xml en la carpeta src. Este archivo es el archivo de configuración del contexto donde se definiran que objetos deben existir al cargar el mismo. En nuestro ejemplo se define un objeto del tipo HolaMundo, con el campo mensaje inicializado.

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemalocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd">

<bean class="com.ljlg.blog.spring.HolaMundo" id="holaMundo">
       <property name="mensaje" value="Hola mundo, esta es mi primera aplicación con Spring">
   </property>
</bean>

</beans>

Ya podemos ejecuatr nuestra primera aplicación hecha con spring.

lunes, 22 de septiembre de 2014

Dibujar con Android 1

Dibujar con Android 1.

Para dibujar en la pantalla simplemente debemos sobreescribir la función onDraw del componente en el cual deseamos dibujar. 

A continuación os pongo un ejemplo. He creado una clase que extiende de la clase View, en esta como podeis ver se sobreescribe la función onDraw y en ella se dibuja un circulo de color azul sobre fondo negro en el centro del componente.


package com.ljlg.dibuja;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.util.AttributeSet;
import android.view.View;

public class DrawCircle extends View {

    private final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);

    public DrawCircle(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public DrawCircle(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public DrawCircle(Context context) {
        super(context);
    }

    @Override
    protected void onDraw(Canvas canvas) {

         // Calculamos el punto central del componente
        int cx = this.getWidth() / 2;
        int cy = this.getHeight() / 2;

        // Ponemos el fondo de color negro
        canvas.drawColor(Color.BLACK);

         // Dibujamos un circulo relleno de color azul
        paint.setStyle(Style.FILL_AND_STROKE);
        paint.setColor(Color.BLUE);
        canvas.drawCircle(cx, cy, 100, paint);

    }

}
 

Así pues lo único que debeis hacer es dibujar en el canvas aquello que se desee (circulos, líneas, un bitmap, texto, etc..)

En caso de que se desee que forzar la llamada a la función onDraw simplemente se debe hacer una llamada a la función invalidate().

Para añadir el componente creado simplemnete nos vamos a la actividad en la cual queremos que aparezca y lo añadirmos, tal y como se muestra a continuación


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.ljlg.dibuja.MainActivity" >

 <com.ljlg.dibuja.DrawCircle
        android:id="@+id/drawView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="1dp"
        android:layout_marginTop="1dp"/>



</RelativeLayout>


Como puede verse sólo es necesario añadir una etiqueta indicando la clase que implementa el componente. 


miércoles, 16 de julio de 2014

Las Canteras

Ahora que llega el verano y que van a empezar mis vacaciones os quiero recomendar la playa que tengo cerquita de mi casa que es la playa de Las Canteras.


Se trata de la principal playa de la ciudad de Las Palmas de Gran Canaria. Una playa de la que se puede disfrutar durante todo el año pues es muy raro que bajemos de los 20 grados en cualquier época del año.




 En la playa se pueden distinguirvarias zonas: por un lado la mayor parte de la playa está protegida por una barrera de roca natural lo que hace que casi nunca haya oleaje, cuando la marea está baja es casi como estar en una piscina. Por otro tenemos la llamada zona de la Cicer donde si hay mas corrientes y olas y mi zona preferida pues es a donde voy a despejarme haciendo surf. Si os gusta el surf además teneís la zona del Lloret, junto al auditorio que se trata de una zona de rocas donde suelen salir muy buenas olas.

La Cicer
Si lo que os gusta es caminar teneís una larga avenida que recorre todas la playa y continuá mas allá hasta el Confital, donde teneís una zona de baño tranquila aunque con bastantes corrientes y con olas para surfear que pueden llegar a ser peligrosas.

El Confital
Aquí os pongo la vista de una cámara en directo:

Y aquí un enlace a una nueva webcam en la zona de la cicer.

domingo, 27 de abril de 2014

Android - AlarmManager

Anteriormente hemos visto un artículo en el cual se muestra como hacer que una función se ejecute cada cierto tiempo, sin embargo si lo que queremos es que el proceso se ejecute cada cierto tiempo aunque la aplicación se cierre, la manera correcta es usar la clase AlarmManager. A través de esta clase podemos añadir al servicio de alarma de Android llamadas a nuestro proceso. Lo primero que debemos hacer es crear una clase que extienda de la clase BroadcastReceiver y sobreescribir la función onReceiver con las funcionalidades que se deseen.

package com.example.alarmexample;

import java.text.SimpleDateFormat;
import java.util.Date;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.location.Location;

public class ExampleBroadcastReceiver extends BroadcastReceiver {
   
    @Override
    public void onReceive(Context context, Intent intent) {
        // Aquí lo que se quiera ejecutar
        System.out.println("*******Temporizador " + new SimpleDateFormat("HH:mm:ss").format(new Date()));      
    }
}

El segundo paso es modificar el archivo AndroidManifest.xml. De este modo registramos el Receiver.

...
       <activity
            android:name="com.example.alarmexample.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
     
       </activity>

        <!-- Registar el Receiver -->
        <receiver
            android:name="com.example.alarmexample.
ExampleBroadcastReceiver"
            android:enabled="true" >
        </receiver>

Finalmente debemos añadir el código necesario para registrar la acción a ejecutarse y para pararla. Suponiendo que se han añadido dos botones a nuestra aplicación el código sería el siguiente:

package com.example.alarmexample;

import android.support.v7.app.ActionBarActivity;
import android.support.v4.app.Fragment;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.TextView;

public class MainActivity extends ActionBarActivity {
   
    private ImageButton btnStart;
   
    private ImageButton btnStop;
   
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
       
        btnStart = (ImageButton) findViewById(R.id.imageButton1);
      
        btnStart.setOnClickListener(new OnClickListener() {
             
            // Acción a ejecutar cada vez que se pulse el botón
            @Override
            public void onClick(View v) {               
                /***********************************************************/
                /***********************************************************/
                /***********************************************************/
                // Registrar el servicio cada 60 segundos
                AlarmManager am = (AlarmManager) MainActivity.this.getSystemService(ALARM_SERVICE);                              
                Intent intent = new Intent(MainActivity.this, ExampleBroadcastReceiver.class);               
                  PendingIntent pendingIntent =
                          PendingIntent.getBroadcast(MainActivity.this, 1234567,
                                  intent, PendingIntent.FLAG_UPDATE_CURRENT);               
                  // Realizar la repetición cada 60 segundos. 

                 // Con el primer parámetro estamos indicando que se continue ejecutando 
                 // aunque el dsipositivo este con la pantalla apagada.
                 // En el segundo parámetro se indica a partir de cuando comienza el scheduler,
                 // en este ejemplo es desde el momento actual
                 // El tercer parámetro indica cada cuanto tiempo.
                 // El cuarto hace referencia al receiver que se va a ejecutar.
                 am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 60*1000, pendingIntent);                /***********************************************************/
                /***********************************************************/
                /***********************************************************/
                               
            }
        });    
      
        btnStop = (ImageButton)findViewById(R.id.ImageButton01);
        btnStop.setOnClickListener(new OnClickListener() {
             
            // Acción a ejecutar cada vez que se pulse el botón
            @Override
            public void onClick(View v) {
                /***********************************************************/
                /***********************************************************/
                /***********************************************************/

                // Cancelación
                AlarmManager am = (AlarmManager) MainActivity.this.getSystemService(ALARM_SERVICE);
              
                Intent intent = new Intent(MainActivity.this, com.example.alarmexample.ExampleBroadcastReceiver.class);               
                PendingIntent pendingIntent =
                      PendingIntent.getBroadcast(MainActivity.this, 1234567,
                                intent, PendingIntent.FLAG_UPDATE_CURRENT);               
                am.cancel(pendingIntent);

                /***********************************************************/
                /***********************************************************/
                /***********************************************************/
            }
        });          
    }
}

sábado, 12 de abril de 2014

Android - Planificador de tareas (scheduler)

Para crear una aplicación que se ejecute cada cierto tiempo en Android podemos hacerlo de dos modos diferentes, mediante el uso de timers o mediante el uso de  la clase ScheduledThreadPoolExecutor. En este artículo vamos a usar la clase ScheduledThreadPoolExecutor.

La clase ScheduledThreadPoolExecutor se trata de una implementación de un pool de hilos de ejecución de java.

Para instanciar una un pool de hilos con un número n de hilos podemos usar la clase java.util.concurrent.Executors, que mediante la función newScheduledThreadPool(n) nos retornará un pool con el número de hilos requeridos. Para nuestro ejemplo vamos a pedir un único hilo:

private ScheduledThreadPoolExecutor sch = (ScheduledThreadPoolExecutor) Executors.newScheduledThreadPool(1);

Otra clase que es importante y que vamos a usar es ScheduledFuture. Esta clase nos permite controlar la acción a ejecutar de modo que en cualquier momento podamos cancelar el scheduler.

        // Definir que una tarea (una instancia del tipo Runnable) se ejecute cada 10 segundos.
        periodicFuture = sch.scheduleAtFixedRate(tarea, 0, 10,  TimeUnit.SECONDS);

Para cancelar la tarea sólo es necesario usar la función cancel de la clase ScheduledFuture.

       periodicFuture.cancel(false);

A continuación  veamos todo el código junto de modo tenemos una clase que cada 10 segundos ejecutará un System.out


package com.ljlg.blogscheduler;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

public class MySchedule {
    private ScheduledThreadPoolExecutor sch = (ScheduledThreadPoolExecutor) Executors
            .newScheduledThreadPool(1);

    private ScheduledFuture<?> periodicFuture;
  
    public void start() {
        // Tarea que queremos ejecutar
        Runnable tarea = new Runnable() {
            @Override
            public void run() {
                // Tú código aquí
                System.out.println("Probando");
            }
        };

        // Indicar cuando se ejecuta la próxima ejección
        periodicFuture = sch.scheduleAtFixedRate(tarea, 0, 10,
                TimeUnit.SECONDS);
    }

    public void stop() {
        periodicFuture.cancel(false);
    }
}


Finalmente sólo será necesario que instanciemos nuestra clase desde nuestro programa. Por ejemplo si tenemos un programa con un botón de comenzar y otro de parar tendríamos algo como lo siguiente:



public class MainActivity extends ActionBarActivity {
   
    private Button btnStart;
   
    private Button btnStop;
   
    MySchedule sd = new MySchedule();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btnStart = (Button) findViewById(R.id.button1);
       
        btnStart.setOnClickListener(new OnClickListener() {
              
            // Acción a ejecutar cada vez que se pulse el botón
            @Override
            public void onClick(View v) {
                sd.start();           
            }
        });    
       
        btnStop = (Button)findViewById(R.id.button2);
        btnStop.setOnClickListener(new OnClickListener() {
              
            // Acción a ejecutar cada vez que se pulse el botón
            @Override
            public void onClick(View v) {
                sd.stop();           
            }
        });    
       
    }
 .........
}



jueves, 3 de abril de 2014

Android - Bases de Datos - SQLite

Cuando trabajamos con Android normalmente usaremos como base de datos SQLite. Para ello usaremos las clases incluidas con las librerías de Android del paquete android.database.sqlite.

Lo primero que tenemos que hacer es crear un clase que extenderá de la clase SQLiteOpenHelper.En esta clase debemos sobreescribir los métodos onCreate y onUpdate. Estos dos métodos se van a ejecutar cuando se crea la base de datos y cuando se actualiza.

A continuación tenemos un ejemplo en el cual se crea una tabla de usuarios y se inserta un usuario al crear la base de datos.

package com.ljlg.programandoblog;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;

public class DBHelper extends SQLiteOpenHelper {


    private static final String DATABASE_CREATE = "create table usuarios (" +
            "id integer primary key autoincrement, login text not null," +
            "password text not null);";
   
    public DBHelper(Context context, String name, CursorFactory factory,
            int version) {
        super(context, name, factory, version);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        // Aquí generamos las tablas necesarias      
        db.execSQL(DATABASE_CREATE);
        db.execSQL("INSERT INTO usuarios (login, password) values ('usr1', 'pwd1');");
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    }   
}

Una vez que tenemos la clase creada veamos como usarla.

// Instanciamos la clase creada con anterioridad
DBHelper helper = new DBHelper(this, "blogDatabase", null, 1);      
// Recuperamos una instancia de la clase SQLiteDatabaseque nos va servir para operar sobre la base de datos
SQLiteDatabase db = helper.getReadableDatabase();

Para realizar consultas podemos realizarlas con la función rawQuery y pasando una sentencia sql o mediante la función query indicando la tabla, los campos y el filtro a aplicar.


rawQuery sin parámetros:

Cursor result = db.rawQuery(" SELECT id, login, password FROM Usuarios", null);

rawQuery con parámetros:

String[] parametros = new String[] {"usr1"};
Cursor result = db.rawQuery(" SELECT id, login, password FROM Usuarios where login = ?", parametros);

query con parámetros: 

String[] campos = new String[] {"id", "login", "password"};
String[] parametros = new String[] {"usr1"};        
Cursor result = db.query("Usuarios", campos, "login=?", parametros, null, null, null);


A continuación vemos como recorrer los resultados


while (result.moveToNext()) {
  Long id = result.getLong(0);
  String login= result.getString(1);
  String password = result.getString(2);
  System.out.println("[" + id + "][" + login + "][" + password + "]");
 }      

sábado, 15 de marzo de 2014

Android - Primeros Pasos - Mostrando listados 2

En el artículo anterior vimos como usar el componente ListView. Sin embargo sólo mostrabamos en cada elemento un string, vamos a ver como mostrar item mas complejos.

Para el ejemplo vamos a crear una lista que muestre fichas de personas con el nombre y la foto de la persona.

Lo primero es crear un layout en la carpeta res/layout, ya sea mediante el asistente de eclipse o creando un archivo xml con el código correspondiente. Este layout será el que indicará que elementos y como se va a mostrar cada uno de los items de la lista.



Vamos a añadir al layout dos elementos un ImageView para mostrar la foto y un TextView para el nombre de la persona.


<?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="match_parent"
    android:orientation="horizontal" >

    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="wrap_content"
        android:layout_height="94dp"
        android:layout_weight="0.80"
        android:src="@drawable/ic_launcher" />

    <TextView
        android:id="@+id/textView1"
        android:layout_width="214dp"
        android:layout_height="46dp"
        android:text="Medium Text"
        android:textAppearance="?android:attr/textAppearanceMedium" />

</LinearLayout>


Ahora vamos a crear dos clases, una que representa al objeto persona y otra que extenderá de la clase ArrayAdapter y que se va a encargar de generar cada uno de los items que se van a mostrar en el ListView.

Clase Persona:


package com.ljlg.programandoblog;

import android.graphics.Bitmap;

public class Persona {   
    private String nombre;   
    private Bitmap foto;
  
    public Persona(String nombre, Bitmap foto)
    {
        this.nombre = nombre;
        this.foto = foto;       
    }
    public String getNombre() {
        return nombre;
    }
    public void setNombre(String nombre) {
        this.nombre = nombre;
    }
    public Bitmap getFoto() {
        return foto;
    }
    public void setFoto(Bitmap foto) {
        this.foto = foto;
    }
}


Clase PersonaAdapter


package com.ljlg.programandoblog;

import java.util.List;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;


public class PersonaAdapter extends ArrayAdapter<Persona>
{
   
    Context context;
    int layoutResourceId;
    private List<Persona> datos;


    public PersonaAdapter(Context context, int layoutResourceId, List<Persona> datos) {
        super(context, layoutResourceId, datos);
        this.context = context;
        this.layoutResourceId = layoutResourceId;
        this.datos = datos;
    }
   
   
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
       
        View row = convertView;
       
        if (row == null) {
            // Si la fila que se está mostrando no ha sido creada con anterioridad
            LayoutInflater inflater = (LayoutInflater) getContext()
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            row = inflater.inflate(R.layout.persona, null);
        }
       
        Persona persona = datos.get(position);
       
        if (persona != null)
        {
            // rellenamos
            TextView nombre = (TextView) row
                    .findViewById(R.id.textView1);
            nombre.setText(persona.getNombre());
           
            ImageView foto = (ImageView) row.findViewById(R.id.imageView1);           
            foto.setImageBitmap(persona.getFoto());
        }       
        return row;       
    }
}


Finalmente sólo tendremos que hacer la craga de los valores en nuetra actividad de manera similar a como se vió en el artículo anterior:


package com.ljlg.programandoblog;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import android.os.Bundle;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.widget.ListView;

public class MainActivity extends Activity {

    ListView listView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // listView definido en el layout
        listView = (ListView) findViewById(R.id.listView1);

        List<Persona> valores = new ArrayList<Persona>();

        // Cargar la lista de personas
        Bitmap foto = cargarFoto();
        valores.add(new Persona("Luis", foto));
        valores.add(new Persona("Juan", foto));

        // Adaptador
        PersonaAdapter adaptador = new PersonaAdapter(this, R.layout.persona,
                valores);

        // Asignar el adaptador al listview
        listView.setAdapter(adaptador);

    }

    private Bitmap cargarFoto() {
        try {
            // Para el ejemplo cargamos una foto desde la carpeta assets
            InputStream archivo = getAssets().open("foto.png");
            Bitmap bitmap = BitmapFactory.decodeStream(archivo);
            return bitmap;
        } catch (IOException e1) {

            e1.printStackTrace();
        }
        return null;
    }

}