Update automatico da aplicação

24 respostas
bacoco

Olá estou desenvolvendo uma aplicação java desktop e gostaria de quando o usuario abri-la ela verificar se existe alguma versão mais nova do .jar em um repositorio na rede e baixa-lo e reiniciar a aplicação usando o .jar novo…
Basicamente algo para atualizar automaticamente o aplicativo por um repositorio na rede.

Dei uma pesquisada e o que achei eram pessoas recomendando fazer sistema web ou com repositorios na web…

De que maneiras posso fazer isso? Possuem algum exemplo,tutorial ou algo do genero?
Obrigado

24 Respostas

R

Bom… manualmente voce pode fazer que ao abrir o sistema ele procura no endereço especifico da rede um arquivo XXXX e nesse arquivo resgata a versão e compara com o seu sistema… se for a versão mais recente ele atualiza. Serve?

bacoco

Claro que serve, pode me explicar como faze-lo?

R

Ué… onde ta a dúvida…? Não entendi.

Cria um arquivo ou usa algum que voce ja possui no sistema que possivelmente grava informações como versão por exemplo.

Na rede, defina um local onde vai ficar sempre a ultima versão do programa. Pegue esse endereço (://XX:XX) e configura no seu sistema.

Ao abrir o sistema, ele antes abre um pequeno sisteminha que compara a versão do arquivo do seu sistema e do sistema que está na rede. Se estiver diferente, ele atualiza transferindo os arquivos necessários daquele endereço para o seu sistema. Após atualizado, ele abre o seu sistema.

Qual parte exatamente voce nao sabe fazer?

bacoco

O todo,não sei como fazer o java ir até um caminho na rede e olhar um repositorio, não sei como mandar ele pegar o arquivo e copiar para o PC local e substituir o antigo reiniciando a aplicação…

JuniorMaia

em meu update eu faço o seguinte: crio um arquivo chamado versão.txt, dentro dele eu coloco as seguintes informações: nomeDoArquivo.jar tamanhoEmKb dataDaVersão e versão
exemplo: sistema.jar 4235kb 10/01/2012 4.0.1

no meu sistema eu seto uma variável static contendo a versão atual, exemplo: public static 4.0.0
ao abrir o sistema, baixo o arquivo versão.txt e comparo as versões, por exemplo se o que está no arquivo é != do que está no sistema, baixo o .jar novo

guilherme.dio

JuniorMaia:
em meu update eu faço o seguinte: crio um arquivo chamado versão.txt, dentro dele eu coloco as seguintes informações: nomeDoArquivo.jar tamanhoEmKb dataDaVersão e versão
exemplo: sistema.jar 4235kb 10/01/2012 4.0.1

no meu sistema eu seto uma variável static contendo a versão atual, exemplo: public static 4.0.0
ao abrir o sistema, baixo o arquivo versão.txt e comparo as versões, por exemplo se o que está no arquivo é != do que está no sistema, baixo o .jar novo

Essa é uma boa forma de se fazer, porém acho “desperdício” de memória ao usar uma variável só para guardar a versão.
Eu geralmente uso arquivo properties preso ao jar do sistema, normalmente sigo o padrão maven, e coloco, por exemplo, neste local:

src/main/resources/br/com/ggdio/nomeSistema/versionamento/versao.properties

sergiotaborda

bacoco:
Olá estou desenvolvendo uma aplicação java desktop e gostaria de quando o usuario abri-la ela verificar se existe alguma versão mais nova do .jar em um repositorio na rede e baixa-lo e reiniciar a aplicação usando o .jar novo…
Basicamente algo para atualizar automaticamente o aplicativo por um repositorio na rede.

Dei uma pesquisada e o que achei eram pessoas recomendando fazer sistema web ou com repositorios na web…

De que maneiras posso fazer isso? Possuem algum exemplo,tutorial ou algo do genero?
Obrigado

Existe a tecnologia JWS que faz exactamente essa verificação (entre outras coisas). Contudo, vc precisa de um servidor web central ( um tomcat da vida é suficiente) e prover os jar por lá. Na realidade vc provê um arquivo jnlp que contém um monte de configuração e permite que o usuário instale a aplicação a partir de um link ( e vc pode definir se quer criar atalhos no desktop , qual o icon, etc… ). Esta é a solução provida pela plataforma.

Se vc quiser algo por fora, é bom que vc tenha bons motivos para não usar o jws porque nada disto é trivial.

R

guilherme… acredito que o kra quer algo bem simples pra um sistema desktop… mapear uma classe vai dar um nó na cabeça do kra se ele nao conhecer java web…

faz do jeito que o juniorMaia falou… e acredito que se vc criar um sisteminha simples pra iniciar ANTES do seu programa vc nao precisa reiniciar seu sistema (o que fiz aqui funciona assim…)

agora pra cada coisa q vc falou, tem um lugar diferente no forum explicando… só dar um search ai =p

bacoco

JuniorMaia:
em meu update eu faço o seguinte: crio um arquivo chamado versão.txt, dentro dele eu coloco as seguintes informações: nomeDoArquivo.jar tamanhoEmKb dataDaVersão e versão
exemplo: sistema.jar 4235kb 10/01/2012 4.0.1

no meu sistema eu seto uma variável static contendo a versão atual, exemplo: public static 4.0.0
ao abrir o sistema, baixo o arquivo versão.txt e comparo as versões, por exemplo se o que está no arquivo é != do que está no sistema, baixo o .jar novo

Olá Junior,eu estava pensando em criar uma table no banco e nela colocar dados como versão TOS e outros, e no sistema colocar a versão dentro do properties e depois comparar, se o valor do properties for diferente do valor da tabela ele baixa o novo jar do repositorio…
Meu problema é como fazer isso, como dizer a ele qual repositorio deve ser acessado,como mandar ele pegar o arquivo e substitui-lo pelo existente,entende?

Ivan_Alves

bacoco:
JuniorMaia:
em meu update eu faço o seguinte: crio um arquivo chamado versão.txt, dentro dele eu coloco as seguintes informações: nomeDoArquivo.jar tamanhoEmKb dataDaVersão e versão
exemplo: sistema.jar 4235kb 10/01/2012 4.0.1

no meu sistema eu seto uma variável static contendo a versão atual, exemplo: public static 4.0.0
ao abrir o sistema, baixo o arquivo versão.txt e comparo as versões, por exemplo se o que está no arquivo é != do que está no sistema, baixo o .jar novo

Olá Junior,eu estava pensando em criar uma table no banco e nela colocar dados como versão TOS e outros, e no sistema colocar a versão dentro do properties e depois comparar, se o valor do properties for diferente do valor da tabela ele baixa o novo jar do repositorio…
Meu problema é como fazer isso, como dizer a ele qual repositorio deve ser acessado,como mandar ele pegar o arquivo e substitui-lo pelo existente,entende?

JuniorMaia imprimentei uma atualização automatica só que para uma app em Android onde eu tinha um servidor Java Web, na minha app android eu guardava a versão no arquivo de propriedades(no caso do Android é no AndroidManifest.xml) então no meu servidor web inseri uma tabela no banco contendo dados da ultima versão disponível e o link para download do mesmo. Ao acessar as informações fazia uma comparação de versões se fosse diferentes eu baixava a nova aplicação a partir do link. No seu caso você pode fazer o mesmo e caso essa aplicação tenha pastas que não estão juntos do .jar então você pode compacta-la e extrai-la após fazer o download.

Obs.: Guardava o link para o servidor em uma constante e a aplicação ficava dentro do meu servidor, no banco tinha a url da aplicação que era apenas /atualizacoes/minhaAplicacao.apk ao baixar fazia uma verificação do tipo

if(!urlDaAtualizacao.contains("http://") && !urlDaAtualizacao.contains("https://")){ urlDaAtualizacao = urlDoMeuServidor+urlDaAtualizacao; //juntava as String caso a atualização fosse a partir do meu servidor. } //em seguida fazia o download

Caso você não queira fazer uma aplicação Web para o mesmo pode utilizar também sockets ou algum site que disponibilize tal serviço.

bacoco

Ivan Alves:
bacoco:
JuniorMaia:
em meu update eu faço o seguinte: crio um arquivo chamado versão.txt, dentro dele eu coloco as seguintes informações: nomeDoArquivo.jar tamanhoEmKb dataDaVersão e versão
exemplo: sistema.jar 4235kb 10/01/2012 4.0.1

no meu sistema eu seto uma variável static contendo a versão atual, exemplo: public static 4.0.0
ao abrir o sistema, baixo o arquivo versão.txt e comparo as versões, por exemplo se o que está no arquivo é != do que está no sistema, baixo o .jar novo

Olá Junior,eu estava pensando em criar uma table no banco e nela colocar dados como versão TOS e outros, e no sistema colocar a versão dentro do properties e depois comparar, se o valor do properties for diferente do valor da tabela ele baixa o novo jar do repositorio…
Meu problema é como fazer isso, como dizer a ele qual repositorio deve ser acessado,como mandar ele pegar o arquivo e substitui-lo pelo existente,entende?

JuniorMaia imprimentei uma atualização automatica só que para uma app em Android onde eu tinha um servidor Java Web, na minha app android eu guardava a versão no arquivo de propriedades(no caso do Android é no AndroidManifest.xml) então no meu servidor web inseri uma tabela no banco contendo dados da ultima versão disponível e o link para download do mesmo. Ao acessar as informações fazia uma comparação de versões se fosse diferentes eu baixava a nova aplicação a partir do link. No seu caso você pode fazer o mesmo e caso essa aplicação tenha pastas que não estão juntos do .jar então você pode compacta-la e extrai-la após fazer o download.

Obs.: Guardava o link para o servidor em uma constante e a aplicação ficava dentro do meu servidor, no banco tinha a url da aplicação que era apenas /atualizacoes/minhaAplicacao.apk ao baixar fazia uma verificação do tipo

if(!urlDaAtualizacao.contains("http://") && !urlDaAtualizacao.contains("https://")){ urlDaAtualizacao = urlDoMeuServidor+urlDaAtualizacao; //juntava as String caso a atualização fosse a partir do meu servidor. } //em seguida fazia o download

Caso você não queira fazer uma aplicação Web para o mesmo pode utilizar também sockets ou algum site que disponibilize tal serviço.


A aplicação precisa ser local,pois o repositorio vai ficar numa intranet sem acesso a web…
Fazer a comparação não é o problema o que não sei é informar ao JAVA o diretorio, e fazer ele baixar o novo arquivo e substituir o jar antigo,entende?

Ou seja o problema não é definir uma String conexao = “192.xxxxxxxx/dist/aplicativo.jar” , o problema é fazer com o que o JAVA use essa String para ir até a pasta, pegue os arquivos e então substitua pelos originais que estão sendo usadas e depois reinicie a aplicação…

M

bacoco:
A aplicação precisa ser local,pois o repositorio vai ficar numa intranet sem acesso a web…
Fazer a comparação não é o problema o que não sei é informar ao JAVA o diretorio, e fazer ele baixar o novo arquivo e substituir o jar antigo,entende?

Primeiro você precisa definir onde este novo JAR vai ficar. Você precisa armazená-lo em um servidor (que pode estar na sua intranet) para que os clientes possam baixá-lo.

bacoco

marcobiscaro2112:
bacoco:
A aplicação precisa ser local,pois o repositorio vai ficar numa intranet sem acesso a web…
Fazer a comparação não é o problema o que não sei é informar ao JAVA o diretorio, e fazer ele baixar o novo arquivo e substituir o jar antigo,entende?

Primeiro você precisa definir onde este novo JAR vai ficar. Você precisa armazená-lo em um servidor (que pode estar na sua intranet) para que os clientes possam baixá-lo.

Isso já está feito…

Já tem um servidor na rede onde está a pasta dist inteira,o .jar está dentro dela e junto a pasta lib.
O que preciso é fazer o java ir até lá e baixar esses arquivos e salva-los substituindo as que estão na minha que roda a aplicação…

O que pensei criar uma nova aplicação para que ela execute e verifique se tem alguma atualização,caso não tenha abre o .jar principal,caso tenha ela vai até esse repositorio e baixa tudo depois abre o .jar principal.

Meu problema é como fazer o java ir pela rede até a pasta e copiar tudo que quero e copiar por cima dos existentes? E depois como chamo um .jar para ser executado?

M

bacoco:
marcobiscaro2112:
bacoco:
A aplicação precisa ser local,pois o repositorio vai ficar numa intranet sem acesso a web…
Fazer a comparação não é o problema o que não sei é informar ao JAVA o diretorio, e fazer ele baixar o novo arquivo e substituir o jar antigo,entende?

Primeiro você precisa definir onde este novo JAR vai ficar. Você precisa armazená-lo em um servidor (que pode estar na sua intranet) para que os clientes possam baixá-lo.

Isso já está feito…

Já tem um servidor na rede onde está a pasta dist inteira,o .jar está dentro dela e junto a pasta lib.
O que preciso é fazer o java ir até lá e baixar esses arquivos e salva-los substituindo as que estão na minha que roda a aplicação…


Quando você diz “uma pasta na rede” está dizendo um servidor SMB (compartilhamento Windows)?

bacoco

marcobiscaro2112:
bacoco:
marcobiscaro2112:
bacoco:
A aplicação precisa ser local,pois o repositorio vai ficar numa intranet sem acesso a web…
Fazer a comparação não é o problema o que não sei é informar ao JAVA o diretorio, e fazer ele baixar o novo arquivo e substituir o jar antigo,entende?

Primeiro você precisa definir onde este novo JAR vai ficar. Você precisa armazená-lo em um servidor (que pode estar na sua intranet) para que os clientes possam baixá-lo.

Isso já está feito…

Já tem um servidor na rede onde está a pasta dist inteira,o .jar está dentro dela e junto a pasta lib.
O que preciso é fazer o java ir até lá e baixar esses arquivos e salva-los substituindo as que estão na minha que roda a aplicação…


Quando você diz “uma pasta na rede” está dizendo um servidor SMB (compartilhamento Windows)?

Sim

M

bacoco:
marcobiscaro2112:

Quando você diz “uma pasta na rede” está dizendo um servidor SMB (compartilhamento Windows)?

Sim

Não sei se este é o jeito mais fácil de fazer, mas neste caso você teria que usar uma biblioteca que possa acessar este compartilhamento para copiar os arquivos necessários.

Acredito que seria mais fácil se houvesse um servidor web e o JAR fosse baixado via HTTP.

bacoco

marcobiscaro2112:
bacoco:
marcobiscaro2112:

Quando você diz “uma pasta na rede” está dizendo um servidor SMB (compartilhamento Windows)?

Sim

Não sei se este é o jeito mais fácil de fazer, mas neste caso você teria que usar uma biblioteca que possa acessar este compartilhamento para copiar os arquivos necessários.

Acredito que seria mais fácil se houvesse um servidor web e o JAR fosse baixado via HTTP.

Não tenho como fazer essa segunda opção…

Meu problema serial qual biblioteca e como usa-la…

M

A biblioteca está no link do meu post anterior. É a jCIFS [1]. Na API [2] tem vários exemplos, mas basicamente você precisa criar uma conexão remota, ler de um SmbFileInputStream e escrever em um FileOutputStream local. Algo como:

NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication("domain", "username", "password");
InputStream in = new SmbFileInputStream("smb://host/c/My Documents/somefile.txt", auth);
OutputStrem out = new FileOutputStream("/caminho/para/salvar/o/jar");

// aqui você  do InputStream e escreve o valor lido no OutputStream

// talvez usar as versões Buffered(In|Out)putStream ajude na performance

[1] http://jcifs.samba.org/
[2] http://jcifs.samba.org/src/docs/api/

bacoco

Muitoo obrigado Marcos,vou estudar e tentar usar este pacote.
Obrigado

marcobiscaro2112:
A biblioteca está no link do meu post anterior. É a jCIFS [1]. Na API [2] tem vários exemplos, mas basicamente você precisa criar uma conexão remota, ler de um SmbFileInputStream e escrever em um FileOutputStream local. Algo como:

NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication("domain", "username", "password");
InputStream in = new SmbFileInputStream("smb://host/c/My Documents/somefile.txt", auth);
OutputStrem out = new FileOutputStream("/caminho/para/salvar/o/jar");

// aqui você  do InputStream e escreve o valor lido no OutputStream

// talvez usar as versões Buffered(In|Out)putStream ajude na performance

[1] http://jcifs.samba.org/
[2] http://jcifs.samba.org/src/docs/api/

bacoco
marcobiscaro2112:
A biblioteca está no link do meu post anterior. É a jCIFS [1]. Na API [2] tem vários exemplos, mas basicamente você precisa criar uma conexão remota, ler de um SmbFileInputStream e escrever em um FileOutputStream local. Algo como:
NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication("domain", "username", "password");
InputStream in = new SmbFileInputStream("smb://host/c/My Documents/somefile.txt", auth);
OutputStrem out = new FileOutputStream("/caminho/para/salvar/o/jar");

// aqui você  do InputStream e escreve o valor lido no OutputStream

// talvez usar as versões Buffered(In|Out)putStream ajude na performance

[1] http://jcifs.samba.org/
[2] http://jcifs.samba.org/src/docs/api/

Olá Marcos,você possui experiencia com esse pacote? Estou tendo alguns problemas com ele...

Estou fazendo o seguinte:

jcifs.Config.setProperty( "jcifs.netbios.wins", "10.216.6.1" );
        NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication("internal", "tra", "tra");
        SmbFile file;
        file = new SmbFile("smb://10.192.24.203/corpisa/SQL 2008/MYSQL/readme.txt", auth);
        
        SmbFileInputStream fis = new SmbFileInputStream(file);
        SmbFileOutputStream fos = null;
        
        byte[] b = new byte[8192];
        int n;
        while(( n = fis.read( b )) > 0 ) {
            System.out.write( b, 0, n );
            fos.write(b,0,n);
        }
        
        fos = new SmbFileOutputStream("C:/readme.txt");
Consigo pegar o arquivo e coloca-lo no SmbFile porém quando dou o fos.write ele simplesmente para a execução... Como devo fazer para pegar o arquivo e dar o write para depois faze-lo salvar no pc ??? Estou tentando ir pelo site que você me passou mais so consegui até ai... Obrigado
M

bacoco:

Olá Marcos,você possui experiencia com esse pacote? Estou tendo alguns problemas com ele…

É Marco, não Marcos. Bem, nunca utilizei este pacote, mas parece que tem algo errado no seu código. Tente algo como:

NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication("internal", "tra", "tra");
        SmbFile file = new SmbFile("smb://10.192.24.203/corpisa/SQL 2008/MYSQL/readme.txt", auth);
        
        SmbFileInputStream fis = new SmbFileInputStream(file);
        // você deve criar um FileOutputStream (local) e não um SmbFileOutputStream (remoto)
        FileOutputStream fos = new FileOutputStream("C:/readme.txt"); // a instanciação deve vir antes do laço while
        
        byte[] b = new byte[8192];
        int n;
        while (( n = fis.read( b )) > 0 ) {
            fos.write(b,0,n);
        }

        fis.close();
        fos.close();
bacoco

Olá Marco,perdão o costume,meu pai possui o S no final...

Estou fazendo da seguinte maneira agora...

FileOutputStream ffs = null;
        
        try{
            jcifs.Config.setProperty( "jcifs.netbios.wins", "10.216.6.222" );
            NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication("internal.timbrasil.com.br", "Administrator", "preventiva");
            
            file = new SmbFile("smb://10.216.6.222/preventiva/dist/PreventivaApp.jar", auth);
            

            SmbFileInputStream fis = new SmbFileInputStream(file);
            ffs = new FileOutputStream("\\RCVNA\\PreventivaApp.jar");

            byte[] b = new byte[8192];
            int n;
            while(( n = fis.read( b )) > 0 ) {
                System.out.write( b, 0, n );
                ffs.write(b,0,n);
            }
            
        }catch(Exception e){
            e.printStackTrace();
            System.out.println("Erro: "+e);
        }finally{
            //NÂO ESQUECER DE DAR CLOSE NOS STREAMS
            fos.close();
            ffs.close();            
        }  
    }

Porém não está funcionando,com um arquivo do tipo .txt funciona perfeitamente...

Se você tiver alguma sugestão gostaria de fazer diretamente com a pasta...
Acho que copiando a pasta seria melhor pois vai pegar todo o conteudo que preciso ao inves de ter que repetir o processo com todos os arquivos...
Obrigado.

M

Vamos lá:

Linha 11: porquê este formato com barras invertidas ao invés de “C:/RCVNA/PreventivaApp.jar”?

Linha 25: de onde vem esta variável fos?

Linha 26: você precisa primeiro verificar se a variável chegou a ser instanciada para depois chamar o close:

if (ffs != null) {
    ffs.close();
}

Além disso, aparece algum erro?

bacoco
marcobiscaro2112:
Vamos lá:

Linha 11: porquê este formato com barras invertidas ao invés de "C:/RCVNA/PreventivaApp.jar"?

Linha 25: de onde vem esta variável fos?

Linha 26: você precisa primeiro verificar se a variável chegou a ser instanciada para depois chamar o close:
if (ffs != null) {
    ffs.close();
}

Além disso, aparece algum erro?

Alterei segundo seu conselhos, o fos foi o nome que saiu errado é a ffs e fis apenas, segue como está agora:

public void coneca() throws IOException{
        SmbFile file;
        FileOutputStream ffs = null;
        SmbFileInputStream fis = null;
        
        try{
            jcifs.Config.setProperty( "jcifs.netbios.wins", "10.216.6.222" );
            NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication("internal.timbrasil.com.br", "Administrator", "preventiva");
            
            file = new SmbFile("smb://10.216.6.222/preventiva/dist/PreventivaApp.jar", auth);
            

            fis = new SmbFileInputStream(file);
            ffs = new FileOutputStream("C:/RCVNA/PreventivaApp.jar");

            byte[] b = new byte[8192];
            int n;
            while(( n = fis.read( b )) > 0 ) {
                System.out.write( b, 0, n );
                //fos.write(b,0,n);
                ffs.write(b,0,n);
            }
            
        }catch(Exception e){
            e.printStackTrace();
            System.out.println("Erro: "+e);
        }finally{
            //NÂO ESQUECER DE DAR CLOSE NOS STREAMS
            if (ffs != null) {  
                    ffs.close();  
            }
            if(fis != null){
                fis.close();
            }        
        }  
    }

Ele chega a criar o arquivo na pasta,porém ele fica somente com 8KB debugando ele entra no while faz um write e na segunda vez que ele vai correr dentro do while ele simplsemente para a execução,sem me retornar nada...(Alguma exceção que esqueci de tratar?)

Criado 9 de janeiro de 2013
Ultima resposta 24 de jan. de 2013
Respostas 24
Participantes 7