Sobre este codelab
1. Introdução
Última atualização:03/02/2022
O que você aprenderá
- Como criar uma Webview muito simples no Android
- Como enviar eventos da Webview para o Firebase
O que é necessário
- Projeto do Firebase com o SDK do Google Analytics implementado
- Android Studio versão 4.2 ou mais recente.
- Um Android Emulator com Android 5.0 ou mais recente.
- Noções básicas da linguagem de programação Java.
- Noções básicas da linguagem de programação JavaScript.
2. Criar uma Webview da Web simples no Android
Como adicionar uma WebView no layout da atividade
Para adicionar uma WebView ao app no layout, adicione o seguinte código ao arquivo XML do layout da atividade:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".WebActivity"
>
<WebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>;
Como adicionar uma WebView em onCreate()
Para carregar uma página da Web na WebView, use loadUrl(). A WebView precisa ser criada na atividade em tela preta. Por exemplo, vou implementar isso no método onCreate :
public class WebActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_web);
// Navigate to site
myWebView.loadUrl("https://bittererhu.glitch.me");
}
}
No entanto, antes que isso funcione, seu app precisa ter acesso à Internet. Para ter acesso à Internet, solicite a permissão INTERNET no arquivo de manifesto. Exemplo:
<uses-permission android:name="android.permission.INTERNET" />
Isso é tudo que você precisa para uma WebView básica que mostra uma página da Web.
Como usar o JavaScript em Webviews
Se a página da Web que você pretende carregar na WebView usa JavaScript, você precisa ativar o JavaScript para sua WebView. Depois que o JavaScript for ativado, você também poderá criar interfaces entre o código do app e o código JavaScript.
Por padrão, o JavaScript fica desativado em uma WebView. É possível ativar essa opção nas WebSettings anexadas à WebView. É possível recuperar as WebSettings com getSettings() e ativar o JavaScript com setJavaScriptEnabled().
Exemplo:
WebView myWebView = (WebView) findViewById(R.id.webview);
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
Atividade atualizada :
public class WebActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_web);
WebView myWebView = (WebView) findViewById(R.id.webview);
if(myWebView != null) {
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
}
// Navigate to site
myWebView.loadUrl("https://bittererhu.glitch.me");
}
}
3. Como implementar a interface de ponte do JavaScript
Gerenciador de Javacript
A primeira etapa para usar o Google Analytics em um WebView é criar funções JavaScript para transformar eventos e propriedades do usuário em código nativo. O exemplo a seguir mostra como fazer isso de modo compatível com o código nativo da Apple e do Android:
Neste exemplo, criei um arquivo JavaScript chamado script.js que inclui o seguinte :
function logEvent(name, params) {
if (!name) {
return;
}
if (window.AnalyticsWebInterface) {
// Call Android interface
window.AnalyticsWebInterface.logEvent(name, JSON.stringify(params));
} else if (window.webkit
&& window.webkit.messageHandlers
&& window.webkit.messageHandlers.firebase) {
// Call iOS interface
var message = {
command: 'logEvent',
name: name,
parameters: params
};
window.webkit.messageHandlers.firebase.postMessage(message);
} else {
// No Android or iOS interface found
console.log("No native APIs found.");
}
}
function setUserProperty(name, value) {
if (!name || !value) {
return;
}
if (window.AnalyticsWebInterface) {
// Call Android interface
window.AnalyticsWebInterface.setUserProperty(name, value);
} else if (window.webkit
&& window.webkit.messageHandlers
&& window.webkit.messageHandlers.firebase) {
// Call iOS interface
var message = {
command: 'setUserProperty',
name: name,
value: value
};
window.webkit.messageHandlers.firebase.postMessage(message);
} else {
// No Android or iOS interface found
console.log("No native APIs found.");
}
}
Interface nativa
Para chamar o código nativo do Android do JavaScript, implemente uma classe com os métodos marcados com @JavaScriptInterface
: no exemplo abaixo, criei uma nova classe Java chamada AnalyticsWebInterfcae.java:
public class AnalyticsWebInterface {
public static final String TAG = "AnalyticsWebInterface";
private FirebaseAnalytics mAnalytics;
public AnalyticsWebInterface(Context context) {
mAnalytics = FirebaseAnalytics.getInstance(context);
}
@JavascriptInterface
public void logEvent(String name, String jsonParams) {
LOGD("logEvent:" + name);
mAnalytics.logEvent(name, bundleFromJson(jsonParams));
}
@JavascriptInterface
public void setUserProperty(String name, String value) {
LOGD("setUserProperty:" + name);
mAnalytics.setUserProperty(name, value);
}
private void LOGD(String message) {
// Only log on debug builds, for privacy
if (BuildConfig.DEBUG) {
Log.d(TAG, message);
}
}
private Bundle bundleFromJson(String json) {
// ...
}
}
Once you have created the native interface, register it with your WebView so that it is visible to JavaScript code running in the WebView:
// Only add the JavaScriptInterface on API version JELLY_BEAN_MR1 and above, due to
// security concerns, see link below for more information:
// https://developer.android.com/reference/android/webkit/WebView.html#addJavascriptInterface(java.lang.Object,%20java.lang.String)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
mWebView.addJavascriptInterface(
new AnalyticsWebInterface(this), AnalyticsWebInterface.TAG);
} else {
Log.w(TAG, "Not adding JavaScriptInterface, API Version: " + Build.VERSION.SDK_INT);
}
Código final :
// [START analytics_web_interface]
public class AnalyticsWebInterface {
public static final String TAG = "AnalyticsWebInterface";
private FirebaseAnalytics mAnalytics;
public AnalyticsWebInterface(Context context) {
mAnalytics = FirebaseAnalytics.getInstance(context);
}
@JavascriptInterface
public void logEvent(String name, String jsonParams) {
LOGD("logEvent:" + name);
mAnalytics.logEvent(name, bundleFromJson(jsonParams));
}
@JavascriptInterface
public void setUserProperty(String name, String value) {
LOGD("setUserProperty:" + name);
mAnalytics.setUserProperty(name, value);
}
private void LOGD(String message) {
// Only log on debug builds, for privacy
if (BuildConfig.DEBUG) {
Log.d(TAG, message);
}
}
private Bundle bundleFromJson(String json) {
// [START_EXCLUDE]
if (TextUtils.isEmpty(json)) {
return new Bundle();
}
Bundle result = new Bundle();
try {
JSONObject jsonObject = new JSONObject(json);
Iterator<String> keys = jsonObject.keys();
while (keys.hasNext()) {
String key = keys.next();
Object value = jsonObject.get(key);
if (value instanceof String) {
result.putString(key, (String) value);
} else if (value instanceof Integer) {
result.putInt(key, (Integer) value);
} else if (value instanceof Double) {
result.putDouble(key, (Double) value);
} else {
Log.w(TAG, "Value for key " + key + " not one of [String, Integer, Double]");
}
}
} catch (JSONException e) {
Log.w(TAG, "Failed to parse JSON, returning empty Bundle.", e);
return new Bundle();
}
return result;
// [END_EXCLUDE]
}
Agora que você configurou a interface do JavaScript , está tudo pronto para começar a enviar eventos de análise.
4. Como enviar eventos pela interface
Como você pode ver, minha Webview é muito simples, tem três botões, dois que registram um evento e outro que registra uma propriedade do usuário :
Quando clico nos botões, ele chama meu arquivo "script.js" e executa o seguinte código :
document.getElementById("event1").addEventListener("click", function() {
console.log("event1");
logEvent("event1", { foo: "bar", baz: 123 });
});
document.getElementById("event2").addEventListener("click", function() {
console.log("event2");
logEvent("event2", { size: 123.456 });
});
document.getElementById("userprop").addEventListener("click", function() {
console.log("userprop");
setUserProperty("userprop", "custom_value");
});
Arquivo script.js final :
/* If you're feeling fancy you can add interactivity
to your site with Javascript */
// prints "hi" in the browser's dev tools console
console.log("hi");
// [START log_event]
function logEvent(name, params) {
if (!name) {
return;
}
if (window.AnalyticsWebInterface) {
// Call Android interface
window.AnalyticsWebInterface.logEvent(name, JSON.stringify(params));
} else if (window.webkit
&& window.webkit.messageHandlers
&& window.webkit.messageHandlers.firebase) {
// Call iOS interface
var message = {
command: 'logEvent',
name: name,
parameters: params
};
window.webkit.messageHandlers.firebase.postMessage(message);
} else {
// No Android or iOS interface found
console.log("No native APIs found.");
}
}
// [END log_event]
// [START set_user_property]
function setUserProperty(name, value) {
if (!name || !value) {
return;
}
if (window.AnalyticsWebInterface) {
// Call Android interface
window.AnalyticsWebInterface.setUserProperty(name, value);
} else if (window.webkit
&& window.webkit.messageHandlers
&& window.webkit.messageHandlers.firebase) {
// Call iOS interface
var message = {
command: 'setUserProperty',
name: name,
value: value
};
window.webkit.messageHandlers.firebase.postMessage(message);
} else {
// No Android or iOS interface found
console.log("No native APIs found.");
}
}
// [END set_user_property]
document.getElementById("event1").addEventListener("click", function() {
console.log("event1");
logEvent("event1", { foo: "bar", baz: 123 });
});
document.getElementById("event2").addEventListener("click", function() {
console.log("event2");
logEvent("event2", { size: 123.456 });
});
document.getElementById("userprop").addEventListener("click", function() {
console.log("userprop");
setUserProperty("userprop", "custom_value");
});
Essa é a maneira básica de enviar eventos para o Google Analytics.
5. Depurar eventos da WebView no Firebase
A depuração de eventos da Webview no app funciona da mesma forma que a depuração de qualquer parte nativa do SDK :
Para ativar o modo de depuração, use os seguintes comandos no console do Android Studio:
adb shell setprop debug.firebase.analytics.app package_name
Depois disso, você pode testar e conferir seus eventos da Webview :
6. Parabéns
Parabéns! Você criou uma WebView no seu app Android. É possível enviar e medir os principais eventos do funil no app que ocorrem por WebViews. Para aproveitar ao máximo essa oportunidade, sugerimos que você se conecte ao Google Ads e importe esses eventos como conversões.
Você aprendeu
- Como enviar eventos da Webview para o Firebase
- Como configurar e criar uma Webview simples no Android