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
- Un emulador de Android con Android 5.0 o versiones posteriores
- Estar familiarizado con el lenguaje de programación Java
- Tener conocimientos del 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 debería crearse 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 tu app y el código JavaScript.
De forma predeterminada, JavaScript está inhabilitado en un componente WebView. Puedes habilitarla a través de la configuración web adjunta 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. Cómo implementar 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 de 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 , tienes todo listo para comenzar a enviar eventos de análisis.
4. Cómo enviar eventos a través de la interfaz
Como puedes ver aquí, mi WebView es muy simple. Tiene tres botones: dos que registrarán un evento y el otro una propiedad del usuario:
Cuando haga clic en los botones, se llamará a mi "script.js". y ejecuta 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 depurar 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 en tu app eventos del embudo clave que se producen a través de WebViews. Para aprovechar al máximo esta situación, también te sugerimos conectarte a Google Ads y, luego, importar estos eventos como conversiones.
Aprendiste lo siguiente:
- Cómo enviar eventos de WebView a Firebase
- Cómo configurar y crear una WebView simple en Android