You are on page 1of 15

Comunicación entre Ordenador y dispositivo And...

http://androidesverdesfritos.wordpress.com/2013...

Androides Verdes Fritos
Todo lo que querías saber sobre Android y no te atreviste a preguntar

Comunicación entre Ordenador y dispositivo
Android mediante el USB
mayo 30, 2013
Bueno, bueno, bueno. Hoy vamos a hacer una aplicación complicada. Trata servidor, cliente, servicios,
sockets, timer, programación concurrente y un poco de ingenio. Así que abrochaos los cinturones que la
nave va a despegar.
Advertencia: Este tutorial es largo. Pero a mí me ha encantado hacerlo.
Vamos a empezar por la aplicación de escritorio que he realizado en JAVA puro y duro. Pero lo podéis
hacer con C, con Python, lo que sea que pueda abrir Socket y llamar a un programa de consola.
Para los que no sepan una buena definición de qué es un socket, voy a dejar el link de la Wiki que lo
explica, no en mucha profundidad pero servirá: http://es.wikipedia.org/wiki/Socket_de_Internet
(http://es.wikipedia.org/wiki/Socket_de_Internet). Una definición rápida y entendible sería algo como:
un socket es un canal de comunicación entre dispositivos y es tratado como si fueran ficheros en los que
se escribe o se lee. Este es un esquema de cómo trabajan los socket:

1 de 15

16/10/14 10:31

Cambiando mi método de pensamiento.wordpress.. ya fueran de escritura o de lectura. es el dispositivo el que debe ser el Server Socket.files. eso es solo la punta del iceberg.png) En un primero momento pensé que lo más lógico sería que una aplicación de escritorio que fuera El servidor que estuviera todo el rato escuchando y que contestara a las peticiones que el dispositivo hiciera. http://androidesverdesfritos. Pero es el caso de Android..com/2013/05/socket_1. Lo divertido fue hasta que encontré que hay que abrir un puerto TCP de comunicación mediante el uso del adb.com/2013. (http://androidesverdesfritos..wordpress.. Adb es 2 de 15 16/10/14 10:31 una aplicación que proporciona el sdk de Android para comunicación por medio de comandos desde el .Comunicación entre Ordenador y dispositivo And.

png) El código de la activación del puerto TCP por medio de JAVA sería: 3 de 15 16/10/14 10:31 .exe.com/2013/05/socket_2.wordpress. Esta aplicación se descarga en el sdk. El comando es: <ruta_adb>\adb. (http://androidesverdesfritos.. Se utiliza por ejemplo para abrir un Shell del dispositivo y manejarlo desde nuestro ordenador.com/2013.Comunicación entre Ordenador y dispositivo And.wordpress.. integrarlo en la aplicación de escritorio.. La imagen de la aplicación sería la siguiente.exe forward tcp:Puerto_elegido tcp: Puerto_elegido Esto se puede hacer mediante la línea de comandos o. http://androidesverdesfritos.files. ordenador al pc. Normalmente se encuentra en: <ruta_sdk>\platformtools\adb. Para darle un poco de chicha a la aplicación lo he hecho así..

setText("Todo ha salido bien\n").getRuntime(). 0. } error += ":: No se puede abrir el puente de comunicacion\n" log. try { log.Comunicación entre Ordenador y dispositivo And.hasNext()) { // Encadenamos todo el mensaje error += sc.setText(e.event.setText(error). private void activatetacpMouseClicked(java.exe forward tcp:38300 tcp:38300"). allok = false. } } } Ahora vamos al envío de los mensajes hacia el terminal Android.exec( "C:\\android\\adb. el localhost.setText("Activando puerto TCP").getMessage()).getErrorStream()). Scanner sc = new Scanner(p. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 4 de 55 15 http://androidesverdesfritos. 16/10/14 10:31 // Liberamos el buffer .length()). // Creamos el buffer dónde vamos a escribir BufferedWriter writer = new BufferedWriter(new OutputStreamWrit // Escribimos en el canal writer. } } catch (Exception e) { log. //En mi Windows.. if (sc. 38 Socket socket = new Socket("localhost".write(mss.wordpress. allok = false. tengo directamente el sdk en c. // Formato que le damos a la fecha private final SimpleDateFormat _dateFormat = new SimpleDateFormat("HH:m private void sendMessage(String mss) { try { // Nos tenemos que conectar a nosotros mismos. while (sc.MouseEvent evt) { boolean allok = true. 38300).. por comodidad Process p = Runtime. // Esta función pertenece al hacer click en el botón de Activar..out. } else { System.println("Ha fallado algún proceso\n"). mss..next() + " ".hasNext()) { String error = "". } finally { if (allok) { log.com/2013.awt.

flush().getMessage()).. el servicio y la creación del log en tiempo real.setText(log.getText() + "Send[" + time + "]" + ":: " + mss } catch (UnknownHostException e) { log.getMessage()). pero mi idea es la comunicación.awt..Comunicación entre Ordenador y dispositivo And.getText()).. así que lo cerramos socket.wordpress. // Creamos la fecha con un formato determinado para incluirlo e String time = _dateFormat.wordpress.setText(log. } // Vaciamos de información la caja del texto txtsend. el proyecto para que la ejecutéis dónde queráis y modifiquéis a vuestro antojo..setText("").getText() + "ERROR:: > " + "Could not initializ + e. // Ya hemos enviado el mensaje. } catch (IOException e) { log. // Encadenamos la fecha log. 56 57 58 59 60 61 62 63 http://androidesverdesfritos. Este es más o menos el esquema de la aplicación.png) (http://androidesverdesfritos. Ahora. Se podría mejorar.event.com/2013/05 Os dejo al final del blog.MouseEvent evt) { sendMessage(txtsend.com/2013.format(new Date()). 5 de 15 16/10/14 10:31 . Está pensado para que funcione cuando tengamos el log en pantalla.setText(log. pongamos más situación. } /socket_3. eso está claro. writer.close(). } // Método que se activa cuando se pulsa el botón enviar private void sendMouseClicked(java. los Socket.getText() + "ERROR:: > " + "Socket connection p + e.files.

. (http://androidesverdesfritos.wordpress.com/2013.wordpress.sgoliver.png) http://androidesverdesfritos.net /blog/?p=1731 (http://www..Comunicación entre Ordenador y dispositivo And.sgoliver.com El código de esa Actividad es: Nota: si queréis información sobre Shared preferences teneís esto: http://www. /2013/05/socket_4..net/blog/?p=1731) 6 de 15 16/10/14 10:31 ..files.

. private Button gotolog.layout.setOnClickListener(new OnClickListener() { 16/10/14 10:31 . cb = (CheckBox) findViewById(R. SharedPreferences.txtlog). // Acceso a la actividad del log gotolog.id.wordpress.checkBox).setOnClickListener(new OnClickListener() @Override public void onClick(View v) { // Creación del intent para ejecutar o finalizar el servicio Intent servicio = new Intent(getApplicationContext()..onCreate(savedInstanceState). getApplicationContext(). if (cb. PutTextInCheckBox().servicio).stopService(servicio).startService(servicio).isChecked()) { Toast. PutTextInCheckBox(). public class ConfigureService extends Activity { private CheckBox cb. Toast. Toast.setChecked(true).LENGTH_SHORT). // Iniciar el checkbox con los datos adecuados if (settings.getBoolean(servicioactivado.makeText(getApplicationContext(). } } }). @Override public void onCreate(Bundle savedInstanceState) { super.com/2013.makeText(getApplicationContext(). gotolog = (Button) findViewById(R..edit(). } else { Toast. MODE_PRIVATE). "Servicio Activado". MyService.show(). "Servicio Desactivado". setContentView(R. cb.Comunicación entre Ordenador y dispositivo And.class). PutTextInCheckBox().setChecked(false). // SharedPreferences para guardar el último estado del checkbox SharedPreferences settings = getSharedPreferences( "Preferencias_Servicio".id. getApplicationContext().Editor editor = settings. else cb. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 7 de 55 15 http://androidesverdesfritos. false)) cb.LENGTH_SHORT). private static final String servicioactivado = "myservicio".show()..

putBoolean(servicioactivado.com/2013.setVisibility(View. if (cb. true). editor... } // No os olvidéis de esto.edit().. gotolog.Editor editor = settings.setVisibility(View. } private void PutTextInCheckBox() { SharedPreferences settings = getSharedPreferences( "Preferencia Servicio". editor.GONE). } } Ahora la clase del servicio: 8 de 15 16/10/14 10:31 .Comunicación entre Ordenador y dispositivo And. gotolog.setText("Activado").setText("Desactivado").. editor.putBoolean(servicioactivado.commit(). 56 57 58 59 60 61 62 63 64 65 66 67 http://androidesverdesfritos. SharedPreferences.VISIBLE).isChecked()) { cb. } }). false).wordpress.class). } else { cb. MyLog. MODE_PRIVATE). @Override public void onClick(View v) { Intent nuevaactividad = new Intent(getApplicationContext(). startActivity(nuevaactividad).

new Thread(initializeConnection). server. } @Override public void onStart(Intent intent.Comunicación entre Ordenador y dispositivo And. startId). @Override public IBinder onBind(Intent arg0) { // TODO Auto-generated method stub return null.com/2013. this.wordpress.bind(new InetSocketAddress(38300)).start().. } @Override public void onDestroy() { // TODO Auto-generated method stub super.iniciarServicio(). while (true) { // Creamos el socket cliente Socket client = server. public static final String TAG = "Mi Servicio". public class MyService extends Service { public static List<String> buffer. while (true) { 16/10/14 10:31 . } private Runnable initializeConnection = new Thread() { public void run() { try { // Creamos un socket servidor.. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 9 de 55 15 http://androidesverdesfritos.accept().onDestroy().. // Detenemos el servicio this.setReuseAddress(true). } public void iniciarServicio() { this.. private Handler mHandler = null. server. int startId) { // TODO Auto-generated method stub // Método para iniciar el servicio super. private ServerSocket server = null. server = new ServerSocket().finalizarServicio().buffer = new ArrayList<String>().onStart(intent.

com/2013.e(TAG.close().. } } // Cerramos el cliente client.add(linea).. // Si la línea tiene información guardamos. / compartido con otra actividad buffer.getMessage()).getStackTrace() + " " + e.toString()).getMessage()). "" + e. 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 http://androidesverdesfritos.getLocalizedMessage() + " " + e. "error: " + e. e.. y más claro veo String linea = reader.Comunicación entre Ordenador y dispositivo And. } catch (IOException e) { Log.readLine().close(). "Cannot close server socket" + ec). // La lectura de línea se puede hacer de varias formas // Esta es la que más me gusta. } } }.getInputStream())). 16/10/14 10:31 .. // Recogemos el buffer de lectura del cliente BufferedReader reader = new BufferedReader( new InputStreamReader(client. sino salimos // del bucle if (linea != null) { // Sincronizamos la variable para que no la escriba ot // proceso mientras nosotros recogemos. 10 de 15 public void finalizarServicio() { try { if (server != null) // Cerramos el socket servidor server. } catch (Exception e) { Log. } } catch (SocketTimeoutException e) { Log. synchronized (buffer) { // Añadimos la línea al buffer que hemos creado.e(TAG.e(TAG.e(TAG.wordpress. } catch (IOException ec) { Log. } } else { break.

. deberá aparecer cada vez que escribamos algo en el log y demos a enviar la hora de recepción y el mensaje.Comunicación entre Ordenador y dispositivo And.com/2013.example.png) Ahora el código de la Actividad: 11 de 15 16/10/14 10:31 ...appandroid.. Uno lo recoge del ordenador y otro del propio Android. (http://androidesverdesfritos. } http://androidesverdesfritos.files. Por cierto. Pero doy fe que se reciben tal cual.MyService" ></service> En la actividad del log.wordpress. } } Hay que modificar el manifest.com/2013/05/socket_5.xml: 1 <service android:name="com. las horas son diferentes por los relojes diferentes del sistema.wordpress.

scheduleAtFixedRate(new TimerTask() { @Override public void run() { MyLog.txtlog). setContentView(R. } protected void onDestroy() { super. @Override protected void onCreate(Bundle savedInstanceState) { super..id. } @Override public void onPause() { super.com/2013.onCreate(savedInstanceState). tv = (TextView) findViewById(R.onDestroy(). @SuppressLint("SimpleDateFormat") // Para dar formato a la fecha private final SimpleDateFormat formatofecha = new SimpleDateFormat("HH:m // Crear un timer es una forma simple para crear un log en tiempo real private Timer mitimer = null.wordpress.. mitimer = new Timer(). 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 12 de 5515 http://androidesverdesfritos. mitimer..layout.. } private void startTimer() { stopTimer().onResume().this. public class MyLog extends Activity { private TextView tv. } @Override public void onResume() { super. stopTimer(). stopTimer().onPause().runOnUiThread(new Runnable() { public void run() { 16/10/14 10:31 .activity_my_log). startTimer().Comunicación entre Ordenador y dispositivo And.

mitimer = null.size() > 0) { for (int i = 0. new Date().format(new Date()).buffer. } } } }). tv. El manifest completo sería: 13 de 15 16/10/14 10:31 . } // Eliminamos todo lo leído MyService.Comunicación entre Ordenador y dispositivo And.setText(tv. } private void stopTimer() { if (mitimer != null) { mitimer. } } } Por cierto no os olvidéis de registrar la actividad del log y dar acceso a internet..com/2013.cancel(). i < MyService. 56 57 58 59 60 61 62 63 64 65 66 67 68 http://androidesverdesfritos.. synchronized (MyService. 333).size().buffer) { if (MyService. } }. time += formatofecha.clear(). i++) { String time = "".buffer.buffer.buffer.wordpress. // Sincronizamos la variable para que no la escriba otro // proceso mientras nosotros recogemos...getText() + "\n" + ">> " + time + ":: " + MyService.get(i)).

example. From → Android Dejar un comentario Blog de WordPress.com. lo siguiente: (https://www. 14 de 15 16/10/14 10:31 .MAIN" /> <category android:name="android. – El proyecto Eclipse de la aplicación Android.com/s/vuwrmjuy0o3k5v3/Socket. | El tema Titan.dropbox.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.action.ConfigureService" android:label="@string/app_name" android:launchMode="singleTask" > <intent-filter> <action android:name="android.example.intent.com/2013.category.wordpress..permission.android.appandroid" android:versionCode="1" android:versionName="1.Comunicación entre Ordenador y dispositivo And.com/apk/res/android (http:/ package="com.example. <?xml version="1..example.intent.appandroid.appandroid..MyLog" android:label="@string/title_activity_my_log" > </activity> </application> </manifest> Os dejo en un rar.LAUNCHER" </intent-filter> </activity> <service android:name="com.INTERNET" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 http://androidesverdesfritos.MyService" > </service> <activity android:name="com.appandroid.rar) – El proyecto NetBeans de la aplicación cliente.0" > <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="10" /> <uses-permission android:name="android..

Seguir “Androides Verdes Fritos” Ofrecido por WordPress.com 15 de 15 16/10/14 10:31 . Seguir http://androidesverdesfritos.com/2013..wordpress..Comunicación entre Ordenador y dispositivo And...