domingo, 1 de dezembro de 2013

Delphi XE5 Android - Sincronização



Esta vídeo aula tem como objetivo ensinar como criar um projeto FireMonkey Android utilizando SQLite para guardar informações de banco de dados localmente. 



Também é mostrado como sincronizar os dados do SQLite com o servidor (MySql), tudo com a utilização dos padrões de orientação a objeto e visando o menor consumo em banda de internet. Espero que gostem, qualquer dúvida, sugestão ou comentário basta comentar aqui ou no meu blog. Abraços e bons estudos.

Para download deste fonte, clique aqui.

Para acessar todo o repositório, clique aqui.

Segue o código de conversão entre JSON em classe e vice-versa:


function ComprasToJSON(Obj: TSuaClasse): TJSONValue;
var
  m: TJSONMarshal;
begin
  if Assigned(ListaCompra) then
  begin
    m := TJSONMarshal.Create(TJSONConverter.Create);
    try
      Exit(m.Marshal(Obj));
    finally
      m.Free;
    end;
  end
  else
    Exit(TJSONNull.Create);
end;

function JSONToCompras(Json: TJSONValue): TSuaClasse;
var
  unm: TJSONUnMarshal;
begin
  if Json is TJSONNull then
    Exit(nil)
  else
  begin
    unm := TJSONUnMarshal.Create;
    try
      Exit(unm.Unmarshal(Json) as TSuaClasse);
    finally
      unm.Free;
    end;
  end;
end;

82 comentários:

  1. Parabéns pelo post, tenho aprendido muito com suas Vídeo Aulas, eu tinha feito uma gambiarra do tamanho do trem para fazer isto que você mostrou, vou mudar meu código hoje mesmo, para começar a trabalhar com classes e utilizar este TJSONUNMarshal para converter.

    ResponderExcluir
    Respostas
    1. Muito obrigado pelo comentário, é bom saber que estou ajudando...

      Abraços e bons estudos.

      Excluir
  2. Muito bom Anderson, parabéns!

    Eduardo Belo

    ResponderExcluir
  3. massa em Anderson vai la pro forum hehe

    ResponderExcluir
  4. halo anderson,
    out of topic...
    how to display data type text (more than one line)?
    i have try to using memo but only show 1 line. any suggest component to load text type?

    best regards
    anang

    ResponderExcluir
    Respostas
    1. Helo Anang,
      I use TMemo but the content has to have a line break (#13#10).
      If you don't use the ScrollBar of TMemo it automatic line break.

      You can send me your example, I can correct to you.

      Excluir
  5. Ola... tudo bem?
    Estou estudando o video e adaptando o codigo ao meu primeiro projeto...
    Estou com dificuldade pra entender essa linha:
    dmCliente.SMCliente.getJsonListaCompra
    Como esta no video, nao consigo ver todo o codigo do projeto, poderia me ajudar?

    ResponderExcluir
    Respostas
    1. Olá Carlos, tudo sim e com vc?
      qual a sua dificuldade?

      Excluir
    2. Tudo bem comigo. Obrigado.
      Assistindo a outro video, eu entendi que vc criou um client modulo, que gera a comunicacao entre o client e o servidor. No video aqui em questao, vc nao fez a parte cliente de configuracao da comunicacao, entao quando vc puxa o dmcliente.smcliente, eu fiquei com duvida em quais componentes de banco devo usar... agradeço desde já pela sua atencao.

      Excluir
  6. Parabéns pelas aulas, estão me ajudando muito. Tem como disponibilizar o código fonte para que eu possa analisar melhor

    ResponderExcluir
    Respostas
    1. Dentro de algumas horas vou colocar o link do fonte desta vídeo aula. Fique atento. Abraços.

      Excluir
    2. aguardando ansioso pelo link dos fontes. desde já muito obrigado

      Excluir
    3. Desculpa a demora, tenho andado muito ocupado ultimamente, daí acabo esquecendo...

      Segue o link: https://drive.google.com/folderview?id=0B60tNO-1JvWxWV9jd2RwRGxuZUU&usp=sharing

      Abraços....

      Excluir
  7. Olá Anderson. Parabéns pelo blog. Excelente trabalho. Você poderia disponibilizar, se possível, os fontes deste projeto de sincronização, pois falta somente ele nos links para download. Obrigado.

    ResponderExcluir
    Respostas
    1. Dentro de algumas horas vou colocar o link do fonte desta vídeo aula. Fique atento. Abraços.

      Excluir
    2. Desculpa a demora, tenho andado muito ocupado ultimamente, daí acabo esquecendo...

      Segue o link: https://drive.google.com/folderview?id=0B60tNO-1JvWxWV9jd2RwRGxuZUU&usp=sharing

      Abraços....

      Excluir
    3. Valeu Anderson. Muito obrigado. Vou testar.

      Excluir
  8. Muito boa essas dicas, mas teria como disponibilizar essas fontes pra gente entender melhor. Valeu

    ResponderExcluir
    Respostas
    1. Dentro de algumas horas vou colocar o link do fonte desta vídeo aula. Fique atento. Abraços.

      Excluir
  9. como posso ver o demo das video aulas ?

    ResponderExcluir
    Respostas
    1. Dentro de algumas horas vou colocar o link do fonte desta vídeo aula. Fique atento. Abraços.

      Excluir
  10. Anderson, tudo bem? Parabéns pelas aulas, não tem como vc disponibilizar os fontes desse projeto para eu poder testar e estudar por ele. se possivel muito obrigado!!!

    ResponderExcluir
    Respostas
    1. Dentro de algumas horas vou colocar o link do fonte desta vídeo aula. Fique atento. Abraços.

      Excluir
  11. Man, tem como você fazer um vídeo ensinando como inserir dados do Android no SQLite?

    ResponderExcluir
    Respostas
    1. Já fiz um vídeo desses, segue o link: http://unitechgy.blogspot.com.br/2013/09/delphi-xe5-android-com-sqlite.html

      Abraços.

      Excluir
  12. Desculpa a demora, tenho andado muito ocupado ultimamente, daí acabo esquecendo...

    Segue o link: https://drive.google.com/folderview?id=0B60tNO-1JvWxWV9jd2RwRGxuZUU&usp=sharing

    Abraços....

    ResponderExcluir
  13. quando testo a conexão com sqlite aparece a seguinte mensagem para min "Falied sqlite3.dll not found" eu até achei essa dll, mas tentei jogar junto com o banco, system32 etc... mas não tive sucesso.... se puder me ajudar agradeço...

    ResponderExcluir
    Respostas
    1. Coloca junto com o executável...

      Nunca tive esse problema, então não sei como resolver... Abraços e boa sorte.

      Excluir
  14. no fonte que você disponibilizou. esta faltando um arquivo utdata.pas.

    teria como disponibilizar para nós?

    ResponderExcluir
    Respostas
    1. Infelizmente não posso, tem muito mais por tras dessa unit, troca a chamada por um formatdatetime que resolve. Abraços.

      Excluir
  15. ola Anderson, seus videos estão sensacionais, muito bons mesmo, tive alguns problemas mas com algum esforço consegui resolver, mas o que acontece agora é o seguinte, fiz um teste com esse seu exemplo em ambiente windows ele funciona beleza encontra o caminho do banco sqlite depois sincroniza, mas quando jogo pro device fisico, parece não encontrar o caminho do sqlite, como funciona ele cria o db automático ? eu tenho que jogar algum arquivo também ? ele aparece a seguinte mensagem "no such table: COMPRA", acredito que é coisa simples, mas estou com dificuldade de resolver, se puder ajudar agradeço !!!

    ResponderExcluir
  16. Muito boa as aulas, parabéns.

    Anderson, eu tenho uma dúvida
    Meu caso é o seguinte, tenho um server/client datasnap, já esta tudo configurado bonitnho, porem toda vez que preciso adicionar uma nova function no meu server para q seja acessado do cliente preciso deletar as units relacionadas no cliente e recriar o datasnap Client module, existe alguma maneira de atualizar o cliente sem precisar recria-lo?

    ResponderExcluir
    Respostas
    1. Não precisa apagar nada, clica no objeto de conexão (SQLConnection) com o botão direito e clica em Load Client Classe (ou algo assim) ele cria/recria o único arquivo necessário que é o ClientUnitClasses (algo assim).

      Excluir
  17. Quando clicao no sqlConnection do cliente com o botão direito as opções que me aparecem são:
    save connection paremeters(nao acontece nada)
    reload connection paremeters(nao acontece nada)
    genarete datasnap client class(nao consegue criar pois da erro de socket)provavelmete deve ser essa

    alguma ideia do que possa ser?

    ResponderExcluir
    Respostas
    1. genarete datasnap client class

      Você precisa estar com o servidor ligado!

      Excluir
    2. Sim, estou clicando com o servidor ligado.

      Excluir
    3. Deve ser as configurações de acesso, firewall, porta, IP e tal, mas esse é o cara certo.

      Boa sorte aí.

      Excluir
    4. deu certo aqui, reinicei o xe5 e quando refiz o processo deu certo, valeu.

      Excluir
  18. Anderson boa noite. para fazer a conexão com o banco oracle tenho que ter uma aplicação servidor ?ou faço tudo no cliente do delphi

    ResponderExcluir
    Respostas
    1. Bom dia, então, os componentes de conexão com banco de dados do Delphi (Android) não fazem conexão direta com Oracle, vc precisaria de um servidor datasnap para tal.

      Porém, tem um componente de terceiro, o UniDac, esse sim faz conexão direta com o Oracle atráves do Android, porém é pago.

      Abraços e boa sorte.

      Excluir
  19. Boa Tarde, mas o servidor datasnap eu crio dentro do mesmo projeto do android ou tenho que ter ele rodando fora em outra aplicação ?

    Obrigado

    ResponderExcluir
  20. Boa tarde Anderson, gostei muito da sua aplicação de sincronização esta sendo muito útil. Tenho uma pergunta: No seu exemplo, modifiquei apenas o componente FDPhysMySQLDriverLink1 pelo FDPhysMSSQLDriverLink1 e o mesmo funciona normalmente exceto o botão Enviar Dados que sempre retorna com a mensagem Falha ao sincronizar, consulte o log de erros. Você teria passado pelo mesmo problema? Consigo Receber os dados do servidor normalmente o problema é na hora de envia-los. Agradeço desde já.

    ResponderExcluir
    Respostas
    1. Muito obrigado.

      Assim não sei o que é, tente debugar o projeto (servidor) e vê no que dá.

      Abraços.

      Excluir
    2. Este comentário foi removido pelo autor.

      Excluir
    3. Boa Tarde, tb estou com o mesmo problema...mesma mensagem de de falha ao sincronizar, vc conseguiu resolver? poderia me ajudar?

      Excluir
  21. Anderson, quando jogo pro meu tablet, parece que não encontrar os caminhos do sqlite, como funciona ele cria o db automático ? eu tenho que jogar algum arquivo também ? ele aparece a seguinte mensagem "no such table: COMPRA"

    ResponderExcluir
    Respostas
    1. Tem que enviar o arquivo de banco de dados.

      Essa vídeo aula mostra como fazer: http://unitechgy.blogspot.com.br/2013/09/delphi-xe5-android-com-sqlite.html

      Abraços.

      Excluir
    2. agora ele nao ta conectando com o banco do meu pc, da o erro 'near"TSM":syntax error', tem alguma previsao ?

      abraços.

      Excluir
    3. Não tenho a menor ideia do que seja esse erro...

      Excluir
    4. Anderson estou com o mesmo problema: 'near"TSM":syntax error', Só que no meu caso ao invés de TSM é um código de barras em string. O erro ocorre quando tento inserir os dados no BD. Além disso assim que salvo uma tabela ela volta todos os tamanhos de campo para 1. Saberia me dizer como resolver isso?
      Att.
      PS.: Assisto todos os seus videos. Eles tem sido de grande ajudar. Obrigado pela iniciativa.

      Excluir
    5. Tem alguma coisa errada no seu teste, não sei o que vc esta fazendo, teria que ver e debugar pra entender onde está o erro.

      Tenta comparar o seu com o exemplo que fiz, segue o link para download:
      https://drive.google.com/folderview?id=0B60tNO-1JvWxWV9jd2RwRGxuZUU&usp=sharing

      Abraços e boa sorte.

      Excluir
  22. e se eu sincronizar 10 vezes com o servidor, vou ter no banco 10 vezes os mesmos dados?

    ResponderExcluir
    Respostas
    1. No exemplo que fiz não me preocupei com isso, é só um exemplo.
      No seu, coloque validação, se o registro já existir não insere só faz update ou coisas do gênero...

      Abraços.

      Excluir
  23. Excelente !!!! 10 !!! Já estou no Delphi a 04anos, e estou iniciando com o Android. Não sabia como começar.... Agora já sei, graças ao seu Blog.... VALEU !!!!

    ResponderExcluir
    Respostas
    1. Muito obrigado pelo comentário... boa sorte e bons estudos. Abraços

      Excluir
  24. Ola amigo parabéns pela video-aula , mas tem um detalhe baixei o exemplo e não esta nos arquivos "utdata.pas" tem como você me enviar ricardozamboni@hotmail.com

    ResponderExcluir
    Respostas
    1. Não precisa, não tem nada de mais nessa unit, apenas um formatdatetime, retira ela do código e no lugar que pede troca por um formatdatetime... Abraços

      Excluir
  25. Eu estou fazendo um trabalho de faculdade e fiquei com algumas dúvidas:
    O meu projeto é um aplicativo de vendas, o usuário vai poder gerar o pedido e adicionar os itens. O cadastro de produto e cliente já vem pronto.
    Eu fiz um listbox onde eu mostro os pedidos digitados usando o LiveBindings, mas como eu faço para que quando ele abrir um pedido somente mostrar os itens referentes aquele pedido em outra tabela.
    E mais uma coisa, como eu faço para concatenar a informação que vai aparecer no Listbox, eu adicionei a relacão com a tabela mas por exemplo no ItemHeader.Text esta mostrando o número do peddo, mas eu gostaria de adicionar a palavra: " Pedido:" antes do número.

    E parabéns pelos videos tem me ajudado muito.

    Obrigado

    ResponderExcluir
    Respostas
    1. Dá uma olhada nessa vídeo aulas, mostro como fazer isso:
      http://unitechgy.blogspot.com.br/2013/10/delphi-xe5-android-listview-com-imagens.html

      http://unitechgy.blogspot.com.br/2013/09/delphi-xe5-android-com-sqlite.html

      Quanto a outra questão, faz a concatenação no comando sql mesmo, fica bem melhor... No delphi da pra fazer mas vai ter que montar o listview/listbox manualmente, aí complica mais um pouco. Abraços

      Excluir
  26. Muito bom seus vídeos, parabéns.
    Estou adaptando o projeto para fazer um "Extrato", tipo um cliente apenas e várias contas a pagar, no servidor, coloquei um memo para monitorar o carregamento das classes, esta ok, mas no cliente, retorna a classe vazia testo com if not assigned(classe) aqui tem proxy, será que pode ser isso ou estou fazendo algo errado?
    a comunicação chega até o servidor, ele processa, mas na hora do cliente pegar, não consegue.

    obrigado

    ResponderExcluir
    Respostas
    1. Muito obrigado.

      Então, se a conexão está chegando até o servidor o proxy respondeu bem, ACHO que não deve ser ele.
      Em algum lugar esta destruindo o objeto antes da hora, ou não esta montando corretamente. Revisa aquelas duas funções que faz o Marshal e depois revisa as funções que preparam as classes.

      Abraços

      Excluir
    2. Obrigado pela ajuda, a minha outra dúvida é a seguinte:
      se eu vou ter apenas um cliente com várias contas, preciso Fazer um array ou só a classe direto?
      e na hora de declarar é só "carregar" os dados instanciando o objeto?
      ou seria melhor para fazer o array para fazer o parse JSon?

      Excluir
    3. Vc precisa fazer um array das contas, do jeito que fiz aí.
      Fazendo o array e ao fazer o parse Json, vc instancia o objeto array das contas.

      Excluir
  27. Achei fantástico essa vídeo aula, baseada nela eu fiz um projeto client/server com SQLite servidor e Firebird Cliente , enviando e recebendo dados, já testei no modo windows e funcionou legal. Conexão por IP.
    Agora eu precisava fazer a tela de configuração de conexão do cliente com o servidor, tipo a pessoa digitar o IP do servidor, digitar o FTP para transferencia de arquivo etc.
    Uma boa dica para uma nova video aula.
    Obrigado por postar seus conhecimentos. foi muito bom aproveitado.

    ResponderExcluir
  28. Anderson...bom dia. Parabens pelo post. Eu estou tentando fazer um app com datasnap, seguindo os passos. Porem estou com problema, ao conectar no servidor. Deixo rodando o app do servidor dai no cliente ao receber as informações da o erro: Remote Error: TSM.GetJsonListaproduto method not found in the server method list.
    Só que esta criado esse metodo no servidor. O que será q pode ser ? No aguardo. Obrigado.

    ResponderExcluir
  29. Este comentário foi removido pelo autor.

    ResponderExcluir
  30. Outro detalhe Anderson....no procedimento do cliente Receber Dados, o comando dmClient.SQLConnection1.Open; no meu caso ocorre erro de Socket Error: Conection refused, dai troquei por dmClient.SQLConnection1.connected := true;
    Será q pode ser esse o problema da duvida anterior ?

    ResponderExcluir
  31. Boa Noite, meu nome é André achei show de bola seu exemplo, so estou com dificuldade nesse erro ([dcc32 Error] utCompras.pas(46): E2003 Undeclared identifier: 'TJSONValue') poderia me ajudar?

    ResponderExcluir
    Respostas
    1. Anderson, parabéns pelo post. Tem me ajudado muito, mas muito mesmo. Abç.

      André, caso ainda não tenha conseguido resolver, experimente acrescentar a "System.JSON" na uses . . .comigo deu o mesmo problema em XE6.
      Espero ter ajudado. Abç.

      Excluir
  32. Olá anderson, tudo certo?

    Show de bola suas videos aulas!!!
    Meu projeto está evoluindo graças a você!!!!

    E agora estou precisando da sua ajuda novamente, você já fez algum projeto com delphi e android fazendo impressão em impressora bluetooth ? Teria algum material que pudesse compartilhar?

    Se puder me ajudar agradeço.

    ResponderExcluir
    Respostas
    1. Opa, infelizmente não tenho material para isso. Abraços

      Excluir
  33. Olá Anderson Tenho aprendido muito com suas videos aulas... e sinceramente você está de parabém por sua iniciativa...

    Agora estou com uma dificuldade cruel no tocante a sincronização... não estou conseguindo adaptar seu código com a minha necessidade... será que você teria como de dar uma ajuda... gostaria de fazer a sincronização apenas de uma tabela... no meu caso uma tabela de alunos...

    ResponderExcluir
  34. Sei que no exemplo que você postou imagino ser o mais simples possível... mais tem como postar um exemplo mais simples que esse? rsrsr ...
    segue meu e-mail: alexsnci@hotmail.com

    ResponderExcluir
  35. Anderson me refiro a o uso de apenas uma tabela no código... se não me engano você está usando duas na vídeo aula...

    ResponderExcluir
  36. Anderson me refiro a o uso de apenas uma tabela no código... se não me engano você está usando duas na vídeo aula...

    ResponderExcluir
  37. Anderson, parabéns pela iniciativa.
    Estou fazendo minha primeira aplicação para android, e estou usando como base sua video aula.
    Mas estou com um problema, de incompatibilidade, no result da função.
    Segue o erro:
    [dcc32 Error] mbDados.pas(55): E2010 Incompatible types: 'wsdadosPessoa.TJSONValue' and 'System.JSON.TJSONValue'
    Estou usando a mesma função que você mostrou:

    function PessoaToJSON(ListaPessoa: TListaPessoa): TJSONValue;
    var
    m: TJSONMarshal;
    begin
    if Assigned(ListaPessoa) then
    begin
    m := TJSONMarshal.Create(TJSONConverter.Create);
    try
    Exit(m.Marshal(ListaPessoa));
    finally
    m.Free;
    end;
    end
    else
    Exit(TJSONNull.Create);
    end;

    O erro acontece no método enviar:
    procedure TForm1.btnEnviarClick(Sender: TObject);
    var
    JSONPessoa: TJSONValue;
    Listapessoa: TListaPessoa;
    ArrPessoa: TArrPessoa;
    begin
    dmMobile.fdqryPessoa.Close;
    dmMobile.fdqryPessoa.Open;
    if dmMobile.fdqryPessoa.IsEmpty then
    begin
    ShowMessage('Nenhum registro encontrado para enviar.');
    Exit;
    end;

    try
    dmMobile.fdqryPessoa.First;
    Listapessoa := TListaPessoa.Create;
    JSONPessoa := TJSONValue.Create;

    SetLength(ArrPessoa, dmMobile.fdqryPessoa.RecordCount);
    while not dmMobile.fdqryPessoa.Eof do
    begin
    ArrPessoa[dmMobile.fdqryPessoa.RecNo - 1] := TPessoa.Create;
    ArrPessoa[dmMobile.fdqryPessoa.RecNo - 1].Nome := dmMobile.fdqryPessoa.FieldByName('NOME').AsString;
    dmMobile.fdqryPessoa.Next;
    end;
    ListaPessoa.ListaPessoa := ArrPessoa;
    JSONPessoa := PessoaToJSON(ListaPessoa); <== Nesta linha acontece o erro

    dmMobile.FDconexao.Open();
    if GetIwsDados().SincronizarPessoa(JSONPessoa) then
    ShowMessage('Sincronização efetuada com sucesso.')
    else
    ShowMessage('Falha ao sincronizar.');
    except
    on E: Exception do
    ShowMessage(E.Message);
    end;
    end;

    Sabe o que posso fazer pra resolver?
    Desde já agradeço!

    ResponderExcluir
  38. Amigo, obrigado pelo artigo, estou tendo dificuldades em uma pequena parte do codigo!
    ArrItensCompra[dmClient.qryItensCompra.RecNo - 1].DTValidade := TData.DTInvToDate(dmClient.qryItensCompra.FieldByName('DTVALIDADE').AsInteger);

    já que não esta disponivel a unit utData, sabe me informar como posso utilizar o formatdatetime nesse codigo?

    grato

    ResponderExcluir
  39. Anderson, parabéns pelos artigos !

    Tenho um aplicação criada com Delphi 7 / Firebird 1.5.6 rodando localmente no windows 7 em um computador que está ligado a um roteador que conecta diretamente 5 Tablets que rodam meu APP criado em Delphi XE 6.

    Atualmente tenho a necessidade de listar uma das tabelas do meu banco neste APP nos Tablets, como sei que fica complexo realizar isso com o Firebird, eu fiz o seguinte:

    Criei um DB SQLite no windows localmente e atualizo ele paralelo ao meu Firebird através da minha aplicação Delphi 7.

    Como faço para acessar este banco que está lá no Windows através do meu APP nos Tablets ?

    Grato...

    ResponderExcluir
    Respostas
    1. Completando, preciso fazer apenas um SELECT em uma das tabelas !

      Excluir