Como estender o aplicativo móvel offline do Consumer Goods Cloud para acionar aplicativos nativos de navegação, mensageria e telefonia através da API Facade.startThirdPartyAsync.
Na rotina diária no varejo, o representante de vendas ou promotor divide seu tempo entre pesquisas de gôndola, pedidos e o deslocamento entre pontos de venda (PDVs). Durante esse trajeto, abrir o navegador GPS para traçar a rota ou enviar uma mensagem no WhatsApp confirmando o recebimento de mercadorias com o gerente da loja são tarefas recorrentes.
Quando a aplicação móvel funciona isolada, o promotor precisa copiar o endereço manualmente, sair do aplicativo, colar os dados no Google Maps ou Waze e depois repetir o processo para encontrar o contato no mensageiro. Esse fluxo gera atrito e abre espaço para erros de digitação.
Para integrar a experiência em campo, o framework do Salesforce Consumer Goods Cloud (CGC) Modeler oferece o recurso de App2App Communication (comunicação entre aplicativos).
Por meio desse protocolo, a aplicação offline do Consumer Goods Cloud invoca esquemas de URL nativos (URI Schemes ou Intent URLs) registrados no Android e no iOS. Usando a API Facade.startThirdPartyAsync, é possível transferir parâmetros contextuais (como coordenadas geográficas e mensagens de texto) sem depender de conexão de internet e sem violar a integridade do banco SQLite local (app.db3).
1. Arquitetura do App2App: do clique ao handover do sistema operacional
A comunicação entre aplicativos no Modeler Mv2 ocorre por transferência de controle (handover) ao sistema operacional. Quando o usuário clica em um botão na interface do app, o runtime do Consumer Goods Cloud solicita ao sistema operacional a abertura do aplicativo cadastrado como padrão para aquele protocolo.
O fluxo de execução compreende quatro etapas:
- UserInterface (
.userinterface.xml): Exibe o botão ou item de menu cuja visibilidade é condicionada à existência de coordenadas válidas no cadastro. - ProcessFlow (
.processflow.xml): Captura o evento de clique na interface (View Action Event) e aciona uma ação lógica (actionType="LOGIC"). - Business Logic (
.bl.js): Lê os dados do Business Object, higieniza os valores, monta a string do URI Scheme e executa a API nativaFacade.startThirdPartyAsync(url, options). - Sistema operacional (Android Intent / iOS URL Scheme): O dispositivo móvel suspende temporariamente o app do Consumer Goods Cloud e abre o aplicativo correspondente (Google Maps, Waze ou WhatsApp).
┌─────────────────────────────────────────────────────────────┐
│ UserInterface Contract (.userinterface.xml) │
│ <MenuItem name="BtnNavigate" image="Directions" ... /> │
└──────────────────────────────┬──────────────────────────────┘
│ Event: NavigateTo
▼
┌─────────────────────────────────────────────────────────────┐
│ ProcessFlow Contract (.processflow.xml) │
│ <Action name="NavigateToAction" actionType="LOGIC" ... /> │
└──────────────────────────────┬──────────────────────────────┘
│ Invoke Business Logic
▼
┌─────────────────────────────────────────────────────────────┐
│ Business Logic (.bl.js) │
│ 1. Obtém Latitude e Longitude do LuCustomer │
│ 2. Monta URI: maps.google.com ou waze://?ll=... │
│ 3. Executa: Facade.startThirdPartyAsync(url, {}) │
└──────────────────────────────┬──────────────────────────────┘
│ Device Handover
▼
┌─────────────────────────────────────────────────────────────┐
│ Sistema Operacional (Android / iOS) │
│ - Abre Google Maps / Waze / WhatsApp com dados injetados │
│ - Ao encerrar, o usuário retorna ao CGC Mobile App │
└─────────────────────────────────────────────────────────────┘
Code language: HTML, XML (xml)
2. A API nativa Facade.startThirdPartyAsync
O serviço Facade do framework Mv2 encapsula chamadas de baixo nível para recursos do dispositivo. O método para acionar aplicações externas possui a seguinte assinatura:
Facade.startThirdPartyAsync(url, options);
url(String): A URL completa ou URI Scheme customizado a ser disparado (ex.:http://maps.google.com/maps?...ouwhatsapp://send?...).options(Object): Objeto de configuração repassado ao runtime nativo (geralmente passado como{}).- Retorno (Promise): Promessa resolvida assim que o sistema operacional aceita a requisição de abertura do app terceiro.
3. Catálogo de URI Schemes para campo
Cada aplicativo requer uma formatação específica de protocolo para receber os dados contextuais:
Google Maps (Multiplataforma)
Abre o aplicativo calculando a rota da localização atual até as coordenadas do ponto de venda:
var url = "http://maps.google.com/maps?mode=d&daddr=" + latitude + "+" + longitude;
Waze
Inicia diretamente a navegação curva a curva:
var url = "waze://?ll=" + latitude + "," + longitude + "&navigate=yes";
Abre uma conversa direta no WhatsApp injetando texto pré-definido:
var encodedMessage = encodeURIComponent("Olá! Sou o promotor da Alpine Group e gostaria de confirmar nossa visita técnica para hoje.");
var url = "https://api.whatsapp.com/send?phone=" + formattedPhone + "&text=" + encodedMessage;
Discador telefônico
Abre o teclado de chamadas com o número pronto para discagem:
var url = "tel:" + phoneNumber;
4. Implementação na camada de Business Logic (.bl.js)
Para ilustrar o padrão, criamos dois métodos no Business Object: um para controlar a visibilidade do botão e outro para disparar a navegação.
Método 1: Visibilidade condicional (BoMyDisplay.IsNavigateVisible.bl.js)
O botão de rota só deve aparecer na interface se o ponto de venda associado possuir coordenadas de latitude e longitude registradas no SQLite:
"use strict";
///////////////////////////////////////////////////////////////////////////////////////////////
// IMPORTANT - DO NOT MODIFY AUTO-GENERATED CODE OR COMMENTS //
//Parts of this file are auto-generated and modifications to those sections will be //
//overwritten. You are allowed to modify: //
// - the tags in the jsDoc as described in the corresponding section //
// - the function name and its parameters //
// - the function body between the insertion ranges //
// "Add your customizing javaScript code below / above" //
///////////////////////////////////////////////////////////////////////////////////////////////
/**
* Avalia se o botão de navegação para mapas externos deve ser exibido.
*
* @function isNavigateVisible
* @this BoMyDisplay
* @kind businesslogic
* @namespace CUSTOM
* @returns {Boolean} Retorna true quando existem coordenadas válidas no registro.
*/
function isNavigateVisible() {
var me = this;
///////////////////////////////////////////////////////////////////////////////////////////////
// //
// Add your customizing javaScript code below. //
// //
///////////////////////////////////////////////////////////////////////////////////////////////
/*
* Data: 2026-09-11
* Objetivo da Customização: Avaliar se o botão de navegação para aplicativos externos (Google Maps, Waze) deve ser exibido com base na presença de coordenadas válidas do cliente.
*/
var isVisible = false;
var customer = me.getLuCustomer();
if (Utils.isDefined(customer) && customer.getPKey() !== " ") {
var lat = customer.getLatitude();
var lon = customer.getLongitude();
if (Utils.isDefined(lat) && Utils.isDefined(lon) && lat !== 0 && lon !== 0) {
isVisible = true;
}
}
return isVisible;
///////////////////////////////////////////////////////////////////////////////////////////////
// //
// Add your customizing javaScript code above. //
// //
///////////////////////////////////////////////////////////////////////////////////////////////
}
Método 2: Disparo de navegação (BoMyDisplay.MyNavigateTo.bl.js)
Recupera a localização da loja, formata a URL de destino e invoca o Facade:
"use strict";
///////////////////////////////////////////////////////////////////////////////////////////////
// IMPORTANT - DO NOT MODIFY AUTO-GENERATED CODE OR COMMENTS //
//Parts of this file are auto-generated and modifications to those sections will be //
//overwritten. You are allowed to modify: //
// - the tags in the jsDoc as described in the corresponding section //
// - the function name and its parameters //
// - the function body between the insertion ranges //
// "Add your customizing javaScript code below / above" //
///////////////////////////////////////////////////////////////////////////////////////////////
/**
* Dispara o aplicativo de mapas passando as coordenadas do ponto de venda.
*
* @function myNavigateTo
* @this BoMyDisplay
* @kind businesslogic
* @async
* @namespace CUSTOM
* @param {Object} context Contexto de execução do processo.
* @returns {Promise<Object>} Promessa resolvida com o contexto.
*/
function myNavigateTo(context) {
var me = this;
///////////////////////////////////////////////////////////////////////////////////////////////
// //
// Add your customizing javaScript code below. //
// //
///////////////////////////////////////////////////////////////////////////////////////////////
/*
* Data: 2026-09-11
* Objetivo da Customização: Disparar navegação App2App para mapas externos utilizando a API nativa Facade.startThirdPartyAsync com coordenadas de latitude e longitude.
*/
AppLog.info("BoMyDisplay.myNavigateTo: Iniciando processo App2App para mapas.");
var customer = me.getLuCustomer();
var latitude = 0.0;
var longitude = 0.0;
if (Utils.isDefined(customer)) {
latitude = customer.getLatitude() || 0.0;
longitude = customer.getLongitude() || 0.0;
}
if (latitude === 0.0 && longitude === 0.0) {
AppLog.warn("BoMyDisplay.myNavigateTo: Coordenadas geográficas não encontradas.");
return when.resolve(context);
}
var mapUrl = "http://maps.google.com/maps?mode=d&daddr=" + latitude + "+" + longitude;
var promise = Facade.startThirdPartyAsync(mapUrl, {}).then(function() {
AppLog.info("BoMyDisplay.myNavigateTo: Aplicativo externo acionado pelo sistema operacional.");
return context;
}).catch(function(error) {
AppLog.error("BoMyDisplay.myNavigateTo: Falha ao acionar aplicativo externo.", error);
return context;
});
return promise;
///////////////////////////////////////////////////////////////////////////////////////////////
// //
// Add your customizing javaScript code above. //
// //
///////////////////////////////////////////////////////////////////////////////////////////////
}
5. Orquestração no ProcessFlow (.processflow.xml)
No contrato do fluxo (MyDisplay_DisplayDetailsProcess.processflow.xml), declare o evento de tela e a transição para a lógica JavaScript. No Modeler Mv2, contratos de Process usam obrigatoriamente schemaVersion="0.0.0.5":
<?xml version="1.0" encoding="UTF-8"?>
<ProcessFlow name="MyDisplay_DisplayDetailsProcess" schemaVersion="0.0.0.5">
<Declaration>
<Context name="CurrentDisplay" type="BoMyDisplay" />
</Declaration>
<ViewActionEvents>
<Event name="NavigateTo" action="NavigateToAction" />
</ViewActionEvents>
<States>
<State name="ShowDisplayDetails">
<Actions>
<Action name="NavigateToAction" actionType="LOGIC" call="ProcessContext::CurrentDisplay.MyNavigateTo">
<TransitionTo action="ShowDisplayDetails" />
</Action>
</Actions>
</State>
</States>
</ProcessFlow>
6. Configuração do botão na UserInterface (.userinterface.xml)
Na interface visual (MyDisplay_DisplayDetailsUI.userinterface.xml), inserimos a ação na barra de menu, ligando a visibilidade à regra do Business Object. Contratos de UI utilizam schemaVersion="0.0.0.5":
<?xml version="1.0" encoding="UTF-8"?>
<UserInterface name="MyDisplay_DisplayDetailsUI" schemaVersion="0.0.0.5">
<Header title="Detalhes da Exibição">
<MenuItems>
<MenuItem name="BtnNavigate" image="Directions" text="labels:LblNavigateToStore" visible="ProcessContext::CurrentDisplay.isNavigateVisible">
<Events>
<Event name="click" event="NavigateTo" />
</Events>
</MenuItem>
</MenuItems>
</Header>
<Container name="MainContainer">
</Container>
</UserInterface>
7. Particularidades de teste e validação
O disparo físico de aplicações de terceiros não opera dentro do simulador desktop (sf modeler workspace server start). No navegador web do computador, a chamada do protocolo não encontra os aplicativos móveis correspondentes.
Para validar o fluxo completo:
- Validação sintática e de schemas: Execute no terminal:
sf modeler workspace validate sf modeler workspace build - Geração do pacote de deploy: Gere o arquivo de distribuição:
sf modeler workspace package - Distribuição para o dispositivo móvel: Suba o pacote compilado para a org Salesforce e atribua o contrato aos perfis móveis.
- Sincronização no tablet ou smartphone: Abra o aplicativo Salesforce Consumer Goods Cloud no dispositivo físico, execute a sincronização inicial e abra a tela de detalhe. Ao tocar no ícone de direção, o Google Maps ou Waze abrirá com a rota traçada.

Conclusão
O recurso de App2App Communication integra o banco de dados offline do Consumer Goods Cloud às ferramentas nativas de navegação e comunicação instaladas no dispositivo. A chamada a Facade.startThirdPartyAsync, combinada com a higienização de parâmetros e regras de visibilidade no Business Object, elimina a digitação manual de endereços e simplifica o atendimento diário em campo.
