Guía de implementación

Hay un ejemplo completo disponible en la aplicación de ejemplo GitHub. Contiene clases reutilizables para personalizar la interfaz de usuario, conectarse al servicio en segundo plano y gestionar el ciclo de vida de la aplicación y la actividad de la pestaña personalizada.

Si sigue las instrucciones de esta página, podrá crear una gran integración.

El primer paso para una integración de pestañas personalizadas es agregar la Biblioteca del navegador AndroidX a tu proyecto. Abra el archivo app/build.gradle y agregue la biblioteca del navegador a la sección dependencias.

dependencies {
...
implementation "androidx.browser:browser:1.3.0"
}

Una vez que se agrega la biblioteca del navegador a su proyecto, hay dos conjuntos de personalizaciones posibles:

  • Personalizar la interfaz de usuario y la interacción con las pestañas personalizadas.
  • Hacer que la página se cargue más rápido y mantener viva la aplicación.

Las personalizaciones de la interfaz de usuario se realizan utilizando las clases CustomTabsIntent y CustomTabsIntent.Builder ; las mejoras de rendimiento se logran utilizando el CustomTabsClient para conectarse al servicio de pestañas personalizadas, calentar el navegador y hacerle saber qué URL se abrirán.

Abrir una pestaña personalizada #

A CustomTabsIntent.Builder se puede usar para configurar una pestaña personalizada. Una vez listo, llame a CustomTabsIntent.Builder.build para crear un CustomTabsIntent e inicie la url deseada con CustomTabsIntent.launchUrl.

String url = ¨https://paul.kinlan.me/¨;
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
CustomTabsIntent customTabsIntent = builder.build();
customTabsIntent.launchUrl(this, Uri.parse(url));

Configurar el color de la barra de direcciones #

Uno de los aspectos más importantes (y más sencillos de implementar) de las pestañas personalizadas es la capacidad de cambiar el color de la barra de direcciones para que sea coherente con el tema de la aplicación.

El fragmento de código que aparece a continuación cambia el color de fondo de la barra de direcciones. colorInt es un int que especifica un Color.

int coolorInt = Color.parseColor("#FF0000"); //red
builder.setToolbarColor(colorInt);

Configurar un botón de acción personalizado #

builder.setActionButton(icon, description, pendingIntent, tint);

Captura de pantalla del Botón de Acción en la aplicación de Tumblr

Como desarrollador de su aplicación, tiene control total sobre el Botón de Acción que se presenta a los usuarios dentro de la pestaña del navegador.

En la mayoría de los casos, esta será una acción principal, como Compartir u otra actividad común que realizarán los usuarios.

El Botón de acción se representa como un Paquete con un icono del botón de acción y un PendingIntent que será llamado por el navegador cuando su usuario presione el botón de acción. El icono tiene una altura actual de 24dp y una anchura de 24-48 dp.

Se puede personalizar llamando a CustomTabsIntentBuilder#setActionButton:

  • icones un Bitmap que se utilizará como fuente de imagen para el botón de acción.
  • description es un String ser utilizado como un accesible descripción para el botón.
  • pendingIntent es un PendingIntent para que se inicie cuando el botón de acción o elemento de menú fue aprovechado. El navegador llamará a PendingIntent#send en los toques después de agregar la url como datos. La aplicación cliente puede llamar a Intent#getDataString para obtener la url.
  • tint es un booleano que define si el botón de Acción debe estar teñido.

Configure un menú personalizado #

builder.addMenuItem(menuItemTitle, menuItemPendingIntent);

Captura de pantalla del menú en la aplicación de Twitter

El navegador tiene un menú completo de acciones que los usuarios realizarán con frecuencia dentro de un navegador, sin embargo, pueden no ser relevantes para el contexto de su aplicación.

Las pestañas personalizadas tendrán un conjunto de acciones predeterminadas proporcionadas por el navegador. Estas acciones pueden incluir elementos como» Reenviar»,» Información de la página»,» Actualizar»,» Buscar en la página «o»Abrir en el navegador».

Como desarrollador, puede agregar y personalizar hasta cinco elementos de menú que aparecerán entre la fila de iconos y los elementos de pie.

Se agrega un elemento de menú llamando a CustomTabsIntent.Builder#addMenuItem con título y un PendingIntent que el navegador llamará en su nombre cuando el usuario toque el elemento se pasan como parámetros.

Configurar animaciones personalizadas de entrada y salida #

Muchas aplicaciones de Android usan animaciones personalizadas de Entrada y Salida de vistas al realizar la transición entre Actividades en Android. Las pestañas personalizadas no son diferentes, puede cambiar las animaciones de entrada y salida (cuando el usuario presiona Atrás) para que sean coherentes con el resto de la aplicación.

builder.setStartAnimations(this, R.anim.slide_in_right, R.anim.slide_out_left);
builder.setExitAnimations(this, R.anim.slide_in_left, R.anim.slide_out_right);

Calienta el navegador para que las páginas se carguen más rápido #

De forma predeterminada, cuando se llame a CustomTabsIntent#launchUrl, activará el navegador e iniciará la URL. Esto puede tomar un tiempo precioso e impactar en la percepción de suavidad.

Creemos que los usuarios exigen una experiencia casi instantánea, por lo que hemos proporcionado un Servicio al que su aplicación puede conectarse y decirle al navegador y sus componentes nativos que se calienten. Las pestañas personalizadas también proporcionan la capacidad para que usted, el desarrollador, le diga al navegador el conjunto probable de páginas web que visitará el usuario. Los navegadores podrán realizar:

  • Pre-resolución DNS del dominio principal
  • Pre-resolución DNS de los sub-recursos más probables
  • Pre-conexión al destino, incluida la negociación HTTPS / TLS.

El proceso de calentamiento del navegador es el siguiente:

  • Use CustomTabsClient#bindCustomTabsService para conectarse al servicio.
  • Una vez que el servicio esté conectado, llame a CustomTabsClient#warmup para iniciar el navegador entre bastidores.
  • Llame a CustomTabsClient#newSession para crear una nueva sesión. Esta sesión se utiliza para todas las solicitudes a la API.
  • Opcionalmente, adjunte un CustomTabsCallback como parámetro al crear una nueva sesión, para que sepa que se cargó una página.
  • Indique al navegador qué páginas es probable que cargue el usuario con CustomTabsSession#mayLaunchUrl
  • Llame al constructor CustomTabsIntent.Builder pasando el constructor CustomTabsSession como parámetro.

Conéctese al Servicio de pestañas personalizadas #

El método CustomTabsClient#bindCustomTabsService elimina la complejidad de conectarse al servicio de pestañas personalizadas.

Cree una clase que extienda CustomTabsServiceConnection y use onCustomTabsServiceConnectedpara obtener una instancia de CustomTabsClient. Esta instancia será necesaria en los próximos pasos.

// Package name for the Chrome channel the client wants to connect to. This
// depends on the channel name.
// Stable = com.android.chrome
// Beta = com.chrome.beta
// Dev = com.chrome.dev
public static final String CUSTOM_TAB_PACKAGE_NAME = "com.android.chrome"; // Change when in stable
CustomTabsServiceConnection connection = new CustomTabsServiceConnection() {
@Override
public void onCustomTabsServiceConnected(ComponentName name, CustomTabsClient client) {
mCustomTabsClient = client;
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
boolean ok = CustomTabsClient.bindCustomTabsService(this, mPackageNameToBind, connection);

Caliente hasta que el Proceso del Navegador #

boolean warmup(long flags)

se Calienta el proceso del explorador y las cargas de las bibliotecas nativas. El calentamiento es asíncrono, el valor devuelto indica si la solicitud ha sido aceptada. Varias llamadas exitosas también devolverán true.

Devuelve true si tiene éxito.

Crear una nueva sesión de pestaña #

boolean newSession(CustomTabsCallback callback)

La sesión se utiliza en llamadas posteriores para vincular la llamada mayLaunchUrl, el CustomTabsIntent y la pestaña generada entre sí. La devolución de llamada proporcionada aquí está asociada con la sesión creada. Cualquier actualización para la sesión creada (consulte Devolución de llamada de pestañas personalizadas a continuación) también se recibe a través de esta devolución de llamada. Devuelve si una sesión se creó correctamente. Varias llamadas con el mismo CustomTabsCallback o un valor null devolverán false.

Dile al navegador qué URL es probable que abra el usuario #

boolean mayLaunchUrl(Uri url, Bundle extras, List<Bundle> otherLikelyBundles)

Este método CustomTabsSession le indica al navegador una posible navegación futura a una URL. El método warmup() debe llamarse primero como práctica recomendada. La URL más probable debe especificarse primero. Opcionalmente, se puede proporcionar una lista de otras URL probables. Se tratan como menos probables que el primero, y deben clasificarse en orden de prioridad decreciente. Estas URL adicionales pueden ignorarse. Todas las llamadas anteriores a este método se carecerán de prioridad. Devuelve si la operación se completó correctamente.

Devolución de llamada de conexión de pestañas personalizadas #

void onNavigationEvent(int navigationEvent, Bundle extras)

Se llamará cuando ocurra un evento de navegación en la pestaña personalizada. El navigationEvent int es uno de los 6 valores que define el estado en el que se encuentra la página. Consulte a continuación para obtener más información.

/**
* Sent when the tab has started loading a page.
*/
public static final int NAVIGATION_STARTED = 1;
/**
* Sent when the tab has finished loading a page.
*/
public static final int NAVIGATION_FINISHED = 2;
/**
* Sent when the tab couldn't finish loading due to a failure.
*/
public static final int NAVIGATION_FAILED = 3;
/**
* Sent when loading was aborted by a user action before it finishes like clicking on a link
* or refreshing the page.
*/
public static final int NAVIGATION_ABORTED = 4;
/**
* Sent when the tab becomes visible.
*/
public static final int TAB_SHOWN = 5;
/**
* Sent when the tab becomes hidden.
*/
public static final int TAB_HIDDEN = 6;

¿Qué sucede si el usuario no tiene instalado un navegador que admita Pestañas personalizadas? #

Las pestañas personalizadas son compatibles con la mayoría de los navegadores Android. Sin embargo, dado que utiliza una Intent ACTION_VIEW con extras clave para personalizar la interfaz de usuario, se abrirá en el navegador del sistema o en el navegador predeterminado del usuario si no se admiten pestañas personalizadas.

Si el usuario tiene instalado un navegador que admite la pestaña personalizada y es el navegador predeterminado, recogerá automáticamente los EXTRAS y presentará una interfaz de usuario personalizada.

¿Cómo puedo comprobar si el dispositivo Android tiene un navegador compatible con la pestaña personalizada? #

Es posible usar PackageManager para consultar en el dispositivo Android las aplicaciones que pueden manejar Pestañas personalizadas. Consultamos las aplicaciones que son capaces de manejar Intents http, luego verificamos si esas aplicaciones también declaran soporte para el Servicio de pestañas personalizadas:

/**
* Returns a list of packages that support Custom Tabs.
*/
public static ArrayList<ResolveInfo> getCustomTabsPackages(Context context) {
PackageManager pm = context.getPackageManager();
// Get default VIEW intent handler.
Intent activityIntent = new Intent()
.setAction(Intent.ACTION_VIEW)
.addCategory(Intent.CATEGORY_BROWSABLE)
.setData(Uri.fromParts("http", "", null));
// Get all apps that can handle VIEW intents.
List<ResolveInfo> resolvedActivityList = pm.queryIntentActivities(activityIntent, 0);
ArrayList<ResolveInfo> packagesSupportingCustomTabs = new ArrayList<>();
for (ResolveInfo info : resolvedActivityList) {
Intent serviceIntent = new Intent();
serviceIntent.setAction(ACTION_CUSTOM_TABS_CONNECTION);
serviceIntent.setPackage(info.activityInfo.packageName);
// Check if this package also resolves the Custom Tabs service.
if (pm.resolveService(serviceIntent, 0) != null) {
packagesSupportingCustomTabs.add(info);
}
}
return packagesSupportingCustomTabs;
}

Android 11 ha introducido cambios en la visibilidad de los paquetes. Si tu aplicación para Android está dirigida al nivel de API 30 o superior, es necesario agregar una sección queries a AndroidManifest.xml, de lo contrario, el fragmento de código anterior no devolverá los resultados:

<queries>
<intent>
<action android:name=
"android.support.customtabs.action.CustomTabsService" />
</intent>
</queries>

Deja una respuesta

Tu dirección de correo electrónico no será publicada.