Modificando `wardrive-android`

Bueno, pues aquí estamos, reestrenando blog :D

La aplicación Wardrive de android es una excelente herramienta para mapear redes con el móvil, que además está liberada bajo la licencia GNU GPLv3, en este post veremos como añadirle la opción de enviar la base de datos a un servidor web remoto.

Captura de la aplicación tomada del_repositorio

Lo primero que tenemos que hacer es descargar el código fuente, con svn checkout http://wardrive-android.googlecode.com/svn/trunk/ wardrive- android-read-only

Una vez hecho esto, lo abrimos con el IDE que prefiramos ( no me pararé a explicar como instalar los complementos para desarrollar para Android, se puede encontrar con una simple búsqueda ).

En el caso de NetBeans nos notificará que hay un problema, si hacemos click con el botón derecho en el proyecto y pulsamos en "Resolver problemas de referencia", dirá que '"Android_gapi_1.6" platform not found'. Si pulsamos en el botón resolver abrirá el gestor de plataformas, así que solo tenemos que seleccionar "Add platform".

El tipo de plataforma a instalar será "Google android ..."

A continuación tendremos que seleccionar la ruta al SDK

Y por último darle un nombre, "Android_gapi_1.6", y seleccionar la plataforma objetivo.

Una vez solucionados los problemas con el IDE, si no existe hay que crear un Dispositivo Android Virtual que incluya las API de Google, utilizadas para mostrar los mapas.

Ahora toca liarse con el código...

Primero añadiremos la opción de enviar los datos a la lista de opciones que se accede a través del Menú > More. Este menú se encuentra en el archivo options_menu.xml, en el directorio /res/menu , debajo de la siguiente línea añadimos la misma modificada para nuestra opción:

El archivo quedaría por ejemplo así:

<item android:id="@+menu_id/SERVICE" android:title="@string/MENU_SERVICE_LABEL"

android:icon="@drawable/ic_menu_manage" />

<item android:id="@+menu_id/LIST" android:title="@string/MENU_LIST_LABEL"

android:icon="@drawable/ic_menu_mylocation" />

<item android:id="@+menu_id/STATS" android:title="@string/MENU_STATS_LABEL"

android:icon="@drawable/ic_menu_view" />

<item android:id="@+menu_id/PREFERENCES" android:title="@string/ MENU_OPTIONS_LABEL"

android:icon="@drawable/ic_menu_preferences" />

<item android:id="@+menu_id/QUIT" android:title="@string/MENU_QUIT_LABEL"

android:icon="@drawable/ic_menu_close_clear_cancel" />

<item android:id="@+menu_id/KML_EXPORT" android:title="@string/ MENU_KML_EXPORT_LABEL"

android:icon="@drawable/ic_menu_save">

<item android:id="@+menu_id/DELETE" android:title="@string/MENU_DELETE_LABEL" /

Además habría que añadir la cadena que tendría en cada idioma a los archivos string.xml, aunque con añadirlo a la que se muestra por defecto es suficiente en las pruebas dio problemas al añadirlo solo por defecto, aquí se explica el paso para ponerlo en inglés. Podemos encontrar los valores en el directorio /res/values-/ , buscamos la línea que contenga MENU_SEND_TO_WIGLE, y la copiamos modificando los valores necesarios, es decir, añadimos esta línea: Send wardrive.kml to server

Hecho esto, ya se muestra la opción, aunque lo único que hace es mostrar el 'about':

Lo que queda por cambiar es la acción que se toma al pulsar el botón, esto se define en el case de la función onOptionsItemSelecteddel archivomain.java, bajo este switch: switch (item.getItemId())

Añadimos nuestro case: case R.menu_id.SEND_TO_SERVER:

showDialog(Constants.DIALOG_SERVER_UPLOAD);

break;

Bien, vamos entonces con el diálogo, al switch de la función protected Dialog onCreateDialog(int id) (~línea 625 ), hay que añadirle un nuevo case que tome la URL y nos la pase a una función para manejarla: case Constants.DIALOG_SERVER_UPLOAD:

builder = new AlertDialog.Builder(this);

final EditText URIinput = new EditText(this);

URIinput.setText("");

builder.setView(URIinput);

builder.setPositiveButton(getString(R.string.OK), new DialogInterface.OnClickListener() {

   public void onClick(DialogInterface dialog, int whichButton) {

       String uri = URIinput.getText().toString().trim();

       send_to_server(uri);

   }

});

builder.setNegativeButton(getString(R.string.NO),

           new DialogInterface.OnClickListener() {



   public void onClick(DialogInterface dialog, int whichButton) {

       send_to_server(null);

   }

});

return builder.create();

Lógicamente hay que añadir un valor DIALOG_SERVER_UPLOAD a la clase Constants en Constants.java, como public static final int DIALOG_SERVER_UPLOAD = DIALOG_WIGLE_UPLOAD + 1;

Además hay que importar android.widget.EditText, que se utiliza en el Dialog.

Todo lo que queda por escribir es la función send_to_server(), que hace return si el string es null o envía el archivo a la url en un POST multipart, nombrandolo como 'wardrive'.
public void send_to_server(String url){

       if(url == null){

           return;

       }

       HttpClient httpclient = new DefaultHttpClient();

       HttpPost httppost = new HttpPost(url);



       File f = new File("/sdcard/wardrive.kml");

       try {

         MultipartEntity entity = new MultipartEntity();



         entity.addPart("wardrive", new FileBody(f));

         httppost.setEntity(entity);

         httpclient.execute(httppost);

       } catch (Exception e) {

       }

   }

Para esta función se requiere tener los .jar apache-mime4j, httpmime, httpclient y httpcore en el directorio de compilación e importar esto: import android.widget.EditText;

import org.apache.http.client.HttpClient;

import org.apache.http.impl.client.DefaultHttpClient;

import org.apache.http.client.methods.HttpPost;

import org.apache.http.entity.mime.MultipartEntity;

import org.apache.http.entity.mime.content.FileBody;

Nota: lógicamente hay que exportar el KML antes de enviarlo al servidor

El código fuente resultante: wardrive-mod.zip

Y compilado: wardrive.apk

Y eso es todo, nos vemos. [Referencias] http://code.google.com/p/wardrive-android/ http://www.softwarepassion.com/android-series-get-post-and-multipart-post- requests/ https://code.google.com/p/androidmcr/source/browse/trunk/MCR/apache-mime4j- 0.6.jar?r=85 https://code.google.com/p/google-secure-data-connector/source/browse/trunk/ data-connector-agent/third-party/httpcomponents-client-4.0.1/httpmime- 4.0.1.jar?r=525

untagged

Como hacer las imagenes que ponen ip, navegador... » « Monitoreando la IP pública