Mensagens no app com deep link
Aprenda como usar deep link dentro de uma mensagem no app para o SDK Braze.
Pré-requisitos
Antes de usar este recurso, você precisará integrar o SDK Android Braze.
Criando um delegado universal
O SDK do Android oferece a capacidade de definir um único objeto delegado para tratar de forma personalizada todos os deep links abertos pelo Braze nos cartões de conteúdo, mensagens no app e notificações por push.
Seu objeto delegado deve implementar a interface IBrazeDeeplinkHandler e ser definido usando BrazeDeeplinkHandler.setBrazeDeeplinkHandler(). Na maioria dos casos, o delegado deve ser definido no Application.onCreate() do seu app.
Veja a seguir um exemplo de substituição do comportamento padrão UriAction com sinalizadores de intenção personalizados e comportamento personalizado para URLs do YouTube:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class CustomDeeplinkHandler implements IBrazeDeeplinkHandler {
private static final String TAG = BrazeLogger.getBrazeLogTag(CustomDeeplinkHandler.class);
@Override
public void gotoUri(Context context, UriAction uriAction) {
String uri = uriAction.getUri().toString();
// Open YouTube URLs in the YouTube app and not our app
if (!StringUtils.isNullOrBlank(uri) && uri.contains("youtube.com")) {
uriAction.setUseWebView(false);
}
CustomUriAction customUriAction = new CustomUriAction(uriAction);
customUriAction.execute(context);
}
public static class CustomUriAction extends UriAction {
public CustomUriAction(@NonNull UriAction uriAction) {
super(uriAction);
}
@Override
protected void openUriWithActionView(Context context, Uri uri, Bundle extras) {
Intent intent = getActionViewIntent(context, uri, extras);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
if (intent.resolveActivity(context.getPackageManager()) != null) {
context.startActivity(intent);
} else {
BrazeLogger.w(TAG, "Could not find appropriate activity to open for deep link " + uri + ".");
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class CustomDeeplinkHandler : IBrazeDeeplinkHandler {
override fun gotoUri(context: Context, uriAction: UriAction) {
val uri = uriAction.uri.toString()
// Open YouTube URLs in the YouTube app and not our app
if (!StringUtils.isNullOrBlank(uri) && uri.contains("youtube.com")) {
uriAction.useWebView = false
}
val customUriAction = CustomUriAction(uriAction)
customUriAction.execute(context)
}
class CustomUriAction(uriAction: UriAction) : UriAction(uriAction) {
override fun openUriWithActionView(context: Context, uri: Uri, extras: Bundle) {
val intent = getActionViewIntent(context, uri, extras)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
if (intent.resolveActivity(context.packageManager) != null) {
context.startActivity(intent)
} else {
BrazeLogger.w(TAG, "Could not find appropriate activity to open for deep link $uri.")
}
}
}
companion object {
private val TAG = BrazeLogger.getBrazeLogTag(CustomDeeplinkHandler::class.java)
}
}
Deep links para as configurações do app
Para permitir que os deep links abram diretamente as configurações do seu app, você precisará de um BrazeDeeplinkHandler personalizado. No exemplo a seguir, a presença de um par de chave/valor personalizado chamado open_notification_page fará com que o deep link abra a página de configurações do app:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
BrazeDeeplinkHandler.setBrazeDeeplinkHandler(new IBrazeDeeplinkHandler() {
@Override
public void gotoUri(Context context, UriAction uriAction) {
final Bundle extras = uriAction.getExtras();
if (extras.containsKey("open_notification_page")) {
Intent intent = new Intent();
intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//for Android 5-7
intent.putExtra("app_package", context.getPackageName());
intent.putExtra("app_uid", context.getApplicationInfo().uid);
// for Android 8 and later
intent.putExtra("android.provider.extra.APP_PACKAGE", context.getPackageName());
context.startActivity(intent);
}
}
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
BrazeDeeplinkHandler.setBrazeDeeplinkHandler(object : IBrazeDeeplinkHandler {
override fun gotoUri(context: Context, uriAction: UriAction) {
val extras = uriAction.extras
if (extras.containsKey("open_notification_page")) {
val intent = Intent()
intent.action = "android.settings.APP_NOTIFICATION_SETTINGS"
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
//for Android 5-7
intent.putExtra("app_package", context.packageName)
intent.putExtra("app_uid", context.applicationInfo.uid)
// for Android 8 and later
intent.putExtra("android.provider.extra.APP_PACKAGE", context.packageName)
context.startActivity(intent)
}
}
})
Personalizando a atividade WebView
Quando o Braze abre links profundos de sites dentro do app, os links profundos são tratados por BrazeWebViewActivity.
Para mensagens in-app personalizadas em HTML, links configurados com target="_blank" abrem no navegador web padrão do dispositivo e não são tratados por BrazeWebViewActivity.
Para mudar isso:
- Crie uma nova atividade que manipule o direcionamento do URL de
Intent.getExtras()com a chavecom.braze.Constants.BRAZE_WEBVIEW_URL_EXTRA. Para um exemplo, vejaBrazeWebViewActivity.kt. - Adicione essa atividade a
AndroidManifest.xmle definaexportedcomofalse.1 2 3
<activity android:name=".MyCustomWebViewActivity" android:exported="false" />
- Defina sua Activity personalizada em um objeto do construtor
BrazeConfig. Construa o construtor e passe-o paraBraze.configure()no seuApplication.onCreate().
1
2
3
4
5
BrazeConfig brazeConfig = new BrazeConfig.Builder()
.setCustomWebViewActivityClass(MyCustomWebViewActivity::class)
...
.build();
Braze.configure(this, brazeConfig);
1
2
3
4
5
val brazeConfig = BrazeConfig.Builder()
.setCustomWebViewActivityClass(MyCustomWebViewActivity::class.java)
...
.build()
Braze.configure(this, brazeConfig)
Usando Jetpack Compose
Para tratar links profundos ao usar Jetpack Compose com NavHost:
- Certifique-se de que a atividade que trata seu link profundo está registrada no Manifesto do Android.
1 2 3 4 5 6 7 8 9 10 11
<activity ... <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.DEFAULT" /> <data android:host="articles" android:scheme="myapp" /> </intent-filter> </activity>
- No NavHost, especifique quais links profundos você deseja que ele trate.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
composableWithCompositionLocal( route = "YOUR_ROUTE_HERE", deepLinks = listOf(navDeepLink { uriPattern = "myapp://articles/{${MainDestinations.ARTICLE_ID_KEY}}" }), arguments = listOf( navArgument(MainDestinations.ARTICLE_ID_KEY) { type = NavType.LongType } ), ) { backStackEntry -> val arguments = requireNotNull(backStackEntry.arguments) val articleId = arguments.getLong(MainDestinations.ARTICLE_ID_KEY) ArticleDetail( articleId ) }
- Dependendo da arquitetura do seu app, você pode precisar tratar a nova intenção que é enviada para sua atividade atual também.
1 2 3 4 5 6 7
DisposableEffect(Unit) { val listener = Consumer<Intent> { navHostController.handleDeepLink(it) } addOnNewIntentListener(listener) onDispose { removeOnNewIntentListener(listener) } }
Pré-requisitos
Antes de poder usar esse recurso, você precisará integrar o Swift Braze SDK.
Manuseio de deep linking
Etapa 1: Registrar um esquema
Para lidar com o deep linking, um esquema personalizado deve ser declarado em seu arquivo Info.plist. A estrutura de navegação é definida por uma matriz de dicionários. Cada um desses dicionários contém um vetor de strings.
Use o Xcode para editar seu Info.plist arquivo:
- Adicione uma nova chave,
URL types. O Xcode fará automaticamente disso um vetor contendo um dicionário chamadoItem 0. - Dentro de
Item 0, adicione uma chaveURL identifier. Defina o valor para seu esquema personalizado. - Dentro de
Item 0, adicione uma chaveURL Schemes. Isso será automaticamente um vetor contendo umaItem 0string. - Defina
URL Schemes»Item 0para seu esquema personalizado.
Alternativamente, se você deseja editar seu arquivoInfo.plist diretamente, siga esta especificação:
1
2
3
4
5
6
7
8
9
10
11
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>YOUR.SCHEME</string>
<key>CFBundleURLSchemes</key>
<array>
<string>YOUR.SCHEME</string>
</array>
</dict>
</array>
Etapa 2: Adicionar uma lista de permissões de esquema
Você deve declarar os esquemas de URL que deseja passar para canOpenURL(_:) adicionando a chave LSApplicationQueriesSchemes ao arquivo Info.plist do seu app. Tentar chamar esquemas fora desta lista de permissão fará com que o sistema registre um erro nos logs do dispositivo, e o deep link não abrirá. Um exemplo desse erro é o seguinte:
1
<Warning>: -canOpenURL: failed for URL: "yourapp://deeplink" – error: "This app is not allowed to query for scheme yourapp"
Por exemplo, se uma mensagem no app deve abrir o aplicativo do Facebook ao ser tocada, o app deve ter o esquema personalizado do Facebook (fb) em sua lista de permissões. Caso contrário, o sistema rejeitará o deep link. Os deep linkings que direcionam para uma página ou exibição dentro do seu próprio aplicativo ainda exigem que o esquema personalizado do seu aplicativo seja listado no site Info.plist.
Seu exemplo de lista de permissões pode ser algo como:
1
2
3
4
5
6
<key>LSApplicationQueriesSchemes</key>
<array>
<string>myapp</string>
<string>fb</string>
<string>twitter</string>
</array>
Para saber mais, consulte a documentação da Apple sobre a tecla LSApplicationQueriesSchemes.
Etapa 3: Implementar um manipulador
Depois de ativar seu app, o iOS chamará o método application:openURL:options:. O argumento importante é o objeto NSURL.
1
2
3
4
5
6
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
let path = url.path
let query = url.query
// Insert your code here to take some action based upon the path and query.
return true
}
1
2
3
4
5
6
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options {
NSString *path = [url path];
NSString *query = [url query];
// Insert your code here to take some action based upon the path and query.
return YES;
}
App Transport Security (ATS)
Conforme definido pela Apple, “o App Transport Security é um recurso que melhora a segurança das conexões entre um aplicativo e os serviços da Web. O recurso consiste em requisitos de conexão padrão que estão em conformidade com as melhores práticas para conexões seguras. Os apps podem substituir esse comportamento padrão e desativar a segurança de transporte.”
O ATS é aplicado por padrão. Requer que todas as conexões usem HTTPS e sejam criptografadas usando TLS 1.2 com sigilo direto. Consulte Requisitos para Conexão Usando ATS para saber mais. Todas as imagens servidas pela Braze para dispositivos finais são gerenciadas por uma rede de entrega de conteúdo (“CDN”) que suporta TLS 1.2 e é compatível com ATS.
A menos que sejam especificadas como exceções no site Info.plist do seu aplicativo, as conexões que não seguirem esses requisitos falharão com erros semelhantes aos seguintes.
Exemplo de erro 1:
1
2
CFNetwork SSLHandshake failed (-9801)
Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred, and a secure connection to the server cannot be made."
Exemplo de erro 2:
1
NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802)
A conformidade com ATS é aplicada para links abertos dentro do app móvel (nosso tratamento padrão de links clicados) e não se aplica a sites abertos externamente por meio de um navegador da web.
Trabalhando com ATS
Você pode lidar com o ATS de uma das seguintes maneiras, mas recomendamos que você cumpra os requisitos do ATS.
Sua integração com a Braze pode atender aos requisitos do ATS, garantindo que todos os links existentes para os quais você direciona os usuários (por exemplo, por meio de mensagens no app e campanhas de mensagens) atendam aos requisitos do ATS. Embora existam maneiras de contornar as restrições do ATS, nossa recomendação é garantir que todos os URLs vinculados estejam em conformidade com o ATS. Dada a ênfase crescente da Apple à segurança de aplicativos, as seguintes abordagens para permitir exceções ATS podem não ser compatíveis.
Você pode permitir que um subconjunto de links com determinados domínios ou esquemas sejam tratados como exceções às regras do ATS. Sua integração com o Braze atenderá aos requisitos do ATS se todos os links usados em um canal de envio de mensagens do Braze estiverem em conformidade com o ATS ou forem tratados por uma exceção.
Para adicionar um domínio como exceção do ATS, adicione o seguinte ao arquivo Info.plist do seu app:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSExceptionDomains</key>
<dict>
<key>example.com</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<false/>
<key>NSIncludesSubdomains</key>
<true/>
</dict>
</dict>
</dict>
Consulte o artigo da Apple sobre [chaves de segurança de transporte de app para saber mais.
Você pode desativar o ATS completamente. Nota que isso não é uma prática recomendada, devido tanto à perda de proteções de segurança quanto à compatibilidade futura com o iOS. Para desativar o ATS, insira o seguinte no arquivo Info.plist do seu app:
1
2
3
4
5
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
Decodificação de URLs
O SDK codifica os links em porcentagem para criar URLs válidos. Todos os caracteres de link que não são permitidos em um URL devidamente formado, como caracteres Unicode, serão escapados por porcentagem.
Para decodificar um link codificado, use a propriedade String removingPercentEncoding. Você também deve retornar true em BrazeDelegate.braze(_:shouldOpenURL:). Uma chamada para ação é necessária para disparar o tratamento da URL pelo seu aplicativo. Por exemplo:
1
2
3
4
5
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
let urlString = url.absoluteString.removingPercentEncoding
// Handle urlString
return true
}
1
2
3
4
5
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<NSString *, id> *)options {
NSString *urlString = [url.absoluteString stringByRemovingPercentEncoding];
// Handle urlString
return YES;
}
Deep linking para as configurações do app
Você pode aproveitar o UIApplicationOpenSettingsURLString para fazer um deep link dos usuários para as configurações do seu app a partir das notificações por push e mensagens no app do Braze.
Para levar os usuários do seu app para as configurações do iOS:
- Primeiro, confira se o seu aplicativo está configurado para [links profundos baseados em esquema ou [links universais.
- Decida sobre um URI para deep linking para a página de Configurações (por exemplo,
myapp://settingsouhttps://www.braze.com/settings). - Se você estiver usando links profundos baseados em esquemas personalizados, adicione o seguinte código ao seu método
application:openURL:options::
1
2
3
4
5
6
7
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
let path = url.path
if (path == "settings") {
UIApplication.shared.openURL(URL(string:UIApplication.openSettingsURLString)!)
}
return true
}
1
2
3
4
5
6
7
8
9
10
- (BOOL)application:(UIApplication *)app
openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
NSString *path = [url path];
if ([path isEqualToString:@"settings"]) {
NSURL *settingsURL = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
[[UIApplication sharedApplication] openURL:settingsURL];
}
return YES;
}
Opções de personalização
Personalização padrão do WebView
A classe Braze.WebViewController exibe URLs da web abertas pelo SDK, normalmente quando “Abrir URL da Web Dentro do App” é selecionado para um deep link da web.
Você pode personalizar Braze.WebViewController por meio do método delegado BrazeDelegate.braze(_:willPresentModalWithContext:).
Personalização do manuseio de links
O protocolo BrazeDelegate pode ser usado para personalizar o tratamento de URLs, como deep links, URLs da web e links universais. Para definir o delegado durante a inicialização da Braze, defina um objeto delegado na instância Braze. Braze chamará a implementação do seu delegado de shouldOpenURL antes de lidar com qualquer URI.
Links universais
O Braze oferece suporte a links universais em notificações por push, mensagens no app e cartões de conteúdo. Para ativar o suporte a links universais, configuration.forwardUniversalLinks deve ser definido como true.
Quando ativada, a Braze encaminhará links universais para o AppDelegate do seu app por meio do método application:continueUserActivity:restorationHandler:.
Seu aplicativo também precisa ser configurado para lidar com links universais. Consulte a documentação da Apple para garantir que seu aplicativo esteja configurado corretamente para links universais.
O encaminhamento de links universais requer acesso aos direitos do aplicativo. Ao executar o aplicativo em um simulador, esses direitos não estão diretamente disponíveis e os links universais não são encaminhados para os manipuladores do sistema.
Para adicionar suporte às compilações do simulador, você pode adicionar o arquivo .entitlements do aplicativo à fase de compilação Copy Bundle Resources. Para saber mais, consulte a documentação forwardUniversalLinks.
O SDK não consulta o arquivo apple-app-site-association de seus domínios. Ele realiza a diferenciação entre links universais e URLs regulares observando apenas o nome do domínio. Como resultado, o SDK não respeita nenhuma regra de exclusão definida em apple-app-site-association conforme Suporte a domínios associados.
Exemplos
BrazeDelegate
Veja um exemplo usando BrazeDelegate. Para saber mais, consulte a referência do Braze Swift SDK.
1
2
3
4
5
6
7
8
func braze(_ braze: Braze, shouldOpenURL context: Braze.URLContext) -> Bool {
if context.url.host == "MY-DOMAIN.com" {
// Custom handle link here
return false
}
// Let Braze handle links otherwise
return true
}
1
2
3
4
5
6
7
8
- (BOOL)braze:(Braze *)braze shouldOpenURL:(BRZURLContext *)context {
if ([[context.url.host lowercaseString] isEqualToString:@"MY-DOMAIN.com"]) {
// Custom handle link here
return NO;
}
// Let Braze handle links otherwise
return YES;
}
Editar esta página no GitHub