domingo, 14 de julio de 2013

SOCKETS CON IntentService ( ANDROID Y PC )

Especificaciones:

Hardware: LG L9
Versión: ANDROID ICE CREAM 4.0.4
Framework: Eclipse Java EE IDE for Web Developers.
Versión: Juno Service Release 2

Bueno, para comenzar este pequeño tutorial daré algunos aspectos técnicos que son básicos para entender este tipo de aplicaciones.

Servicios:
Un servicio es un componente de aplicación que puede realizar operaciones de larga duración dentro de un subproceso y no proporciona una interfaz de usuarios. Otro componente de la aplicación se puede iniciar desde un servicio y continuará funcionando dentro un segundo plano, incluso si el usuario cambia a otra aplicación.
Nuestro servicio puede tener básicamente dos formas:

·         Started
Un servicio se “empieza” cuando un componente de la aplicación (por ejemplo, una actividad) se inicia llamando startService(). Una vez iniciado, un servicio puede ejecutarse en un segundo plano de forma indefinida, incluso si el componente de se inició, se destruye. Por lo general, un servicio que se inicia realiza solo operación y no devuelve un resultado a la persona que llama. Por ejemplo, puede descargar o cargar un archivo en la red. Una vez realizada la operación, el servicio debe pararse.

·         Bound
Un servicio es “bound” cuando un componente de aplicación se una a ella llamado blindService(). Un servicio consolidado ofrece una interfaz cliente-servidor que permite a los componentes interactuar con el servicio, enviar solicitudes, obtener resultados, e incluso hacerlo a través de los procesos de comunicación entre procesos (IPC). Un servicio funciona mientras otro componente de la aplicación es obligado a ello. Múltiples componentes pueden unirse al servicio, pero todos ellos llegan dirimir, cuando el servicio se destruye.

Aunque generalmente se trabaja con estos servicios por separado, el servicio puede funcionar en ambos sentidos, se pueden iniciar(ejecutar indefinidamente) y permitir la unión. Es simplemente cuestión de si se implementa un par de métodos de devolución de llamada:

Para permitir el inicio de los componentes.
Para permitir la unión.

IntentServices:
Es una clase base para generar un servicio que maneja peticiones asíncronas ( expresadas como intenciones) a petición.
Los clientes envían peticiones a través de llamadas startService(intención), el servicio se pone en marcha cuando se necesita, se encarga de cada intención, y todo esto se genera en un subproceso de trabajo y se detiene a sí mismo cuando se acaba el trabajo.
Este “proceso en cola  de trabajo” patrón se utiliza comúnmente para no sobrecargar las tareas dentro del hilo principal dentro la aplicación. En este caso existe la clase intentService para simplificar este patrón y cuidar los procesos. Para usarlo, se extiende intentService y se implementa onHandleIntent(Intención). IntentService recibirá las intenciones, iniciando el subproceso de trabajo, y deteniendo el servicio según corresponda.

LA APLICACIÓN

EN JAVA:

clase MyServerSocket.java:

package sockets;

import java.io.DataOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Random;

/**
 *
 * @author kamehy
 */
public class MyServerSocket {

final int PUERTO=5001;
ServerSocket sc;
Socket so;
DataOutputStream salida;
String mensajeRecibido;

   public void MyServerSocket(){
       
   }
        
    public void initServer() {        
        try {
            boolean listening = true;
            sc = new ServerSocket(PUERTO);/* crea socket servidor que escuchara en puerto 5000*/
            so = new Socket();    
            
            int limite=10;
            Random r = new Random();
            
            System.out.println("Iniciando server por puerto " + PUERTO);
            while (listening)
               new ThreadClienteSc(sc.accept(),r.nextInt(),PUERTO).run();
            
            System.out.println("Cerrando server");
            sc.close();//Aqui se cierra la conexión con el cliente
        } catch (Exception e) {
            System.out.println("Error: " + e.getMessage() + " " + e.toString());
        }
    }
}

clase Sockets,java:

package sockets;

import java.net.ServerSocket;
import sockets.MyServerSocket;

/**
 *
 * @author kamehy
 */
public class Sockets {

    private static MyServerSocket myserverSocket;
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        myserverSocket = new MyServerSocket();        
        myserverSocket.initServer();
    }
}

clase ThreadsClienteSc:

package sockets;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author kamehy
 */
public class ThreadClienteSc implements Runnable{

    private int id;
    private Socket so;
    private DataOutputStream salida;
    private String mensajeRecibido;
    private int puerto;
    
    public ThreadClienteSc(Socket socket,int Id,int puerto){       
       this.id = id;            
       this.puerto = puerto;
       this.so = socket;
    }
    
    @Override
    public void run(){
        try {
                System.out.println("cliente lanzado:" + id + " puerto:" + puerto);                
                BufferedReader entrada;
                
                entrada = new BufferedReader(new InputStreamReader(so.getInputStream()));
                mensajeRecibido = entrada.readLine();                                
                
                System.out.println("recibido:" + mensajeRecibido);
                
                salida = new DataOutputStream(so.getOutputStream());
                System.out.println("Confirmando conexion al cliente....");                
                salida.writeUTF("Se recibio tu mensaje.n Terminando conexion..." + id + "\n");                
                
                
                System.out.println("Cerrando conexión..." + id);                
        } catch (IOException ex) {
            System.out.println("error hilo cliente :" + id + ex.toString());
        }

    }
    
}

Al correar la aplicación deberá aparecer la siguiente pantalla:

EN ANDROID:

Diseño aplicació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=".MainActivity" >

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true"
        android:layout_marginTop="21dp"
        android:text="Conexión" />

</RelativeLayout>

clase MainActivity.java:

package com.example.sockets;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btnSync = (Button) findViewById(R.id.button1);
btnSync.setOnClickListener(new OnClickListener() {

            public void onClick(View view) {
            
              System.out.println("iniciando conexion al server.... pba01"); 
              
              Intent cliente = new Intent (MainActivity.this, Cliente.class);
              
              startService(cliente);
            
           }

       });
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

}

clase Cliente.java:
package com.example.sockets;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.Socket;

import android.app.IntentService;
import android.content.Intent;

public class Cliente extends IntentService  {
Socket sc;
public Cliente(){
super("IntentServiceOperacion");
}
protected void onHandleIntent(Intent intent){
        try {
            BufferedReader entrada;
            System.out.println("Conectar por puerto:"  );

            //En esta parte entra en CMD y escribe ipconfig para encontrar la ip de tú PC           
            //la ip siempre deberá de ser STRING

            sc = new Socket("X.X.X.X" , 5001 );                 
            
            sc.setSoTimeout(10000);
            
            if(sc.isConnected()){
                System.out.println("Confirmando conexion al server....");            
                DataOutputStream mensaje = new DataOutputStream(sc.getOutputStream());
                mensaje.writeUTF("ID : 1 | android\n");           

                entrada = new BufferedReader(new InputStreamReader(sc.getInputStream()));

                String mensajeRecibido = entrada.readLine();
                System.out.println(mensajeRecibido);     
                
                 
                System.out.println("fin conexion al server....");
                sc.close();
                                
            }    
                       
        } catch (Exception ex) {
            System.out.println("Error al conectar cliente" + ex.toString());
        }finally{
           if(sc!=null){
                try {
                    sc.close();
                } catch (Exception ex) {
                    System.out.println("Error al cerrar el socket");
                }
           }
        }  
}   
}
clase AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.sockets"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />
 <uses-permission 
    android:name="android.permission.ACCESS_NETWORK_STATE" /> 

<uses-permission 
    android:name="android.permission.ACCESS_WIFI_STATE" /> 

<uses-permission 
    android:name="android.permission.INTERNET" /> 

<uses-permission 
    android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" /> 
    
    
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        
        <service android:name="com.example.sockets.Cliente"></service>        
        <activity
            android:name="com.example.sockets.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>
    </application>

</manifest>

Al correar la aplicación dentro de un dispositivo android deberá aparecer la siguiente pantalla:


Y al presionar la pantalla deberá de aparecer lo siguiente dentro del aplicativo en java, el cual debimos de ejecutar antes de seleccionar el boton conexión en el dispositivo android:



Nota: Si presentan un error con el puerto 5001, tendrán que desactivar su FIREWALL para que se pueda generar la conexión.

Por: Alejandro Bautista Mancilla y Jhonatan Becerril Bautista


Fuentes:

No hay comentarios:

Publicar un comentario