Olá Amigos do The Club, neste artigo abordarei um assunto interessante
para quem deseja realizar a troca de arquivos do Android para outro sistema
utilizando o protocolo FTP. Para quem não conhece, qual seria o significado da
sigla FTP?
FTP significa
“File Transfer Protocol” que traduzindo
para o português seria: Protocolo de Transferência de Arquivos, é uma forma bastante rápida e versátil de
transferir arquivos, sendo uma das mais usadas na internet.
Nada mais é do
que um sistema de transferência de arquivos cliente/servidor. Isto quer dizer,
que utilizando este protocolo você poderá enviar e receber arquivos do seu
computador (cliente) para o
host (servidor) onde
fica hospedado o seu site, blog, entre outros.
O Sistema
Android, junto com outras bibliotecas nos fornece todo o aparato necessário
para trabalharmos com este tipo de transferência.
Baixando a Biblioteca
Para conciliarmos esta integração do Android junto com tarefas de
transferência de arquivos via FTP deveremos baixar uma biblioteca do Apache no
link a seguir.
Figura 01: Endereço do Site.
Utilizaremos a versão 3.1 que até a data de hoje é a mais estável e
atual. O nome do arquivo baixado deverá ser semelhante a “commons-net-3.1-bin.zip”.
Descompacte-o em uma pasta e observe três arquivos importantes que será
importado mais adiante:
- “commons-net-3.1.jar”
- “commons-net-3.1-sources.jar”
-
“commons-net-examples-3.1.jar”
Importando a Biblioteca
Para
isto abra seu Eclipse e clique em “File/New/Android Project” e crie um projeto
em Android, recomendo a criação na versão 2.2 ou 2.3 utilizando o nome que
desejar. No meu caso criei como “AndroidFTP”. Clique com o botão direito sobre
o mesmo e escolha Propriedades, Ver Figura 02.
Figura 02: Propriedades do Projeto.
“Navegue até o item “Java Build Path” e na aba “Libraries” adicione os
arquivos “.jar” citados anteriormente. Recomendo criar uma pasta no projeto
para uma melhor organização, no meu caso foi criada como “bibliotecas”. Ver
Imagem 03.
Figura 03: Adicionando as bibliotecas necessárias.
Na estrutura do projeto teremos uma “Referenced Libraries”, que nada
mais é do que as bibliotecas adicionadas anteriormente. Ver Imagem 04.
Figura 04: Biblioteca importada com sucesso.
Desenvolvendo um exemplo prático
Dividiremos o exemplo em duas partes, na primeira criaremos uma classe
com os métodos responsáveis por fazer a integração com o FTP e a segunda uma
Atividade para utilizar estes métodos.
- Criando a Classe FTP
Para isto clique com o botão direito e escolha “Add/New/Class” e defina
o nome como “classe_FTP”.
Importe os seguintes pacotes:
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;
Defina duas variáveis globais:
FTPClient mFtp;
String TAG = "classeFTP";
Segue em seguida a classe completa e com os métodos devidamente
comentados para melhores detalhes.
public class classe_FTP
{
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 possível listar os arquivos e pastas do diretório " + Diretorio
+ ". " + e.getMessage());
}
return null;
}
O método “Dir” é responsável por listar os arquivos e diretórios de um
determinado caminho. Tem como parâmetro de entrada uma String “Diretorio”, onde
inserimos o diretório para o qual irá ser listado dos arquivos e como saída uma
variável do tipo FTPFile[] que nada mais é que uma variável idêntica ao tipo File[],
responsável por armazenar o nome dos arquivos/diretórios.
public boolean MudarDiretorio(String Diretorio)
{
try
{
mFtp.changeWorkingDirectory(Diretorio);
}
catch(Exception e)
{
Log.e(TAG, "Erro: não foi possível mudar o diretório para
" + Diretorio);
}
return false;
}
Este método é utilizado quando desejamos utilizar o mesmo diretório
corrente. O método “changeWorkingDirectory()” que realize esta tarefa.
public boolean
Desconectar()
{
try
{
mFtp.disconnect();
mFtp = null;
return true;
}
catch (Exception e)
{
Log.e(TAG, "Erro: ao
desconectar. " + e.getMessage());
}
return false;
}
O método “Desconectar()”, como o próprio nome diz, faz o trabalho de
desconectar ou encerrar a conexão do servidor FTP usando o método “disconnect()”.
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
possível conectar" + Host);
}
return false;
}
Já o método “Conectar()” inicia uma sessão com o servidor FTP, possuindo como parâmetro de entrada o servidor FTP, o usuário, a senha e a porta utilizada. Esta função nos retorna uma variável do tipo booleana para nos certificarmos que a conexão foi efetuada com sucesso.
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()
mFtp.enterLocalPassiveMode();
status = mFtp.retrieveFile(ArqOrigem,
desFileStream);
desFileStream.close();
Desconectar();
return
status;
}
catch (Exception e)
{
Log.e(TAG, "Erro: Falha ao efetuar download. " +
e.getMessage());
}
return status;
}
O método Download recebe os seguintes parâmetros: O diretório de origem,
o arquivo de origem e o de destino. É criada uma variável do tipo
“Outputstream” para o arquivo ser passado como parâmetro, logo em seguida
definimos o tipo de arquivo como “BINARY_FILE_TYPE”. O método mais importante
é o “RetrieveFile” sendo responsável por baixar o arquivo. Após estas etapas
executamos o método Desconectar(). Temos como retorno um booleano que indica se
ocorreu tudo corretamente.
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);
Desconectar();
return status;
}
catch (Exception e)
{
Log.e(TAG, "Erro: Falha ao efetuar Upload. " + e.getMessage());
}
return
status;
}
O método Upload faz o inverso, ou seja, estamos salvando os dados do Android para o Servidor FTP, tendo como parâmetro de entrada o diretório e o nome do arquivo e de saída uma variável do tipo booleana. Foi criado uma variável do tipo “FileInputStream” para armazenar o arquivo a enviar e logo em seguida usamos o “setFileType” e “SetFileTransferMode” para indicar o tipo de transferência de arquivos, que no caso usaremos como “Stream”. Finalmente transferimos o arquivo usando o método “storeFile” seguindo o “Desconectar” .
Todos os métodos implementados anteriormente foi utilizado o bloco de
comandos “Try..Catch” e “Log.e” para nos dar mais detalhes caso exista alguma
falha no decorrer de sua execução.
- Montando o “Lay-Out”
O exemplo utilizará os seguintes componentes:
- 2 Spinners
- 4 TextViews
- 2 Buttons
A Imagem 05 nos dá uma idéia do “Lay-out”.
Figura 05: Sugestão de “Lay-Out”.
O XML correspondente ficou da seguinte maneira:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
>
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:id="@+id/textView4"
android:text="Download
de Arquivos">
</TextView>
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:id="@+id/textView2"
android:text="Lista de Arquivos do FTP:">
</TextView>
<Spinner android:id="@+id/spinner1"
android:layout_width="310dp"
android:layout_height="50dp">
</Spinner>
<Button android:text="Efetuar
Download"
android:id="@+id/Button01"
android:layout_width="140dp"
android:layout_height="wrap_content"
android:onClick="Download_click"
android:layout_gravity="center_horizontal">
</Button>
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:id="@+id/textView5"
android:text="Upload de Arquivos">
</TextView>
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:id="@+id/textView1"
android:text="Lista de Arquivos do Celular:">
</TextView>
<Spinner android:id="@+id/spinner2"
android:layout_width="310dp"
android:layout_height="50dp">
</Spinner>
<Button android:text="Efetuar
Upload"
android:id="@+id/button1"
android:layout_width="140dp"
android:layout_height="wrap_content"
android:onClick="Upload_click"
android:layout_gravity="center_horizontal">
</Button>
</LinearLayout>
- Codificando a Atividade Principal
A atividade será composta de algumas funções para Downloads e Uploads. Usaremos
também “Threads” para indicar o processamento das tarefas. Comentarei o código
a seguir para melhor entendimento.
Utilizaremos as seguintes bibliotecas:
package pct.AndroidFTP;
import android.app.Activity;
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.EditText;
import android.widget.Spinner;
import android.widget.Toast;
public class
AndroidFTPActivity extends Activity
{
Spinner SpnListarArquivosFTP;
ArrayList<String>
ArquivosFTP = new ArrayList<String>();
Spinner
SpnListarArquivosCelular;
ArrayList<String>
ArquivosCelular = new ArrayList<String>();
ProgressDialog dialog;
Estas são as variáveis globais que utilizaremos ao decorrer do
desenvolvimento, o Spinner e o ArrayList serão responsáveis por armazenar os
nomes dos arquivos localizados tanto no celular quanto no servidor FTP.
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
SpnListarArquivosFTP =
(Spinner) findViewById(R.id.spinner1);
SpnListarArquivosCelular =
(Spinner) findViewById(R.id.spinner2);
ListarArquivosdoFTP();
ListarArquivosdoCelular();
}
No evento OnCreate é inicializado os “listeners” SpnListarArquivosFTP e
SpnListarArquivosCelular. Também são invocadas os métodos ListarArquivosFTP() e
ListarArquivosdoCelular() que são respectivamente responsáveis por listar os
arquivos do servidor e do celular.
public void ListarArquivosdoFTP()
{
classe_FTP ClienteFTP = new classe_FTP();
ClienteFTP.Conectar("ftp.teste.com.br",
"the club", "123mudar", 21);
FTPFile[]
arquivos = ClienteFTP.Dir("/thiago");
if(arquivos != null)
{
int length = arquivos.length;
for(int i =
0; i < length; ++i)
{
FTPFile f = arquivos[i];
if(f.isFile())
{
ArquivosFTP.add(f.getName());
}
}
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_dropdown_item_1line,
ArquivosFTP);
SpnListarArquivosFTP.setAdapter(arrayAdapter);
}
}
Método que trás os arquivos que estão localizados no servidor FTP.
Inicialmente instanciamos a “classe_FTP” e usamos o método Conectar(), passando
os seguintes parâmetros:
Usuário: “the club”
Senha: “123mudar”
Porta: 21
Estes mesmos dados serão utilizados posteriormente.
O método “ClienteFTP.Dir()” recebe como parâmetro o nome da pasta que
iremos utilizar para listar os arquivos, no nosso caso utilizei uma chamada
“/thiago” para fins de testes.
Por final faremos um “for” nestes arquivos para adicionarmos no Spinner
(SpnListarArquivosFTP).
public void ListarArquivosdoCelular()
{
File diretorio = new
File("/mnt/sdcard");
File[] arquivos = diretorio.listFiles();
if(arquivos != null)
{
int length =
arquivos.length;
for(int
i = 0; i < length; ++i)
{
File f = arquivos[i];
if(f.isFile())
{
ArquivosCelular.add(f.getName());
}
}
ArrayAdapter<String> arrayAdapter = new
ArrayAdapter<String>(this,android.R.layout.simple_dropdown_item_1line,
ArquivosCelular);
SpnListarArquivosCelular.setAdapter(arrayAdapter);
}
}
Este método é bem parecido com o descrito anteriormente, só que estamos
listando os arquivos que estão localizados dentro do celular ou do tablet. No
caso estamos passando como parâmetro o caminho “/mnt/sdcard” que é o caminho
padrão de armazenamento externo.
public void
Efetuar_Download()
{
String lstrArq = "";
try
{
classe_FTP ClienteFTP
= new classe_FTP();
lstrArq =
"/"+SpnListarArquivosFTP.getSelectedItem().toString();
File lArquivo = new File(Environment.getExternalStorageDirectory(),
lstrArq);
ClienteFTP.Conectar("ftp.teste.com.br", "the club",
"teste123", 21);
ClienteFTP.Download("/thiago",
SpnListarArquivosFTP.getSelectedItem().toString(), lArquivo.toString());
}
catch (Exception e)
{
trace("Erro :
" + e.getMessage());
}
}
O método “Efetuar_Download()” utiliza a classe_FTP. Selecionaremos o
item desejado no “SpnListarArquivosFTP” (Os arquivos que estão no servidor FTP)
e logo em seguida conectando no FTP chamando o método “Download()”. Os
parâmetros são respectivamente: Nome da Pasta, Nome do Arquivo a baixar e Nome
do Arquivo a ser salvo junto com o caminho.
public void
Download_click(View v)
{
dialog = ProgressDialog.show(AndroidFTPActivity.this,"The
Club","Sincronizando Dados . . .", false, true);
dialog.setCancelable(false);
new Thread()
{
public void
run()
{
try
{
Efetuar_Download();
dialog.dismiss();
}
catch
(Exception e)
{
trace("Erro
: " + e.getMessage());
}
}
}.start();
}
Este é o evento do botão “Download()”, onde invocaremos a função criada
no momento anterior. Faremos o uso de Threads para execução de múltiplas
tarefas e para dar uma melhor impressão ao usuário. Usaremos também a classe
“ProgressDialog.Show()” que tem como objetivo mostrar uma mensagem informativa até
o término do processamento desta operação.
public void
Efetuar_Upload()
{
try
{
String lstrArq =
"/"+SpnListarArquivosCelular.getSelectedItem().toString();
classe_FTP ClienteFTP = new classe_FTP();
ClienteFTP.Conectar("ftp.teste.com.br",
"the club", "teste123", 21);
ClienteFTP.Upload(lstrArq, "/thiago"+lstrArq);
}
catch (Exception e)
{
trace("Erro
: " + e.getMessage());
}
}
O método “Efetuar_Upload()” utiliza a classe_FTP. Selecionaremos o item
desejado no “SpnListarArquivosCelular” (Os arquivos que estão no celular) e
logo em seguida conectando no FTP chamando o método “Upload()”. Os parâmetros
são respectivamente: Nome do arquivo que irá fazer o upload e Nome da pasta
onde será salvo o arquivo no servidor FTP.
public void
Upload_click(View v)
{
dialog = ProgressDialog.show(AndroidFTPActivity.this,"The
Club","Sincronizando Dados . . .", false, true);
dialog.setCancelable(false);
new Thread()
{
public void
run()
{
try
{
Efetuar_Upload();
dialog.dismiss();
}
catch(Exception
e)
{
trace("Erro :
" + e.getMessage());
}
}
}.start();
}
Este é o evento do botão “Upload()”, onde invocaremos a função criada no
momento anterior. Faremos novamente o uso de Threads para execução de múltiplas
tarefas e para dar uma melhor impressão ao usuário.
public void toast (String
msg)
{
Toast.makeText
(getApplicationContext(), msg, Toast.LENGTH_SHORT).show ();
}
private void trace (String msg)
{
toast(msg);
}
}
Métodos responsáveis para informar ao usuário de diversas ações que
poderão ocorrer ao longo da execução do aplicativo.
A imagem 06 e a 07 nos dão uma noção básica de como ficou o aplicativo
em funcionamento.
Figura 06: Aplicação em Run-Time.
Figura 07: Aplicativo efetuando Download/Upload de arquivos.
Conclusão
Procurei
neste artigo fazer o uso simplificado e elegante do protocolo FTP, protocolo
específico para transferência de arquivos via internet. Ao decorrer no
desenvolvimento de aplicações existem diversas formas de implementar o uso
deste mecanismo, tais como atualizador automático de executáveis, banco de
dados, geração de scripts etre outros. Fica a critério do programador fazer ou
não o uso desta tecnologia que busca sempre a automatização de tarefas. Com o
Sistema Android isto também se torna possível e fácil, junto com bibliotecas de
terceiros, que neste caso estamos usando a “commons-net” do Apache. Com o
Sistema Android tudo se torna mais flexível pelo fato de ser uma mistura da
linguagem XML com Java possibilitando a resolução de diversas situações.
Fica aí a
dica amigos, Um forte abraço e até o mês que vem!
Nenhum comentário:
Postar um comentário