Error importing csv files from FTP into the application

1

I'm creating an application and I'm trying to import some csv files that are on ftp into the android.

Then I have hers as follows:

InSpinnerwilllistallthefilespresentinthe"import" folder that is inside my FTP.

But when this listing is going to make the error occurs, let's go to the codes:

class ImportsFTPActivity:

package realsysten.com.br.sigarestaurante;

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.app.ProgressDialog;
import android.os.Bundle;

import java.io.File;
import java.util.ArrayList;

import org.apache.commons.net.ftp.FTPFile;

import android.os.Environment;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;

/**
 * Created by Vitor on 14/06/2016.
 */
public class importaFtpActivity extends AppCompatActivity {

    Spinner spImport;
    ArrayList<String> arquivosFTP = new ArrayList<String>();
    ProgressDialog dialog;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.importa_ftp);

        spImport = (Spinner) findViewById(R.id.spImport);
        ImportItens();

        Button b2 = (Button) findViewById(R.id.btnImpInfos);
        b2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dialog = ProgressDialog.show(importaFtpActivity.this, "FTP",
                        "Sincrozinzando dados...", false, true);
                dialog.setCancelable(false);

                ChamaImport();
            }
        });

        Button biv = (Button) findViewById(R.id.btnVoltar);
        biv.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent i = new Intent(importaFtpActivity.this, OpcoesActivity.class);
                startActivity(i);
                finish();
            }
        });
    }

    public void ImportItens() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                listarArquivosFTP();
            }
        }).start();
    }

    public void ChamaImport() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                efetuarDownload();
                dialog.dismiss();
            }
        }).start();
    }

    public void listarArquivosFTP() {
        FTPController ftp = new FTPController();
        ftp.conectar("192.168.2.5", "vitor", "248693751qQ", 21);
        ftp.mudarDiretorio("/import");
        FTPFile[] arquivos = ftp.dir("/import");
        if (arquivos != null) {
            int lenght = arquivos.length;
            for (int i = 0; i < lenght; i++) {
                FTPFile f = arquivos[i];
                if (f.isFile()) {
                    arquivosFTP.add(f.getName());

                }
            }
            ArrayAdapter<String> arraAdapter = new ArrayAdapter<String>(this,
                    android.R.layout.simple_dropdown_item_1line, arquivosFTP);
            spImport.setAdapter(arraAdapter);
        }
    }

    public void efetuarDownload() {
        String lstrArq = "";
        try {
            FTPController ftp = new FTPController();
            lstrArq = "/" + spImport.getSelectedItem().toString();
            File lArquivos = new File(Environment.getExternalStorageDirectory(), lstrArq);

            if (!lArquivos.exists()) {
                lArquivos.mkdir();
            }
            ftp.conectar("192.168.2.5", "vitor", "248693751qQ", 21);

            ftp.download("/Import", spImport.getSelectedItem().toString(), lArquivos.toString());
        } catch (Exception e) {
            e.getStackTrace();
        }
    }
}

FTPController class:

package realsysten.com.br.sigarestaurante;

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

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 android.os.Environment;
import android.util.Log;

/**
 * Created by Vitor on 14/06/2016.
 */
public class FTPController{

    FTPClient mFTP;
    private String TAG = "classeFTP";

    public FTPFile[] dir(String diretorio) {
        try {
            FTPFile[] ftpFiles = mFTP.listFiles(diretorio);
            return ftpFiles;
        } catch (Exception e) {
            Log.e(TAG, "Erro: não foi possivel listar os arquivos e pastas do diretorio " +
                    diretorio + " . " + e.getMessage());
        }
        return null;
    }

    public boolean mudarDiretorio(String diretorio) {
        try {
            mFTP.changeWorkingDirectory(diretorio);
        } catch (Exception e) {
            Log.e(TAG, "Erro: não foi possivel mudar o diretorio para " + diretorio);
        }

        return false;
    }

    public boolean desconecta() {
        try {
            mFTP.disconnect();
            mFTP = null;
            return true;
        } catch (Exception e) {
            Log.e(TAG, "Erro: ao desconectar. " + e.getMessage());
        }
        return false;
    }

    public boolean conectar(String host, String usuario, String senha, int porta){
        try {
            mFTP = new FTPClient();
            mFTP.connect(host, porta);
            if (FTPReply.isPositiveCompletion(mFTP.getReplyCode())) {
                boolean status = mFTP.login(usuario, senha);

                mFTP.setFileType(FTP.BINARY_FILE_TYPE);
                mFTP.enterLocalPassiveMode();

                return status;
            }
        } catch (Exception e) {
            Log.e(TAG, "ERRO: não foi possivel conectar " + host);
        }
        return false;
    }

    public boolean download(String diretorioOrigem, String arqOrigem, String arqDestino) {
        boolean status = false;

        try {
            mudarDiretorio(diretorioOrigem);
            FileOutputStream desFileStream = new FileOutputStream(arqDestino);
            mFTP.setFileType(FTP.BINARY_FILE_TYPE);
            mFTP.enterLocalActiveMode();

            status = mFTP.retrieveFile(arqOrigem, desFileStream);
            desFileStream.close();
            desconecta();
            return status;
        } catch (Exception e) {
            Log.e(TAG, "Erro: Falha ao efetuar download. " + e.getMessage());
        }
        return status;
    }

    public boolean upload(String diretorio, String nomeArquivo) {
        boolean status = false;
        try {
            FileInputStream arqEnviar = new FileInputStream(Environment.getExternalStorageDirectory() + diretorio);
            mFTP.setFileTransferMode(FTPClient.STREAM_TRANSFER_MODE);
            mFTP.setFileType(FTPClient.STREAM_TRANSFER_MODE);
            mFTP.storeFile(nomeArquivo, arqEnviar);
            desconecta();
            return status;
        } catch (Exception e) {
            Log.e(TAG, "Erro: falha ao efetuar upload. " + e.getMessage());
        }
        return status;
    }
}

When the application executes ImportItens(); that is in method onCreate of class ImportFTP , it does all the right execution, ftp.conectar , ftp.mudarDiretorio , ftp.dir , but when it arrives in spImport.setAdapter(arraAdapter); the following error occurs:

error:

  

06-15 12: 19: 47.433 31113-31623 / realsysten.com.br.sigarestaurante E / AndroidRuntime: FATAL EXCEPTION: Thread-321                                                                                          Process: realsysten.com.br.sigarestaurante, PID: 31113                                                                                          android.view.ViewRootImpl $ CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.                                                                                              at android.view.ViewRootImpl.checkThread (ViewRootImpl.java:6556)                                                                                              at android.view.ViewRootImpl.focusableViewAvailable (ViewRootImpl.java:3034)                                                                                              at android.view.ViewGroup.focusableViewAvailable (ViewGroup.java:761)                                                                                              at android.view.ViewGroup.focusableViewAvailable (ViewGroup.java:761)                                                                                              at android.view.ViewGroup.focusableViewAvailable (ViewGroup.java:761)                                                                                              at android.view.ViewGroup.focusableViewAvailable (ViewGroup.java:761)                                                                                              at android.view.ViewGroup.focusableViewAvailable (ViewGroup.java:761)                                                                                              at android.view.ViewGroup.focusableViewAvailable (ViewGroup.java:761)                                                                                              at android.view.View.setFlags (View.java:10555)                                                                                              at android.view.View.setFocusable (View.java:7481)                                                                                              at android.widget.AdapterView.checkFocus (AdapterView.java:738)                                                                                              at android.widget.AbsSpinner.setAdapter (AbsSpinner.java:116)                                                                                              at android.widget.Spinner.setAdapter (Spinner.java:508)                                                                                              at android.support.v7.widget.AppCompatSpinner.setAdapter (AppCompatSpinner.java:391)                                                                                              at realsysten.com.br.sigarestaurante.importaFtpActivity.listarFTP files (importaFtpActivity.java:97)                                                                                              at realsysten.com.sigarestaurante.importaFtpActivity $ 3.run (importaFtpActivity.java:66)                                                                                              at java.lang.Thread.run (Thread.java:818)

    
asked by anonymous 15.06.2016 / 14:38

2 answers

2

Now, what happens is that you are trying to update the screen from a different thread from the person responsible for managing the components (the thread responsible for this is UIThread ).

Your listarArquivosFTP method tries to refresh the screen, on the spImport.setAdapter(arraAdapter) line, and it is called within a new thread from ImportItens . So you have this exception thrown.

public void ImportItens() {
    new Thread(new Runnable() {
        @Override
        public void run() {
            listarArquivosFTP();
        }
    }).start();
}

.    .    .

public void listarArquivosFTP() {
    FTPController ftp = new FTPController();
    ftp.conectar("192.168.2.5", "vitor", "248693751qQ", 21);
    ftp.mudarDiretorio("/import");
    FTPFile[] arquivos = ftp.dir("/import");
    if (arquivos != null) {
        int lenght = arquivos.length;
        for (int i = 0; i < lenght; i++) {
            FTPFile f = arquivos[i];
            if (f.isFile()) {
                arquivosFTP.add(f.getName());

            }
        }
        ArrayAdapter<String> arraAdapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_dropdown_item_1line, arquivosFTP);

        spImport.setAdapter(arraAdapter);

    }
}

There are some alternatives to work around this, and one of them is using runOnUiThread method. This method will execute your content directly in the UIThread.

Here's what your code looks like:

public void listarArquivosFTP() {
    FTPController ftp = new FTPController();
    ftp.conectar("192.168.2.5", "vitor", "248693751qQ", 21);
    ftp.mudarDiretorio("/import");
    FTPFile[] arquivos = ftp.dir("/import");
    if (arquivos != null) {
        int lenght = arquivos.length;
        for (int i = 0; i < lenght; i++) {
            FTPFile f = arquivos[i];
            if (f.isFile()) {
                arquivosFTP.add(f.getName());

            }
        }
        ArrayAdapter<String> arraAdapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_dropdown_item_1line, arquivosFTP);

        runOnUiThread(new Runnable() {
            @Override
            public void run() {
               spImport.setAdapter(arraAdapter);
            }
        });
    }
}
    
15.06.2016 / 15:01
2

This is because you are trying to change your spinner from within the thread in your ImportItens() method, consider using AsyncTask for this, in the onPostExecute() method you can change your spinner after running doInBackground() .

But you can also change your ImportarItens method to:

    public void ImportItens() {

        suaActivity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                   //aqui seu código
                   listarArquivosFTP();     
                }
        });
    }
    
15.06.2016 / 14:58