Conexión FTP para Android Studio

Programando una app en Android, no he encontrado ningún sitio en Español que contara como podemos hacer una conexión FTP desde nuestra aplicación Android. El proyecto que estoy desarrollando requiere de la lectura de un archivo ubicado en un servidor FTP. Se debe por tanto descargar, procesar, y meter en la base de datos SQLite para que el operario pueda trabajar con la APP. La información original está en la web The App Guruz. Puedes descargar el código fuente de su página (link) o de la mía (Android–How-to-start-FTP-in-Android-Demo-Project-master).

Vamos al meollo de la cuestión.

Pasos:

  1. Descargar los archivos .jar
  2. Clase con las funciones básicas para funcionar
  3. Conectarse al FTP
  4. Añadir permisos para conectarse a Internet

1. Descarga de los archivos .jar

Primero de todo descargamos los archivos .jar necesarios para usar la clase FTPClient. Se pueden encontrar en la siguiente url:

http://commons.apache.org/proper/commons-net/download_net.cgi

En mi caso, he descargado el archivo commons-net-3.6-bin.zip. Lo he extraído, y he sacado el archivo que nos interesa: commons-net-3.6.jar.

Añade este archivo a la carpeta libs del proyecto. Navega hasta la ubicación del archivo y pulsando el botón derecho pulsa en “Add as Library”. Con esto ya tienes las librerías necesarias para poder hacer conexiones FTP.

2. Clase con las funciones básicas para funcionar

A continuación creamos una clase para gestionar la conexión al FTP. En mi caso la he llamado MyFTPClientFunctions.

package es.muley.albada;

import android.content.Context;
import android.util.Log;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;

import java.io.FileInputStream;
import java.io.FileOutputStream;

/**
 * Created by Lucas on 16/04/2017.
 */

public class MyFTPClientFunctions {

    // Now, declare a public FTP client object.

    private static final String TAG = "MyFTPClientFunctions";
    public FTPClient mFTPClient = null;

    // Method to connect to FTP server:
    public boolean ftpConnect(String host, String username, String password,
                              int port) {
        try {
            mFTPClient = new FTPClient();
            // connecting to the host
            mFTPClient.connect(host, port);

            // now check the reply code, if positive mean connection success
            if (FTPReply.isPositiveCompletion(mFTPClient.getReplyCode())) {
                // login using username & password
                boolean status = mFTPClient.login(username, password);

            /*
             * Set File Transfer Mode
             *
             * To avoid corruption issue you must specified a correct
             * transfer mode, such as ASCII_FILE_TYPE, BINARY_FILE_TYPE,
             * EBCDIC_FILE_TYPE .etc. Here, I use BINARY_FILE_TYPE for
             * transferring text, image, and compressed files.
             */
                mFTPClient.setFileType(FTP.BINARY_FILE_TYPE);
                mFTPClient.enterLocalPassiveMode();

                return status;
            }
        } catch (Exception e) {
            Log.d(TAG, "Error: could not connect to host " + host);
        }

        return false;
    }

    // Method to disconnect from FTP server:

    public boolean ftpDisconnect() {
        try {
            mFTPClient.logout();
            mFTPClient.disconnect();
            return true;
        } catch (Exception e) {
            Log.d(TAG, "Error occurred while disconnecting from ftp server.");
        }

        return false;
    }

    // Method to get current working directory:

    public String ftpGetCurrentWorkingDirectory() {
        try {
            String workingDir = mFTPClient.printWorkingDirectory();
            return workingDir;
        } catch (Exception e) {
            Log.d(TAG, "Error: could not get current working directory.");
        }

        return null;
    }

    // Method to change working directory:

    public boolean ftpChangeDirectory(String directory_path) {
        try {
            mFTPClient.changeWorkingDirectory(directory_path);
        } catch (Exception e) {
            Log.d(TAG, "Error: could not change directory to " + directory_path);
        }

        return false;
    }

    // Method to list all files in a directory:

    public String[] ftpPrintFilesList(String dir_path) {
        String[] fileList = null;
        try {
            FTPFile[] ftpFiles = mFTPClient.listFiles(dir_path);
            int length = ftpFiles.length;
            fileList = new String[length];
            for (int i = 0; i < length; i++) {
                String name = ftpFiles[i].getName();
                boolean isFile = ftpFiles[i].isFile();

                if (isFile) {
                    fileList[i] = "File :: " + name;
                    Log.i(TAG, "File : " + name);
                } else {
                    fileList[i] = "Directory :: " + name;
                    Log.i(TAG, "Directory : " + name);
                }
            }
            return fileList;
        } catch (Exception e) {
            e.printStackTrace();
            return fileList;
        }
    }

    // Method to create new directory:

    public boolean ftpMakeDirectory(String new_dir_path) {
        try {
            boolean status = mFTPClient.makeDirectory(new_dir_path);
            return status;
        } catch (Exception e) {
            Log.d(TAG, "Error: could not create new directory named "
                    + new_dir_path);
        }

        return false;
    }

    // Method to delete/remove a directory:

    public boolean ftpRemoveDirectory(String dir_path) {
        try {
            boolean status = mFTPClient.removeDirectory(dir_path);
            return status;
        } catch (Exception e) {
            Log.d(TAG, "Error: could not remove directory named " + dir_path);
        }

        return false;
    }

    // Method to delete a file:

    public boolean ftpRemoveFile(String filePath) {
        try {
            boolean status = mFTPClient.deleteFile(filePath);
            return status;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return false;
    }

    // Method to rename a file:

    public boolean ftpRenameFile(String from, String to) {
        try {
            boolean status = mFTPClient.rename(from, to);
            return status;
        } catch (Exception e) {
            Log.d(TAG, "Could not rename file: " + from + " to: " + to);
        }

        return false;
    }

    // Method to download a file from FTP server:

    /**
     * mFTPClient: FTP client connection object (see FTP connection example)
     * srcFilePath: path to the source file in FTP server desFilePath: path to
     * the destination file to be saved in sdcard
     */
    public boolean ftpDownload(String srcFilePath, String desFilePath) {
        boolean status = false;
        try {
            FileOutputStream desFileStream = new FileOutputStream(desFilePath);
            ;
            status = mFTPClient.retrieveFile(srcFilePath, desFileStream);
            desFileStream.close();

            return status;
        } catch (Exception e) {
            Log.d(TAG, "download failed");
        }

        return status;
    }

    // Method to upload a file to FTP server:

    /**
     * mFTPClient: FTP client connection object (see FTP connection example)
     * srcFilePath: source file path in sdcard desFileName: file name to be
     * stored in FTP server desDirectory: directory path where the file should
     * be upload to
     */
    public boolean ftpUpload(String srcFilePath, String desFileName,
                             String desDirectory, Context context) {
        boolean status = false;
        try {
            FileInputStream srcFileStream = new FileInputStream(srcFilePath);

            // change working directory to the destination directory
            // if (ftpChangeDirectory(desDirectory)) {
            status = mFTPClient.storeFile(desFileName, srcFileStream);
            // }

            srcFileStream.close();

            return status;
        } catch (Exception e) {
            e.printStackTrace();
            Log.d(TAG, "upload failed: " + e);
        }

        return status;
    }

}

3. Conectarse al FTP

En la aplicación que estoy desarrollando he ubicado en un submenú las dos opciones básicas: conectarnos al FTP, y desconectarnos al FTP. El código es el siguiente:

public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            ////
            case R.id.action_conexionftp:
                //Conexión al FTP
                ftpclient = new MyFTPClientFunctions();
                new Thread(new Runnable() {
                    public void run() {
                        boolean status = false;
                        // host – your FTP address
                        // username & password – for your secured login
                        // 21 default gateway for FTP
                        status = ftpclient.ftpConnect(host, username, password, 21);
                        if (status == true) {
                            Log.d(TAG, "Connection Success");
                        } else {
                            Log.d(TAG, "Connection failed");
                        }
                    }
                }).start();
                return true;
            case R.id.action_desconexionftp:
                //Conexión al FTP
                new Thread(new Runnable() {
                    public void run() {
                        ftpclient.ftpDisconnect();
                    }
                }).start();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

Por separado, el código para conectarse al FTP sería:

new Thread(new Runnable() {
    public void run() {
        boolean status = false;
        // host – your FTP address
        // username & password – for your secured login
        // 21 default gateway for FTP
        status = ftpclient.ftpConnect(host, username, password, 21);
        if (status == true) {
            Log.d(TAG, "Connection Success");    
        } else {
            Log.d(TAG, "Connection failed");
        }
    }
}).start();

Y para desconectarnos:

new Thread(new Runnable() {
    public void run() {
        ftpclient.ftpDisconnect();
    }
}).start();

Usamos Thread para que la acción se realice en segundo plano. Una explicación completa a puedes ver en la maravillosa página de sgoliver.net.

4. Añadir permisos para conectarse a Internet y guardar archivos en la tarjeta de memoria

Debes añadir en el AndroidManifest permisos para conectarse a Internet. Sino la conexión dará un error:

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

En mi caso lo he añadido antes de la etiqueta <application …></application>

Además, también añadimos los permisos para guardar en la tarjeta de memoria:

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

Para guardar en la tarjeta de memoria debemos usar la función

public boolean ftpDownload(String srcFilePath, String desFilePath)

declarada en la clase MyFTPClientFunctions.

 

 

 

 

 

 

 

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *