DS_PATHAPKDOW — Caminho do APK do Pedido Mobile para Download
Tela de configuração: MFA001 — Parâmetros de Faturamento Localização: Parâmetros → aba Pedido Mobile → grupo Caminho do Apk Pedido Mobile Tabela:
PARMFATUR.DS_PATHAPKDOWTipo: Texto — caminho absoluto do arquivo.apkno servidor (VARCHAR(500), nullable) —TDBMemoReadOnly preenchido viaTOpenDialogValor padrão: vazio/NULL (o campo não é preenchido noAfterInsertdo dataset e o DDL não possuiDEFAULT— verUdmMFA001.pasedocs/schema/tables/PARMFATUR.sql)
Telas impactadas
O parâmetro é apenas configurado na MFA001. Quem o consome em runtime é a API REST do Pedido Mobile (projeto Java ERPPedidoRestAS), responsável por servir o APK aos dispositivos Android via HTTP — a tela ERP Desktop não lê este campo em nenhum outro módulo além da própria MFA001.
| Módulo / Componente | Código | Papel |
|---|---|---|
| Parâmetros de Faturamento | MFA001 | Tela produtora — grava o caminho absoluto do arquivo .apk |
API REST Pedido Mobile — ParametroSmartDAO | source/Server/PedidoMobile/ERPPedidoRestAS | Consumidor — lê PARMFATUR.DS_PATHAPKDOW no SELECT do parâmetro e injeta em PathServidor.INSTANCE.setDsPath(...) durante a sincronização |
API REST Pedido Mobile — DownloadResource (servlet /download/*) | source/Server/PedidoMobile/ERPPedidoRestAS | Consumidor — abre new File(filePath), transmite os bytes do APK no response HTTP (Content-Disposition: attachment) |
Observação — Homônimo: há um campo similar
PARMFATUR.DS_PATHDOWNAPKCOLETALEITE(também editado na MFA001, na mesma aba), porém destinado ao APK de Coleta de Leite e consumido por outra API (CaptacaoMobile). Não confundir:DS_PATHAPKDOWé exclusivamente o APK do Pedido Mobile.
Procedures impactadas
Não há procedures/views que referenciem DS_PATHAPKDOW. O campo é acessado apenas por SELECT direto no Java (ParametroSmartDAO.TEXTO_PARAMETROS).
Campos envolvidos
| Campo | Descrição |
|---|---|
PARMFATUR.DS_PATHAPKDOW | Este parâmetro. Caminho absoluto (no servidor onde o WildFly está publicado) do arquivo .apk do Pedido Mobile — VARCHAR(500) |
PARMFATUR.DS_PATHDOWNAPKCOLETALEITE | Campo irmão, na mesma aba da MFA001 — caminho do APK de Coleta de Leite (outra API) |
Comportamento / Uso
1. Configuração na MFA001 (aba Pedido Mobile)
A aba possui um TGroupBox "Caminho do Apk Pedido Mobile" com:
mmDS_PATHAPKDOW: TDBMemo— somente-leitura (ReadOnly = True),MaxLength = 240, vinculado ao campo viaDataField = 'DS_PATHAPKDOW'.btnDS_PATHAPKDOW: TBitBtn— Caption "Selecione Caminho do APK Pedido Mobile", Hint "Abrir Arquivo" — chamaTOpenDialoge grava oFileNameescolhido no campo.
Código responsável pelo clique no botão (source/MFA001/UMFA001.pas linhas 1760-1771):
procedure TfrmMFA001.btnDS_PATHAPKDOWClick(Sender: TObject);
begin
AbrirArquivo.Filter := 'Aplicativos (*.apk)|*.APK';
AbrirArquivo.Title := 'Selecione o APk do Pedido Mobile';
dmMFA001.tabPARMFATUR.Edit;
if (AbrirArquivo.Execute) then
dmMFA001.tabPARMFATURDS_PATHAPKDOW.AsString := AbrirArquivo.FileName
else
dmMFA001.tabPARMFATURDS_PATHAPKDOW.AsString := '';
end;
Atenção: ao cancelar o
TOpenDialogo campo é zerado (string vazia). Para preservar o caminho existente, o usuário deve evitar clicar no botão.
Simulação passo a passo
- Copie o arquivo do APK do Pedido Mobile para o servidor onde a API
ERPPedidoRestASestá publicada (mesmo host do WildFly), ex.:C:\Junsoft\Mobile\junsoftpedido.apk. - Abra MFA001 → aba Pedido Mobile.
- Clique em Selecione Caminho do APK Pedido Mobile (
btnDS_PATHAPKDOW). - No filtro "Aplicativos (*.apk)", selecione o arquivo → o caminho completo é gravado em
mmDS_PATHAPKDOW(somente-leitura,MaxLength=240). - Salve (F6) — a
PARMFATURrecebeUPDATE ... SET DS_PATHAPKDOW = :DS_PATHAPKDOW.
Resultado esperado: caminho absoluto armazenado em PARMFATUR.DS_PATHAPKDOW. No próximo login do app Pedido Mobile (ou ao acionar a opção de atualização), o APK passa a ser baixado por esse caminho.
2. Consumo pela API Pedido Mobile (ParametroSmartDAO + PathServidor)
Durante a sincronização de parâmetros do dispositivo, o DAO lê o campo diretamente no SELECT e coloca o caminho em um enum singleton (PathServidor.INSTANCE):
source/Server/PedidoMobile/ERPPedidoRestAS/src/main/java/br/com/junsoft/DAO/ParametroSmartDAO.java — linhas 25 e 130:
// SELECT dos parâmetros:
+ " P.ST_VARIOSVENDEDORES, P.DS_PATHAPKDOW, P.CD_TABPRECO, "
...
// Após ler o ResultSet:
PathServidor.INSTANCE.setDsPath(rs.getString("DS_PATHAPKDOW"));
O singleton simplesmente guarda a string em memória (source/Server/PedidoMobile/ERPPedidoRestAS/src/main/java/br/com/junsoft/sincronizacao/PathServidor.java):
public enum PathServidor {
INSTANCE;
private String dsPath;
public String getDsPath() { return dsPath; }
public void setDsPath(String dsPath) {
if (dsPath != null) { this.dsPath = dsPath; }
}
}
Observação — estado global:
PathServidoré um enum singleton JVM. O valor fica cacheado no WildFly até que um novo dispositivo se sincronize e sobrescreva (ou até o servidor ser reiniciado). Por isso, após alterar o parâmetro na MFA001, talvez seja necessário um novo login/sync de dispositivo para que o cache seja atualizado — ou oDownloadResourceo recarrega na demanda (ver abaixo).
3. Download do APK (DownloadResource — servlet /download/*)
Quando o app Android (ou qualquer cliente HTTP) chama GET /download/{idEmpresa}/{arquivo}, o servlet DownloadResource transmite o arquivo apontado por PARMFATUR.DS_PATHAPKDOW.
source/Server/PedidoMobile/ERPPedidoRestAS/src/main/java/br/com/junsoft/resources/DownloadResource.java — linhas 34-82:
if (PathServidor.INSTANCE.getDsPath() == null) {
try (Sessao sessao = ConnectionFactory.createSessao(Integer.parseInt(path[3]))) {
new ParametroSmartDAO().buscar(sessao, Integer.parseInt(path[3]));
} catch (Exception ex) {
...
}
}
String filePath = PathServidor.INSTANCE.getDsPath();
File downloadFile = new File(filePath);
FileInputStream inStream = new FileInputStream(downloadFile);
String mimeType = context.getMimeType(filePath);
if (mimeType == null) { mimeType = "application/octet-stream"; }
response.setContentType(mimeType);
response.setContentLength((int) downloadFile.length());
response.setHeader("Content-Disposition",
String.format("attachment; filename=\"%s\"", downloadFile.getName()));
OutputStream outStream = response.getOutputStream();
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = inStream.read(buffer)) != -1) {
outStream.write(buffer, 0, bytesRead);
}
Fluxo do servlet:
- Se
PathServidor.getDsPath()ainda énull, o servlet força umParametroSmartDAO.buscar(...)passando oIdEmpresaextraído do path (posição 3 doURI) — assim ele popula o cache sob demanda. - Abre o arquivo em
new File(filePath)e transmite os bytes ao cliente comContent-Disposition: attachment; filename="<nomeArquivo>". - O MIME type é resolvido pelo
ServletContexte faz fallback paraapplication/octet-stream.
Simulação passo a passo (lado dispositivo)
- Garanta que
PARMFATUR.DS_PATHAPKDOWaponta para um arquivo existente no servidor (ex.:C:\Junsoft\Mobile\junsoftpedido.apk). - No app Pedido Mobile, acione a opção de atualização/download do APK (ou acesse diretamente
http://<servidor>:<porta>/ERPPedidoRest/download/<idEmpresa>/junsoftpedido.apk). - A API abre o arquivo no caminho configurado e transmite os bytes como
attachment.
Resultado esperado: o APK é enviado ao cliente com Content-Disposition: attachment (nome = último segmento do path). Se o caminho estiver em branco ou apontar para um arquivo inexistente, o new File(...)/FileInputStream lança FileNotFoundException, que sobe como 500 Internal Server Error ao cliente (log do WildFly) — o usuário final recebe falha no download.
Formato esperado
| Regra | Detalhe |
|---|---|
| Tipo de dado (DDL) | DS_PATHAPKDOW DOM_VARCHAR500 — coluna nullable, sem DEFAULT (ver docs/schema/tables/PARMFATUR.sql linha 208) |
| Tipo de dado (FireDAC) | TStringField com Size = 500 em UdmMFA001.dfm linhas 1872-1876 |
| Componente na tela | TDBMemo ReadOnly (MaxLength = 240 — inconsistente com o Size=500 do banco, limita o usuário a 240 caracteres embora o banco aceite até 500) |
| Como é preenchido | Clique em btnDS_PATHAPKDOW → TOpenDialog (filtro "Aplicativos (.apk) |
| Cancelar o diálogo | Apaga o caminho (grava string vazia). Para preservar, o usuário deve não clicar no botão |
| Caminho absoluto vs. relativo | O TOpenDialog retorna caminho absoluto. O servlet DownloadResource passa o valor direto para new File(filePath) — precisa ser um caminho válido no servidor do WildFly/API, não na estação do cliente que salvou |
| Extensão esperada | Filtro do diálogo aceita apenas *.apk (case-insensitive). Tecnicamente o campo é texto livre — qualquer caminho pode ser gravado; o servlet apenas tenta abrir como arquivo |
| Validação no AfterPost/OnValidate | Não há. O campo não possui evento OnValidate. Um caminho inválido só é detectado no download (HTTP 500 no servlet) |
| Cache em memória (JVM) | PathServidor.INSTANCE (enum singleton) armazena a string e só é atualizada quando um novo ParametroSmartDAO.buscar(...) é executado (nova sincronização ou chamada ao DownloadResource quando dsPath == null). Após alterar o parâmetro na MFA001, considere reiniciar o WildFly ou sincronizar um dispositivo para forçar o refresh |
| Ambiente | O caminho deve ser resolvível pelo processo Java do WildFly. Caminhos UNC (\\SERVIDOR\Share\app.apk) funcionam se o serviço tiver permissão de rede; caminhos locais (C:\...) precisam existir na própria máquina do servidor |
Referências no Código Fonte
Tela MFA001 (configuração)
source/MFA001/UMFA001.dfmlinhas 12078-12136 — abapagPedidoMobile(Caption='Pedido Mobile'), grupogrpDS_PATHAPKDOW(Caption=' Caminho do Apk Pedido Mobile '),mmDS_PATHAPKDOW: TDBMemo(ReadOnly, MaxLength=240, DataField='DS_PATHAPKDOW'),btnDS_PATHAPKDOW: TBitBtn(Caption='Selecione Caminho do APK Pedido Mobile')source/MFA001/UMFA001.paslinhas 502-504 — declaração degrpDS_PATHAPKDOW,mmDS_PATHAPKDOW,btnDS_PATHAPKDOWsource/MFA001/UMFA001.paslinha 756 — assinaturaprocedure btnDS_PATHAPKDOWClick(Sender: TObject);source/MFA001/UMFA001.paslinhas 1760-1771 —btnDS_PATHAPKDOWClick: aplica filtro'Aplicativos (*.apk)|*.APK', executaTOpenDialoge grava/limpatabPARMFATURDS_PATHAPKDOW.AsStringsource/MFA001/UdmMFA001.paslinha 265 —tabPARMFATURDS_PATHAPKDOW: TStringFieldsource/MFA001/UdmMFA001.paslinhas 434-606 —tabPARMFATURAfterInsert: o campo não é inicializado (valor padrão = vazio)source/MFA001/UdmMFA001.dfmlinhas 278, 1872-1876 (definição do campoSize=500), 2436, 2608 (INSERT), 2859 (UPDATE), 3158 (FetchRow) — CRUD do parâmetro
Consumidor — API REST Pedido Mobile (Java / WildFly)
source/Server/PedidoMobile/ERPPedidoRestAS/src/main/java/br/com/junsoft/DAO/ParametroSmartDAO.javalinha 25 —SELECT ... P.DS_PATHAPKDOW, ...emTEXTO_PARAMETROSsource/Server/PedidoMobile/ERPPedidoRestAS/src/main/java/br/com/junsoft/DAO/ParametroSmartDAO.javalinha 130 —PathServidor.INSTANCE.setDsPath(rs.getString("DS_PATHAPKDOW"));source/Server/PedidoMobile/ERPPedidoRestAS/src/main/java/br/com/junsoft/sincronizacao/PathServidor.java— enum singleton (INSTANCE) comdsPath/getDsPath/setDsPath(ignoranullemsetDsPath)source/Server/PedidoMobile/ERPPedidoRestAS/src/main/java/br/com/junsoft/resources/DownloadResource.javalinhas 25-82 — servlet@WebServlet("/download/*"), força reload doPathServidorquandonull, transmitenew File(filePath)comoattachment
DDL da tabela
docs/schema/tables/PARMFATUR.sqllinha 208 —DS_PATHAPKDOW DOM_VARCHAR500,(nullable, semDEFAULT)