1. Introducción
Última actualización: 3/2/2022
Qué aprenderás
- Cómo crear un WebView muy simple en Android
- Cómo enviar eventos de WebView a Firebase
Requisitos
- Proyecto de Firebase con el SDK de Analytics implementado
- Android Studio versión 4.2 o posterior
- Android Emulator con Android 5.0 o versiones posteriores
- Familiaridad con el lenguaje de programación Java
- Familiaridad con el lenguaje de programación JavaScript
2. Cómo crear una WebView simple en Android
Cómo agregar WebView en el diseño de la actividad
Para agregar una WebView a tu app en el diseño, agrega el siguiente código al archivo en formato XML de diseño de tu actividad:
<?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>;
Cómo agregar una WebView en onCreate()
Para cargar una página web en WebView, usa loadUrl(). La WebView se debe crear en la actividad negra. Por ejemplo, implementaré esto en el 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");
}
}
Sin embargo, para que esto funcione, la app debe tener acceso a Internet. Para obtener acceso a Internet, solicita el permiso de INTERNET en el archivo de manifiesto. Por ejemplo:
<uses-permission android:name="android.permission.INTERNET" />
Eso es todo lo que necesitas para una WebView básica que muestre una página web.
Cómo usar JavaScript en WebViews
si la página web que planeas cargar en tu WebView usa JavaScript, debes habilitarlo para tu WebView. Una vez que JavaScript esté habilitado, también podrás crear interfaces entre el código de la app y el de JavaScript.
JavaScript está inhabilitado de forma predeterminada en un componente WebView. Puedes habilitarlo a través de WebSettings adjunto a tu WebView. Puedes recuperar WebSettings con getSettings() y luego habilitar JavaScript con setJavaScriptEnabled().
Por ejemplo:
WebView myWebView = (WebView) findViewById(R.id.webview);
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
Actividad actualizada :
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. Implementa la interfaz de puente de JavaScript
Controlador de Javacript
El primer paso para usar Google Analytics en WebView es crear funciones de JavaScript para reenviar eventos y propiedades del usuario al código nativo. En el siguiente ejemplo, se muestra cómo hacerlo de una manera compatible con el código nativo de Android y Apple:
En este ejemplo, creé un archivo JavaScript llamado script.js que incluye lo siguiente:
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.");
}
}
Interfaz nativa
Para invocar código nativo de Android desde JavaScript, implementa una clase con métodos marcados con @JavaScriptInterface
. En el siguiente ejemplo, creé una nueva clase de Java llamada 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]
}
Ahora que configuraste la interfaz de JavaScript, ya puedes comenzar a enviar eventos de Analytics.
4. Envía eventos a través de la interfaz
Como puedes ver, mi WebView es muy simple, tiene tres botones, dos de los cuales registrarán un evento y el otro registrará una propiedad del usuario:
Una vez que haga clic en los botones, se llamará a mi archivo "script.js" y se ejecutará el siguiente 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");
});
Archivo 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");
});
Esta es la forma básica de enviar eventos a Analytics.
5. Cómo depurar eventos de Webview en Firebase
La depuración de eventos de WebView en tu app funciona de la misma manera que la depuración de cualquier parte nativa de tu SDK:
Para habilitar el modo de depuración, usa los siguientes comandos en la consola de Android Studio:
adb shell setprop debug.firebase.analytics.app package_name
Cuando termines, puedes probar y ver cómo cobran vida tus eventos de WebView :
6. Felicitaciones
Felicitaciones, creaste correctamente un WebView en tu app para Android. Puedes enviar y medir los eventos de embudo clave en tu app que se realizan a través de WebViews. Para aprovechar al máximo esta función, también te sugerimos que te conectes a Google Ads y que importes estos eventos como conversiones.
Aprendiste lo siguiente:
- Cómo enviar eventos de WebView a Firebase
- Cómo configurar y crear un WebView simple en Android