xMova Android

MODEL

O xMova interpreta o modelo de dados para criar as telas do fluxo. No modelo define-se todas as entidades e seus campos. Em cada entidade e campo pode-se definir atributos e eventos.

Formato

O modelo é definido da seguinte forma:

Apontamento sync=in|out|beforeInstall
  id inc
      idSeq long uuid
  data Now
      campo1 int
  campo2 String
  events
    beforeInsert
      log Evento que ocorre antes de inserir um registro.

    beforeSync
      log Não sincroniza se retornar 0.

  fieldEvents
    onValidate
      campo1
                //Permite prosseguir apenas se o valor inserido for maior que zero.
        return campo1 > 0

  crudActions
    MostrarResumo
      show TelaResumoApontamento

Tipos de Campo

  • Batterylevel
  • Binary
  • Boolean | Bool
  • Bytes
  • Date
  • Decimal
  • Double
  • Entity
  • Float
  • inc
  • Integer | int
  • List<Entity>
  • Location
  • Long
  • Now
  • ReceivedFile [nome pode ser alterado]
  • String | Str
  • Text

Atributos de Entidades

  • bluetoothKeepRecordsWhenNewRecordsIsEmpty: Usado quando atualiza dados via bluetooth. Caso a lista de dados enviada esteja vazia, mantém os dados existentes no mobile.
  • cleanupDays: Apaga a entidade após passado a quantidade de dias configurado no cleanupDays. Antes de apagar, verifica se existe algum fixedPoint, só realizar o procedimento de apagar caso não exista entidade em uso.
  • confirm: Mostra a tela de confirmação antes da criação ou finalização da entidade. (ex.: confirm=Create|Finish)
  • delete: Permite que o usuário delete dinamicamente um registro da entidade.
  • descriptionFields: Quando for exibido em uma lista, define o que vai aparecer em cada elemento.
  • emptyVerify: Antes de iniciar o preechimento do fluxo, verifica se a entidade sync=in está vazia. Se configurado como emptyVerify=true, não permite prosseguir se estiver vazia. (ex.: emptyVerify=true ou emptyVerify=false)
  • favorite: Marca os ultimos registros selecionados com a cor amarela e adiciona no topo da listagem (permite até 3 itens).
  • insert: Permite que o usuário insira dinamicamente um registro na entidade.
  • insert - insertFields: Definição dos campos que serão pedidos na insersão de um registro.
  • insert - insertFieldNotFillId: Nesse caso é necessário o preenchimento manual do id por parte do programador.
  • memory: Usado em entidades (in e out) para indicar que elas serão mantidas em memória para que as leituras sejam rápidas. (veja Entidade em Memória)
  • messageScheduled: Usado para agendar a visualização de um texto para a hora pré-definida. (veja Mensageria)
  • noFinishAction: Retira a opção do crud que finaliza a entidade.
  • noSyncAction: Retira a opção do crud que sincroniza os dados.
  • notSavedMessage: Não mostra “salvo com sucesso” após salvar o inicio de uma entidade.
  • openFinish: Preenche o campo mobStatus (0 :aberto | 1:fechado)
  • recursive: Usado em entidades que se auto referenciam.
  • SyncBackgroundOnFinishRecord Deve ser utilizado na entidade Boletim. Faz com que o sincronismo seja chamado em background ao finalizar a entidade.

Exemplo:

Entidade1 recursive
        id int
        name Str
        idParent Entidade1
  • searchFields: Define os campos que podem ser usados na busca dos registros da entidade.
  • sync: Define o tipo de sincronismo da entidade. (veja Tipo de Sincronismo da Entidade)

Atributos de Campos

  • autoFill: Adiciona o valor pré-definido ao campo. Não pede o preechimento do campo para o usuário.
  • acceptEmpty: Permite que o usuario passe para o próximo campo sem informar um valor.
  • defaultValue: Valor pré-definido para um campo caso seu retorno seja nulo.
  • externalName: Define como nome do campo que será enviado para o servidor.
  • fill=Finish: Adicionado ao campo para que ele seja preenchido somente no fim do apontamento.
  • fillCondition: Verifica se o campo deve ser preenchido. Se retornado false, permite que o usuario passe para o próximo campo sem informar um valor.
  • fillConfirm: Indica que antes de um campo ser preenchido, sera pergutado ao usuario se deseja preencher o campo.
  • fixedPoint: Indica que o aplicativo deve retornar o campo com o fixedPoint quando reiniciado, caso o field seja acessado no preechimento.
  • getInputScreenLabel: Alteração para mudar titulo da tela.
  • getInputTopMessageLabel: Alteração para mudar a mensagem que é apresentada entre o título e o primeiro item da lista.
  • hide: Oculta um campo e seu valor na tela de detalhe de um elemento da lista.
  • ignoreExternal: Retira o campo do registro enviado para o servidor.
  • maxLength: Usado para limitar o tamanho de um campo.
  • notBack: Usado em campos que pedem informações ao usuário para indicar que o usuário não poderá voltar para o campo anterior.
  • notFill: Indica que não deve solicitar ao usuário que preencha esse campo
  • notSync: Usado em uma entidade sync=in para manter o valor gravado no mobile, mesmo que o registro seja atualizado com o sincronismo.
  • onGetDefaultInputValue: Pré-preenche o valor de um campo, para mostrar ao usuário. Permite a alteração do valor.
  • onlineValidate: Recebe uma string como parâmetro (nome de um método), a validação é feita web. A web deve enviar todos os campos já preenchidos pelo mobile, além dos campos de retorno. (ex.: onlineValidate=validaLider) (veja Validação On-Line)
  • onlineValidate - clearOnValidationFail: Reinicia o processo de preenchimento e reseta os valores quando o valor do campo não passa na validação.
  • onlineValidate - continueOnError: Prossegue com o fluxo quando a validação retornar erro.
  • onlineValidate - continueOnFail: Prossegui com o fluxo quando a validação falhar.
  • onlineValidate - goToFieldOnValidateStatus: Tem a propriedade para pular de campo quando ocorrer um status na validacao online do campo (ex.: onlineValidate=validaLider, goToFieldOnValidateStatus:1,codigoLider).
  • reader: [reader=cam|nfc|bt] Abre a camera do aparelho. Utilizado para leitura de códigos.
  • uuid: Indica que o campo sera preenchido automaticamente por um uuid long ou alfanumerico (ex.: G9x5I.YD:df98W), contemplando os ids do auth, timemillis, etc
  • mask: Permite adicionar uma máscara a um campo de entrada. A máscara permite caracteres numéricos, alfanuméricos, todos caracteres e símbolos especiais. Para utilizar caracteres especiais, precisamos na string que determina a máscara colocar o caractere de scape seguido do símbolo especial, por exemplo 9. Os símbolos especiais da máscara são: 9 (dígito), A (alfa caractere), * (Dígito ou Alfa caractere) e ? (Dígito, Alfa caractere ou símbolos especiais).

Exemplo de uso da máscara:

Boletim sync=out cleanupDays=20 notSavedMessage
        id inc
        idSeqBoletim uuid
        mascaraCPF Long mask="999.999.999-99"
        mascaraNumeral Long mask="9.9.9.9.9.9"
        placaVeiculo Str mask="AAA-9999"
        mascaraTelefoneCelular Str mask="(12)\99999-9999"
        mascaraFicticia Str mask="99A*\?"

Binary

  • Binary - draw: Mostra tela para desenhar. Utilizado para campo de assinatura.
  • Binary - picture: Abre a camera do aparelho. Utilizado para tirar foto.
  • Binary - audiorecord: Mostra uma tela de gravação de som. Utilizado para gravar/reproduzir o som corrente. O formato é o 3gp (mais leve para transferência/armazenamento).
  • Binary - picturemarker: Permite ao usuário tirar uma foto e efetuar marcações sobre a mesma.

BluetoothFile

  • Nome_da_Entidade - bluetoothFile: Indica que este campo será recebido via bluetooth.
  • Nome_da_Entidade - bluetoothFile - sendFields: Usado para indicar quais campos da entidade, a qual o campo que tem o atributo ‘bluetoothFile’, devem ser enviados quando iniciar o recebimento dos arquivos via bluetooth. (Exemplo: Coletor bluetoothFile sendFields: id, name, data).

Boolean

  • Boolean - notShowNo: Mstra apenas o botão SIM e VOLTAR, não mostrar o botão NAO. Combinado com notBack nao mostra o botão voltar.
  • Boolean - notShowYes: Mostra apenas o botão NAO e VOLTAR, não mostrar o botão SIM. Combinado com NotShowNo nao mostra apenas o botao voltar.

Date

  • Date - onlydate: Pede apenas a data.
  • Date - onlytime: Pede apenas a hora.

Decimal

  • Decimal - decimalSize: Define quantas casas decimais serão mostradas quando o número for formatado.
  • Decimal - manualDecimal: Usado para desabilitar a formatação automática de um campo do tipo decimal.

Entity

  • add: Permite preencher os campo da entidade, ao invés de mostrá-la como lista.
  • autoFillWhenOneItem: Se houver apenas um registro na lista (após o filtro), ignora o preenchimento do campo, e preenche o campo com este registro automaticamente.
  • fullDescription: Permite uma lista detalhada com uso do descriptionFields.
  • ignoreWhenListIsEmpty: Quando a lista de escolha do RecordSelector estiver vazia, ignora o preenchimento do campo.
  • inUpper: Indica que o campo devera ser convertido para uppercase antes de apresentá-lo
  • transient: Não deve ser incluido na serialização do objeto

List<Entity>

  • loop: Indica que uma vez iniciado o primeiro registro, deve continuar inserindo mais automaticamente.
  • loop - autoInitializeNew: Indica que a inserção de registros na lista deve ser iniciada automaticamente.
  • loop - autoInitializeNew - finishOnEndLoop: Finaliza a entidade que está em loop automaticamente, quando terminar o preenchimento.
  • getManyRecords: Retorna os registros de uma entidade. Faz com que a entidade seja preenchida uma vez para cada registro retornado. Este valor retornado é atribuído a um campo do mesmo tipo na entidade a ser preenchida.
  • inlineData: Para entidades sync=out, faz com que os valores preenchidos em outra entidade seja atribuído ao campo e enviado junto com a entidade para o servidor.
  • notRequired: Usado para verificar se o campo list<Entity> não precisa ter algum valor selecionado para prosseguir o fluxo.
  • notUseAsFilter: Indica que o campo não deve ser usado como filtro quando estiver selecionando uma lista que refencia este campo.
  • useAsFilter: Indica que o campo deve ser usado como filtro quando estiver selecionando um item na lista, mesmo que a entidade do campo não seja SyncIn.
  • viewAsColorIcon: Apresenta um icone colorido para cada registro na lista.
  • viewAsColorIcon - disableContinueButtonOnColorIcon: Não mostra o botão Continuar quando utilizar a cor do icones (default habilitada).
  • viewAsColorIcon - disableColorIcon: Desabilita icone colorido na lista (default habilitada).
  • viewAsColorIcon - enableColorIcon: Habilita icone colorido na lista (default habilitada).
  • viewAsColorIcon - toggleColorIcon: Permite a troca de cor do item ao clicar nele.
  • fullColorIconList - Necessário o uso do atributo viewAsColorIcon, permite que o label seja completo na linha.

Number

  • internalStatus: Indica que o campo é usado pelo xmova para controlar o status do registro, onde 0 é o status de criado, 2 é o status de finalizado.
  • notFormatThousand: Usado em campos numéricos para retirar os pontos e virgulas do texto
  • numericKeyboard: Uso para forçar a exibição do teclado numérico mesmo quando um campo é do tipo String.
  • onlineFlagCreate: Indica que o campo é uma flag online/offline de criação do registro.
  • onlineFlagFinish: Indica que o campo é uma flag online/offline de finalizacao do registro.

Eventos da Entidade [events]

  • afterInsert: Realiza o evento após gravar o registro pela primeira vez.
  • afterFinish: Realiza o evento após gravar o registro depois de finalizar a entidade.
  • afterSyncSave: Após realizar o sincronismo da entidade. É chamado o evento, após o salvamento de cada registro.
  • beforeInsert: Realiza o evento antes de gravar o registro pela primeira vez.
  • beforeFinish: Realiza o evento antes de finalizar a entidade. Caso o retorno seja falso, não permite a finalização.
  • beforeDelete: Realiza o evento antes de excluir o registro.
  • beforeSync: Realiza o evento antes de realizar o sincronismo.
  • onInsertAlreadyExists: Realiza o evento ao realizar a instrução insert da entidade e o registro já existir.
  • onItemClick: Realiza o evento ao clicar no item da lista de uma entidade.
  • onCrudOptionsBack: Evento executado quando o aplicativo está na tela de opções do crud e é pressionado a opção de voltar, caso retorne ‘false’ a ação padrão da tecla voltar (sair do aplicativo) não é executada.
  • OnShowScheduledMessage: Evento executado no momento que as mensagens estão sendo listadas para serem exibidas. Caso o evento retorne o valor ‘false’ a mensagem não é exibida.

Eventos do Campo [fieldEvents]

  • afterFill: Realiza o evento após o preenchimento do campo.
  • autoFill: Pré-preenche o valor de um campo. Não pede o preechimento do campo para o usuário.
  • fillCondition: Verifica se o campo deve ser preenchido. Se retornado false, permite que o usuario passe para o próximo campo sem informar um valor. (default true)
  • filterListRecord: Filtra o número de elementos de uma lista, cada registro pode ser acessado atravéz da variável listRecord.
  • getInputScreenLabel: Alteração para mudar titulo da tela.
  • getInputTopMessageLabel: Alteração para mudar a mensagem que é apresentada entre o título e o primeiro item da lista.
  • getManyRecords: Retorna os registros de uma entidade. Faz com que a entidade seja preenchida uma vez para cada registro retornado. Este valor retornado é atribuído a um campo do mesmo tipo na entidade a ser preenchida.
  • onGetDefaultInputValue: Pré-preenche o valor de um campo, para mostrar ao usuário. Permite a alteração do valor.
  • onValidate: Verifica se o valor é valido e o fluxo pode prosseguir.(default true)(confirm abre uma tela de confirmação)
  • webView: Retorna texto com url. Funcionalidade de mostrar pagina html adicionando o atributo webView=”url” no campo String.

Padrões de Nomes

Nome da entidade usada no server

O xMova Server quando acessar a entidade do sistema de terceiro ou banco de dados, usará o próprio nome da entidade no JSON e SQL.

Note

Note a saída do JSON. O nome da entidade Serviço não foi alterado. Já o nome da entidade Frente, aparece no JSON como FrenteAG.

Exemplo de Entidade:

Servico
  id inc
  nome String
Frente
  id inc
  nome String
  server name FrenteAG

JSON que será gerado para o sistema de terceiro durante o sync:

{"deviceUuid":"357517051399154",
 "appCode":"E",
 "intVersion":12,
 "version":"1.0.11",
 "auth":{"obra":76,"operador":177749,"celular":10495},
 "types":[
     {"version":0,"name":"Servico"},
     {"version":0,"name":"FrenteAG"}
 ]
}

Quantidade de itens selecionados em listas

Para obter a quantidade de itens selecionados e não selecionados numa lista multi-select, o xmova usa um padrão de nomes de campos para definir os valores.

No campo que termina com Selecteds será definida a quantidade de itens selecionados.

No campo que termina com Unselecteds será definida a quantidade de itens não selecionados, ou seja, o total de itens na lista menos a quantidade de itens selecionados.

Exemplo:

Apontamento
  id inc
  funcionarios List<Funcionario>
  funcionariosSelecteds int notFill
  funcionariosUnselecteds int notFill

Campo com os itens que não foram selecionados

Num campo de checklist são armazenados os ids dos registros que foram selecionados. Para se obter os ids dos que não foram selecionados declara-se um outro campo com nome terminando com ‘UnselectedRecords’.

Exemplo:

Apontamento
  id inc
  funcionarios List<Funcionario>
  funcionariosUnselectedsRecords List<Funcionario> notFill

GERAL

Ações de CRUD [crudActions]

Permite adicionar ações customizadas na tela de opções do crud

Exemplo:

Boletim sync=out cleanupDays=20 notSavedMessage
      id inc
      idSeqBoletim uuid
      numero int notFill

      crudActions
              myCrudAction
                      actionLabel
                              return id
                      fill numero
  • crud: Chama o preenchimeto de uma entidade.
  • isVisible: Retorna se opção será visivel no menu. (default true)
  • fill: Chama o preenchimeto de um campo na mesma entidade.
  • show: Retorna uma tela customizada (custom ou tableLayout)
  • actionLabel: Retorna o texto visivel para a opção no menu.

Options

Permite adicionar ações customizadas no menu de opções que pode ser exibido na tela de opções do crudo e nas telas de lista de entidades.

Exemplo:

Boletim sync=out cleanupDays=20 notSavedMessage
      id inc
      idSeqBoletim uuid
      numero int notFill
      options
              myOption
                      actionLabel
                              return id
                      fill numero
  • isVisible: Retorna se opção será visivel no menu. (default true)
  • actionLabel: Retorna o texto visivel para a opção no menu.

Entidades que podem ser acessadas no fluxo.

  • AppEntityVer: Grava as versões de cada entidade.
  • _Deleted: Grava os registros deletados da entidade. (usar: nome_da_entidade + _Deleted)
  • _Favorite: Grava os registros salvos como favorito da entidade. (usar: nome_da_entidade + _Favorite)
  • _FixedPoint: Salva e recupera o estado da tela para retornar ao app no mesmo ponto do fluxo quando reiniciar o app.
  • _SyncOut: Grava os registros salvos da entidade sync=out que deverá ser enviada para o servidor no próximo sincronismo. (usar: nome_da_entidade + _SyncOut)
  • _Favorite: Grava os registros salvos como favorito da entidade. (usar: nome_da_entidade + _Favorite)

Linguagem xMova

Tipo de Sincronismo da Entidade

Em cada entidade pode-se definir o tipo de sincronismo. Quando o app faz um sync com o servidor cada entidade será analisada para verificar se os dados dela serão enviados ou recebidos do servidor, ou se a entidade será ignorada no sync.

sync=in: O servidor retornará os dados desta entidade em todos os sync Foreground.

sync=out: Em todos os Sync, Foreground ou Background, os dados dessa entidade serão enviados ao servidor.

sync=in|out: O servidor retornará os dados desta entidade em todos os sync Foreground, e enviará os dados inseridos nela em todos os sync.

sync=backgroundIn: O servidor retornará os dados desta entidade em todos os sync, independente de ser Foreground ou Background.

sync=beforeInstall: O servidor retornará os dados desta entidade apenas no primeiro sync ANTES da instalação do app. Serve para fluxos em que seja necessário exibir lista de opções durante o processo de configuração inicial do fluxo.

Data e Hora

No modelo de dados, pode-se definir um campo como tipo ‘now’ para que nesse campo seja armazenada a data e hora corrente quando cria-se um apontamento.

Quando o xmova armazena a data e hora corrente em um registro de apontamento, ela pode ser de 4 tipos. A letra do tipo é que será enviado ao sistema externo.

  • U: Data e hora indefinida;
  • S: Data e hora obtida do servidor;
  • M: Data e hora informada pelo usuário/operador manualmente;
  • G: Data e hora obtida do GPS;
  • D: Data e hora nativa obtida do device;

No fluxo pode-se definir que a data e hora não seja solicitada ao usuário, mas que seja pega a data e hora corrente do device. Quando isso ocorrer, o xmova não enviará para o servidor o tipo de data M Manual, mas sim enviará o tipo de data D Device.

Exemplo:

App appCode=R offlineDate=Device

No modelo, no campo que guarda a data e hora do tipow ‘now’, pode-se definir o nome de campo no sistema externo onde será informado o tipo de data que foi utilizada. Para isso use o atributo timeTypeField. Dessa forma, quando enviar o JSON para o sistema externo, o xMova Server enviará 2 campos, o campo do tipo now contendo a data e hora, que o desenvolvedor criou no modelo, e um segundo campo para informar o tipo de data e hora utilizada, que não faz parte da entidade no mobile, mas foi especificado no campo do tipo now.

Exemplo:

Apontamento
  boletim Boletim
  data now timeTypeField=tipoData
  servico Servico

Exemplo de envio da data no JSON:

{"boletim":100,
 "data":"11/07/2014 09:10:32",
 "tipoData":"G",
 "servico":200}

FUNCIONALIDADES

Entidade em Memória

Para que as buscas de uma determinada entidade seja feita com performance máxima, basta ativar o gerenciamento da entidade em memória. O xMova manterá todos os registros da entidade em memória deixando a leitura dos dados muito rápida, pois não terá que lê-la do banco de dados.

Na primeira vez que uma entidade de memória for usada o xMova carregará os dados dela do banco em memória, e isso poderá demorar um pouco dependendo da quantidade de dados. Enquanto estiver lendo os dados do banco e colocando na memória, aparecerá uma tela bloqueando a tela informando ao usuário que aguarde o carregamento dos dados.

Para ativar o gerenciamento em memória de uma entidade, basta adicionar o atributo memory na entidade.

Exemplo de Entidade em Memória:

Servico sync=in memory
  id inc
  nome String
Frente
  id inc
  nome String

No exemplo acima, a entidade Servico será mantida em memória.

Alteração dos Dados de Configuração

Essa seção descreve os passos necessários para alterar os dados de configuração do aplicativo sem a necessidade de realizar o procedimento de limpeza.

Primeiro é preciso criar a opção Trocar Líder, que ficará no menu da tela inicial.

No App:

Main main entity=AuthInput fields=descricaoObra,descricaoLider,descricaoCelular
  actions
    Boletim Ok
      crud Boletim
    TrocarLider
      Integer numApontBoletim = rowCount table=Boletim_SyncOut
      Integer numApontApontamento = rowCount table=ApontamentoFuncionario_SyncOut
      if numApontBoletim + numApontApontamento + numApontFuncionarios + numApontLocation == 0
        crud ChangeLider
      else
        toast Sincronize os Dados!

A opção TrocarLider deverá ser adicionada no actions do Main.

Qualquer alteração dos dados de configuração somente poderá ser feita se não houver dados offline.

Portanto é necessário realizar uma validação em todas as Entidades que realizam ´´sync=out´´ do aplicativo, confirmando se há algum registro aguardando para ser enviado.

Isso é realizado obtendo a quantidade de registros de todas as entidades do tipo _SyncOut do aplicativo. Deve-se então atribuir a um campo Integer o resultado do rowCount de cada Entidade. Por exemplo, para a Entidade Boletim foi criado o Integer numApontBoletim, que recebe o valor do rowCount da Entidade Boletim_SyncOut.

Após obter o rowCount de todas as entidades, é realizada uma validação, somando todos os valores.

Se o resultado for maior que zero, significa que existem dados gravados e a alteração dos dados não poderá ser realizada. Nesse caso uma mensagem será mostrada, pedindo para sincronizar os dados.

Se o valor for igual a zero, significa que não há dados gravados, e alteração poderá ser realizada. Nesse caso, um CRUD será executado. Esse CRUD é relacionado a uma Entidade que deverá ser definida no modelo, conforme exemplo abaixo.

No Model:

Auth
  obra int
  lider int
  celular int

AuthInput notSavedMessage
  obra obra
  lider int
  celular int

ChangeLider notSavedMessage
  lider int
  events
    afterInsert
      AuthInput authInput = selectFirst from AuthInput
      authInput.lider = lider
      save authInput
      Auth auth = selectFirst from Auth
      auth.lider = lider
      save auth
      dropTable AppEntityVer
      dropTable Funcionario
      exit

No exemplo acima, temos as entidades envolvidas nessa alteração: Auth, AuthInput e ChangeLider.

O Auth é a Entidade que contém as informações que serão enviadas no JSON de todos os apontamentos.

O AuthInput é a Entidade preenchida na primeira vez que o aplicativo é instalado.

O ChangeLider é a Entidade que será criada para alterar algum valor do Auth e AuthInput. Nesse exemplo, será alterado o líder.

Quando executado, o ChangeLider irá pedir o campo líder. Após o preenchimento desse campo, o evento afterInsert será executado.

O AuthInput é carregado e o valor de seu campo líder é alterado para o valor informado. O Auth é carregado e seu campo líder é alterado para o valor informado.

Se houver a necessidade de obter alguma Entidade após essa alteração, é preciso apagar os valores que estão no celular e obtê-los novamente.

Nesse exemplo, a lista de Funcionários vinculados a líder será apagada e obtida novamente. Portanto deve-se apagar a entidade de versões e a de Funcionários. Para isso utiliza-se o comando dropTable + o nome da entidade.

Por fim é executado o comando exit, que fecha o aplicativo. Isso é necessário para os dados sejam obtidos assim que for iniciado.

Auth e AuthInput

Danger

No update essas entidades Auth e AuthInput são mantidas para não ter que digitar os dados de instalação novamente a cada update. Se alterar os campos dessas entidades, visto que elas não são apagadas, o modelo tem campos diferentes dos campos da entidade, corrompendo os dados. Caso seja necessário alterar os campos das entidades Auth e AuthInput, será necessário desisntalar e fazer a instalação do fluxo novamente.

Validação On-Line

O xMova pode fazer validação online dos valores inseridos nos campos de uma entidade. Basta adicionar ao campo o atributo onlineValidate=obra.

Exemplo:

Boletim
  boletim Boletim
  data now timeTypeField=tipoData
  codigoOperador int onlineValidate=operador
  idOperador int notFill
  nomeOperador String notFill

Retorno de Dados Validados

Danger

O xMova Server enviará para o sistema de terceiro o registro inteiro para validação. O sistema deve retornar novamente o sistema inteiro, com os mesmos dados que foram enviados, adicionando ao registro dados adicionais que foram validados. No exemplo acima, deverá ser retornado para o xMova os valores nos campos idOperador e nomeOperador, bem como todos os dados que foram enviados.

O sistema de terceiro deve retornar os seguites status:

  • Sucesso: status=0
  • Erro: status=1
  • Falha: status>=2

Mensagem de Erro de Validação

Quando a validação retornar um status 1 (erro), o xMova mobile pega a mensagem de erro na seguinte ordem:

  1. entity.Boletim.codigoOperador.onlineValidateError
  2. msg.onlineValidateError (obrigatório)

Mensagem de Falha de Validação

Quando a validação retornar um status diferente, ou seja >= 2 (falha), o xmova pega a mensagem na seguinte ordem:

  1. entity.Boletim.codigoOperador.onlineValidate.{STATUS}
  2. entity.Boletim.codigoOperador.onlineValidateFail
  3. msg.onlineValidateFail (obrigatório)

BARCODE

O xMova pode ler codigo de barras de diversos tipo por meio da câmera do celular.

QRCODE

Para ler as informações de um QRCODE, deve ser alterado o APP do fluxo, definindo no reader a propriedade camera, que irá definir o comportamento da leitura. Para ler com QRCODE deve ser adicionado á propriedade camera o atributo type e sizes, onde type define o tipo de leitura( ex: QRCODE,CODE93,CODE128) e o sizes define o numero de caracteres que o QRCODE/BARCODE representa. Quando é definido um valor ao sizes, será feita a busca por códigos de barras, ou barcode, que representam aquele numero de caracteres definido, não reconhcendo QRCODE/BARCODE que possuam mais ou menos dígitos e os entendendo como invalidos. Caso não seja definido o atributo sizes, ele irá ler quaisquer QRCODE/BARCODE que lhe for lhe for apresentado independente de seu tamanho. segue um exemplo de como ficará no APP No exemplo a seguir foi definido no app que a funcionalidade de leitura somente reconhcerá QRCODES e que representem caracteres de 9 digitos.

Exemplo:

App appCode=LIDER periodicSync
  id 555
  name ConstruMobil
  reader
        camera types=QRCODE sizes=9 minQuality=20

Caso haja a necessidade de aceitar outras quantidades de caracteres, é necessário informá-las no atributo sizes.

No exemplo a seguir, o aplicativo aceita QRCODES de tamanho 5 e de tamanho 9.

Exemplo:

App appCode=LIDER periodicSync
  id 555
  name ConstruMobil
  reader
        camera types=QRCODE sizes=5,9

Para que um campo possa ser lido a partir de um QRCODE/BARCODE, deve ser definido o campo como long e adicionado ao campo o atributo reader com o valor (reader=cam). No exemplo a seguir mostra a definição de um campo(code) de uma entidade(TesteQRCode) no model, que será lido de um QRCODE que será lido pela câmera do celular e mostrado uma mensagem com o valor do campo lido.

Exemplo:

TesteQRCode sync=out
  code long reader=cam
  fieldEvents
        onValidate
          code
            return confirm lang=custom.msgQRCode vars=qrcode:code

Sincronismo Off-line por Bluetooth

Master: Recebimento de Dados de Cadastro off-line

O celular que envia dados de cadastro sync=in para outro é chamado de Master. O que recebe os dados é chamado de Slave. No sincronismo via Bluetooth ou Http off-line ocorre tanto o envio dos dados off-line para o master, quanto o recebimento dos dados de cadastro do master para o slave, numa mesma requisição Bluetooth ou HTTP.

Para tornar um fluxo master, defina a linha master no App. No atributo appCodes você define quais os appCodes que esse master vai atender. Se um fluxo Slave com appCode=LIDER tentar enviar dados para um master que não definiu esse appCode, ele apenas conseguirá fazer o envio dos dados offline, mas não o recebimento dos dados sync=in.

Veja um exemplo de como definir um fluxo como Master:

App appCode=LIDER
  id 555
  name ConstruMobil

Main main

master appCodes=A,B
  A
    Servico slaveName=Serv
      onInit
        Equipamento equipamento = auth.equipamento
        Familia familia = selectLast from Familia where id == :equipamento.familia
      onFilter
        Integer i = 0
        if id in familia.servicos && familia.flagPrincipal == auth.familiaPrincipal
          return true
    Familia
      onFilter
        log filtrando...

Entidade AuthSlave

No modelo do fluxo do Master é necessário definir a entidade auth de todos os fluxos de slaves aceitáveis. A definição deve seguir o padrão de nome AuthSlave_ + AppCode do slave. Exemplo: AuthSlave_L. Os campos dessa entidade devem ser idênticos aos campos da entidade auth original do Slave.

Evento onFilter

Para cada appCode definido no master, pode-se definir o evento onFilter para cada entidade. Dessa forma, o Master pode obter os dados completos de uma entidade do servidor, mas enviar apenas uma parte desses dados que interessem ao Slave. Esse evento será chamado para cada registro da entidade em que ele foi definido. São padrão no evento onFilter as variáveis record, auth, e todas as variáveis locais definidas no evento onInit.

Variável record

É o registro que está sendo filtrado no momento. É também o context do evento, podendo ser acessados os campos diretamente. Em vez de digitar if record.familia == 5 pode-se usar diretamente o nome do campo if familia == 5.

Variável auth

É o registro inteiro, com todos os dados do auth do fluxo Slave. Esse registro auth é enviado pelo Slave no início da requisição. Dessa forma, pode-se filtrar os dados de acordo com alguma informação do auth do fluxo do Slave, enviando apenas dados que interesse a ele.

Evento onInit

O evento onInit pode ser definido em cada entidade do Slave. Ele é executado antes de começar a percorrer os registros da entidade que será enviada. Todas as variáveis definidas nesse evento poderão ser usadas no evento onFilter como se fossem variáveis locais definidas lá no onFilter, pois os valores delas são copiados do evento onInit para o evento onFilter. Normalmente usa-se esse evento para pré-carregar registros do banco que serão usados massivamente no evento onFilter.

GPS

Para implementar o GPS no fluxo xMova é necessário adicionar a entidade Location no Modelo e configurar o location no App.

No Modelo:

Location sync=out
  lat double
  long double
  alt double
  gpsTime long

No App:

App
  location minTime=1m minDistance=100 minLastTime=10m
  • minTime: Intervalo de tempo para o core atualizar a posição atual do GPS
  • minDistance: Distância mínima para o core atualizar a posição atual do GPS
  • disableNotifyMessage: Desabilita a mensagem que é exibida ao usuário quando o aplicativo tenta usar o GPS e o mesmo está desativado
  • disableGpsRestartOnResume: Desabilita a funcionalidade que faz com que o GPS seja reiniciado cada vez que o aplicativo sai do estado de background para foreground. (API Android chama o método onResume).
  • minLastTime: É o tempo da última posição válida obtida do GPS que o apontamento pode utilizar. Se tiver configurado para 10 minutos e a última posição válida obtida do GPS for de 20 minutos, o Location nesse caso será nulo, ou seja, não será enviado junto ao apontamento. O tempo ideal estipulado para esse campo é 10 minutos.

Se definir minTime como 1h e minDistance 100m, os dois valores serão tratado como AND, ou seja, só atualizará quando os dois casos forem verdadeiros. Após 1h e tendo deslocado pelo menos 100m. Se passou 2h, mas andou somente 50m, a posição não será atualizada.

Se o minTime for 0 e o minDistance for 100m, o GPS será atualizado sempre que ultrapassar 100m, independente de horário.

Se o minTime for 1h e o minDistance for 0m, o GPS será atualizado a cada hora, independente da distância.

Apontamento com GPS

Para enviar a informação do GPS em uma entidade basta adicionar um campo do tipo Location em tal entidade.

No Modelo:

Boletim sync=out
  id inc
  idSeqBoletim Long
  location Location inlineData

Apontamento sync=out
  id inc
  idSeqApontamento Long
  location Location inlineData

Note

Utilize inlineData para que o registro de Location não fique separado do apontamento.

Exemplo do JSON que será criado nos apontamentos acima descritos:

Boletim
  {
    "id":1,
    "idSeqBoletim":"1023043202340",
    "location":
      {
        "lat": -23.1935728
        "long": -45.8929331,
        "alt": 0.0,
        "gpsTime": 1406721814242,
      }
  }

Apontamento
  {
    "id":1,
    "idSeqApontamento":"1023234402340",
    "location":
      {
        "lat": -23.1935728
        "long": -45.8929331,
        "alt": 0.0,
        "gpsTime": 1406721814242,
      }
  }

Tracking

Para Tracking deve-se adicionar o atributo tracking no location do app, e adicionar minDistance = 0m. O minTime` também deve ser configurado, e seu valor deve ser maior que zero.

Utilize o evento onInsert para adicionar informações adicionais no apontamento ou executar outras instruções antes de um Tracking ser inserido. No exemplo abaixo adicionamos a hora local ao Location no evento onInsert.

No App:

App
  location minTime=1m minDistance=0 minLastTime=10m tracking
    onInsert [opcional]
      dataHora = currentDate

No Model:

Location sync=out
  lat double
  long double
  alt double
  gpsTime long
  dataHora now

Mensageria

O xMova pode receber e enviar mensagens.

Recebimento de Mensagem

Para receber mensagens, precisamos ativar o sync periódico no xmova, de forma que ele faça sync mesmo que não tenha dados offline. O tempo de intervalo entre os sync será o mesmo tempo definido em syncInterval no app. Para ativar o sync periódico, basta adicionar o atributo periodicSync no App.

Nos sync offline normalmente o xMova não retorna qualquer entidade, apenas envia os dados offline. Como o objetivo do sync periódico é retornar as mensagens, precisamos definir na entidade que receberá as mensagens sync=BackgroundIn para que o xMova retorne essa entidade em todos os sync foreground ou background.

Exemplo:

App appCode=LIDER periodicSync
  id 555
  name ConstruMobil
  afterSync
    show MensagemScr

MainSrc …
  ...

MessageScr message title=Mensagem entity=Mensagem messageField=msg dateField=data fromField=from
  actions
    ok
      INSERT INTO ResumoMensagem (texto,data,remetente,enviada) VALUES (:texto,:data,:remetente,false)

Envio de Mensagem

A funcionalidade de envio de mensagens é feita com cadastro normal do xmova, como se fosse um apontamento.

Para o xMova ficar solicitando mensagens

No App:

App syncInterval=1m periodicSync
...
#No events, adicionar:
afterSync
  show MessageScr

Main ...
  actions
    #Adicionar a Action...
    Mensagem
      crud CentralMensagem
#Adicionar a Screen
MessageScr message title=Mensagem entity=MensagemRecebida messageField=texto dateField=data fromField=remetente
  actions
    ok
      INSERT INTO ResumoMensagem (texto,data,remetente,enviada) VALUES (:texto,:data,:remetente,false)

#Adicionar a Screen
Adicionar em Constants
  TipoMensagemEnviarSelecionar 1
  TipoMensagemEnviarEscrever 2
  TipoMensagensEnviadas 1
  TipoMensagensRecebidas 2
  TipoMensagemEnviar 3

#Adicionar no InstallData
InstallData
  TipoMensagemEnviar
    1 Selecionar
    2 Escrever
  TipoMensagens
    1 Enviadas
    2 Recebidas
    3 Enviar

No Model:

MensagemCadastro sync=in EmptyVerify=false
  id int
  descricao Str
MensagemRecebida sync=backgroundIn EmptyVerify=false
  id int
  data Str
  texto Str
  remetente Str
MensagemEnviada sync=out cleanupDays=15 notSavedMessage
  data Now
  texto text
TipoMensagemEnviar
  id int
  descricao Str
TipoMensagens
  id int
  descricao Str
ResumoMensagem cleanupDays=15
  texto Str
  data Str
  remetente Str
  enviada boolean
CentralMensagem cleanupDays=5 notSavedMessage
  id inc
  tipoMensagens TipoMensagens
  tipoEnviar TipoMensagemEnviar fillCondition="tipoMensagens == %TipoMensagemEnviar"
  data Now
  mensagemCadastro MensagemCadastro fillCondition="tipoEnviar == %TipoMensagemEnviarSelecionar"
  mensagemTexto text fillCondition="tipoEnviar == %TipoMensagemEnviarEscrever"
  enviadas ResumoMensagem fillCondition="tipoMensagens == %TipoMensagensEnviadas"
  recebidas ResumoMensagem fillCondition="tipoMensagens == %TipoMensagensRecebidas"
  fieldEvents
    afterFill
      mensagemCadastro
        INSERT INTO MensagemEnviada (data ,texto ) VALUES (:data,:mensagemCadastro.descricao)
        INSERT INTO ResumoMensagem (texto,data,enviada) VALUES (:mensagemCadastro.descricao,:data, true)
        sync background
      mensagemTexto
          INSERT INTO MensagemEnviada (data ,texto ) VALUES (:data,:mensagemTexto)
          INSERT INTO ResumoMensagem (texto,data,enviada) VALUES (:mensagemTexto,:data, true)
          sync background
    filterListRecord
      enviadas
        if (listRecord.enviada == false)
          return false
      recebidas
        if (listRecord.enviada == true)
          return false

#Onde desejar exibir a opção de Mensagens, adicionar na entidade pai:
Boletim
  crudActions
    Mensagens
      fill centralMensagem

No Lang:

EntityLabel.CentralMensagem = Central Mensagem
EntityLabel.MensagemCadastro = Cadastro
EntityLabel.TipoMensagens = Central Mensagens
EntityLabel.TipoMensagemEnviar = Enviar
FieldLabel.CentralMensagem.enviadas = Enviadas
FieldLabel.CentralMensagem.recebidas = Recebidas
FieldLabel.CentralMensagem.mensagemTexto = Mensagem
EntityLabel.ResumoMensagem = Mensagens
FieldLabel.ResumoMensagem.texto= Texto
FieldLabel.ResumoMensagem.data= Data
FieldLabel.ResumoMensagem.remetente= Remetente

Mensagem Agendada

Com o atributo MessageScheduled e a adição de alguns campos obrigatórios é possível receber dados que serão usados para exibir uma mensagem em um determinado horário (todos os dias) ou então em uma determinada data uma única vez.

No App:

App syncInterval=1m periodicSync

No Model:

ScheduledMessage sync=backgroundIn messageScheduled
    id int
    title Str
    text Str
    hour Str
    date Str
    fixedPoint int
    executed Date
    scheduled Date
    events
        onShowScheduledMessage
            log title
            log scheduled
            log executed
  • O campo id é obrigatório, o Core faz uso deste campo para manipular os dados das mensagens a serem agendadas e para encontrá-las depois que foram exibidas para deletar ou fazer o update caso seja uma mensagem que tenha repetição.
  • O Core irá buscar o primeiro campo do tipo String para fazer uso como título da mensagem e o campo abaixo para o conteúdo da mensagem, no caso do exemplo acima o campo title será usado como título da mensagem e o campo text será usado como o conteúdo da mensagem. (Obs.: os campos podem ter outro nome, desde que sejam os primeiros campos do tipo String).
  • O fluxo deve conter um campo de nome hour do tipo String ou um campo date; que pode ser String, long ou Date, ou conter os dois campos. Quando o aplicativo contiver os dois campos será dada a preferência para o campo hour caso o valor seja vazio então será usado o valor do campo date para fazer o agendamento da mensagem.
  • (Obs.: Caso nenhum valor seja encontrado para o campo hour ou date a mensagem não será agendada, caso o Core use o valor do campo date e a data for menor do que a data atual a mensagem não será agendada e caso o Core use o valor do campo hour e o horário for menor do que o horário atual a mensagem será agendada para ser executada no próximo dia).
  • Sempre que o valor do campo hour é utilizado para o agendamento da mensagem o Core reagenda a mensagem para ser executada sempre no mesmo horário, todos os dias.
  • O campo fixedPoint do tipo inteiro indica se deve ou não existir um fixed point salvo no aplicativo para que a mensagem seja exibida. Caso o valor seja 1 o aplicativo somente irá exibir a mensagem se tiver um fixed point salvo.
  • O formato esperado para o campo hour é HH:mm ou HH:mm:ss.
  • O formato esperado para o campo date é yyyyMMddHHmmssSSS
  • Caso o campo executed exista o Core atribui a ele o valor de quando foi a última vez que a mensagem foi exibida e confirmada pelo usuário
  • Caso o campo scheduled exista o Core atribui a ele o valor de quando a mensagem foi agendada
  • O evento ‘onShowScheduledMessage’ é executado antes da mensagem ser exibida, caso o evento retorne ‘false’ a mensagem não é exibida. O contexto do evento é o registro da mensagem que será exibida, então podem ser usados os valores dos campos da entidade para comparações.
  • Para calcular o tempo para agendar a exibição da mensagem o Core faz uso do ERT (Elapsed Real Time) que registra o tempo de atividade do aplicativo desde o último boot e a diferença em millisegundos da data atual válida para a data de execução da mensagem.
  • Sempre que o dispositivo é desligado ou há uma mudança da hora válida dos tipos ‘D ou M’ para os tipos ‘G ou S’ todos os eventos são reagendados.
  • Sempre que o dispositivo recebe novos dados da entidade para agendamento de mensagem todos as mensagens ainda não exibidas são canceladas e são agendadas todas mensagens recebidas.
  • Caso o Core não encontre o registro no banco de dados no momento de exibir a mensagem agendada a mensagem agendada é cancelada.

No Lang:

FixedKeyMsgScheduledScreenTitle = Mensagem (Valor padrão)
FixedKeyMsgScheduledHour = Horário  (Valor padrão)
FixedKeyMsgScheduledTitle = Título (Valor padrão)
FixedKeyMsgScheduledMessage = Mensagem (Valor padrão)
FixedKeyMessageSourceScreenMessageConfirmOK = OK (Valor padrão)