var monsterinsights_frontend = {"js_events_tracking":"true","download_extensions":"doc,pdf,ppt,zip,xls,docx,pptx,xlsx","inbound_paths":"[{\"path\":\"\\\/go\\\/\",\"label\":\"affiliate\"},{\"path\":\"\\\/recommend\\\/\",\"label\":\"affiliate\"}]","home_url":"https:\/\/accent-systems.com","hash_tracking":"false","v4_id":"G-069LN2YPE1"};
La demo de la App “iBKS Hello World” es un proyecto que contiene las funciones más importantes para comenzar a interactuar con un Beacon.
Este documento explica cómo está estructurado este proyecto, implementado para Android Studio, y cuáles son las funciones que se pueden encontrar en él.
PÚBLICO
Este documento está enfocado para desarrolladores de Apps que no tienen experiencia en la gestión de comunicación con beacons.
Después de descargar el proyecto “iBKS Hello World”, solo tienes que abrirlo en Android Studio y compilarlo. Todas las bibliotecas necesarias están incluidas como dependencias y se descargan automáticamente. El proyecto está estructurado para mostrar tres funcionalidades importantes, cada una en una clase diferente:
ScanActivity: escanea y lista los beacons que están anunciando alrededor y permite el descubrimiento de servicios y características.
NotificationDemo: Muestra un diálogo de notificación en la App activado por un paquete de beacon específico detectado.
BackgroundScan: Inicia un escaneo en segundo plano que permite detectar beacons y realizar algunas acciones (enviar notificación, abrir la app, …) incluso cuando la app está detenida. La primera actividad iniciada en primer plano es “MainActivity” que muestra las diferentes opciones de la app y también verifica los permisos de la app.
3. Permisos de la App
Para gestionar Bluetooth en Android es necesario solicitar el permiso del usuario.
3.1. Ubicación
Si la versión de Android es 6.0 o superior, es necesario solicitar permiso de ubicación. Para hacer esto es necesario agregar permiso en AndroidManifest.xml
El método que verifica los permisos de ubicación es checkLocBT() en MainActivity.
3.2. Bluetooth
Para usar Bluetooth en dispositivos Android, lo primero que hay que hacer es verificar si el dispositivo que ejecuta la app tiene Bluetooth Low Energy (los beacons funcionan con este tipo de protocolo) y si está habilitado. Para habilitar Bluetooth es necesario agregar permiso en AndroidManifest.xml
El método que verifica los permisos de ubicación es inicializeBluetooth() en MainActivity.
4. Escanear dispositivos Bluetooth
Todas las funciones necesarias utilizadas para escanear dispositivos Bluetooth están en ScanActivity. Los pasos para lograrlo son:
Inicializar el Adaptador Bluetooth y configurar los ajustes de escaneo: initBT()
Iniciar el Escaneo BLE con los ajustes definidos y el correspondiente ScanCallback: startLeScan()
Esperar paquetes Bluetooth en el callback ScanCallback (onScanResult) y realizar alguna acción dependiendo del RSSI, publicidad, etc.
Opcionalmente, conectar al dispositivo. En el proyecto, la conexión se realiza cuando se hace clic en un dispositivo de la lista: onItemClick1.
Una vez realizada la conexión, se recibe un callback BluetoothGattCallback (onConnectionStateChange) y es posible descubrir servicios, leer y escribir las características y habilitar notificaciones (todas estas acciones generan un callback BluetoothGattCallback ). Al final de la clase ScanActivity hay algunos ejemplos de estas acciones.
1 Nota: En dispositivos Samsung, la conexión debe hacerse en el hilo principal
La app muestra una lista de todos los dispositivos Bluetooth detectados con su propio RSSI y MAC.
5. Notificaciones
En algunos casos, es útil mostrar una notificación al usuario cuando se detecta un beacon específico en un rango de distancia particular. Este ejemplo se muestra en el NotificationDemo.
La forma más común de detectar un beacon específico es comprobando el identificador anunciado en el paquete Bluetooth, ya sea un paquete iBeacon o Eddystone-UID. Los pasos para lograrlo son:
Iniciar el escaneo como se ve en ScanActivity.
Esperar paquetes Bluetooth en el callback ScanCallback.
Comprobar si los datos de publicidad contienen el identificador deseado. En este proyecto, se utiliza el identificador introducido en el diálogo de configuración.
Opcionalmente, verificar el RSSI para activar la acción solo para un rango de distancia particular entre el beacon y el usuario. En este proyecto definimos tres rangos diferentes (Inmediato, Cercano, Lejano)
Si todas las condiciones son verdaderas, mostrar el diálogo con la información deseada: showDialog()
6. Escaneo en segundo plano
Otra función interesante es el escaneo en segundo plano. Este permite escanear publicidades cuando la app está en segundo plano y también iniciar algunas acciones cuando se detecta el beacon. El ejemplo de un escaneo en segundo plano está en la clase BackgroundScan. Para ejecutar el proceso en segundo plano, es necesario agregarlo a AndroidManifest.xml (ya agregado en el proyecto):
El escaneo en segundo plano utiliza una biblioteca de código abierto externa. Para usar esta biblioteca es necesario agregar al app build.gradle la siguiente dependencia (ya agregada en el proyecto):
compile 'org.altbeacon:android-beacon-library:2+'
Los pasos para configurar el escaneo en segundo plano son:
Configurar Layouts de Beacon. En el proyecto hay un ejemplo de layouts iBeacon y Eddystone-UID, pero en la biblioteca de código abierto puedes encontrar más tipos de tramas.
Configurar el periodo de escaneo en primer plano y en segundo plano. Por favor, ten cuidado al elegir el periodo porque si es muy corto el dispositivo Android tendrá un alto consumo de batería debido a que Bluetooth está escaneando muy a menudo.
Crear las regiones. Es lo mismo que crear una lista de identificadores que se verificarán en cada periodo de escaneo.
Vincular la Actividad BackgroundScan al BeaconService (mBeaconManager.bind(this)). Cuando se recibe el callback onBeaconServiceConnection, habilitar las regiones e iniciar el escaneo (enableRegions()).
Esperar el callback llamado en cada periodo de escaneo, a través de la función didRangeBeaconsInRange, y verificar si se han encontrado los beacons.
Opcionalmente, se puede enviar una notificación al usuario cuando se detecta un beacon. Hay un código de ejemplo para crear una notificación en el proyecto.
(function() {
var data = {"agents":[{"name":"Eli","phone":"+34653105809","time_start":"08:00","time_end":"17:00","days":[1,2,3,4,5]},{"name":"Albert","phone":"+34662925746","time_start":"08:00","time_end":"17:00","days":[1,2,3,4,5]}],"distribution":"random","message":"Hello! I would like to ask for more info."};
var button = document.getElementById('accent-whatsapp-button');
var agentsPanel = document.getElementById('accent-whatsapp-agents');
if (!button) return;
button.addEventListener('click', function(e) {
e.preventDefault();
if (data.distribution === 'all' && data.agents.length > 1 && agentsPanel) {
// Mostrar panel d'agents
agentsPanel.classList.toggle('active');
} else {
// Obrir WhatsApp directament amb un agent
var agent = data.distribution === 'random'
? data.agents[Math.floor(Math.random() * data.agents.length)]
: data.agents[0];
var phone = agent.phone.replace(/[^0-9]/g, '');
var message = encodeURIComponent(data.message);
var url = 'https://wa.me/' + phone + '?text=' + message;
window.open(url, '_blank');
}
});
// Tancar panel si es fa clic fora
document.addEventListener('click', function(e) {
if (agentsPanel && !e.target.closest('#accent-whatsapp')) {
agentsPanel.classList.remove('active');
}
});
})();
var yith_wcwl_l10n = {"ajax_url":"/wp-admin/admin-ajax.php","redirect_to_cart":"no","yith_wcwl_button_position":"after_add_to_cart","multi_wishlist":"","hide_add_button":"1","enable_ajax_loading":"","ajax_loader_url":"https://accent-systems.com/wp-content/plugins/yith-woocommerce-wishlist/assets/images/ajax-loader-alt.svg","remove_from_wishlist_after_add_to_cart":"1","is_wishlist_responsive":"1","time_to_close_prettyphoto":"3000","fragments_index_glue":".","reload_on_found_variation":"1","mobile_media_query":"768","labels":{"cookie_disabled":"Lo siento, pero esta caracter\u00edstica solo est\u00e1 disponible si las cookies de tu navegador est\u00e1n activadas.","added_to_cart_message":"\u003Cdiv class=\"woocommerce-notices-wrapper\"\u003E\u003Cdiv class=\"woocommerce-message\" role=\"alert\"\u003EProducto a\u00f1adido al carrito con \u00e9xito\u003C/div\u003E\u003C/div\u003E"},"actions":{"add_to_wishlist_action":"add_to_wishlist","remove_from_wishlist_action":"remove_from_wishlist","reload_wishlist_and_adding_elem_action":"reload_wishlist_and_adding_elem","load_mobile_action":"load_mobile","delete_item_action":"delete_item","save_title_action":"save_title","save_privacy_action":"save_privacy","load_fragments":"load_fragments"},"nonce":{"add_to_wishlist_nonce":"7ba1a2a9f8","remove_from_wishlist_nonce":"19d18a882f","reload_wishlist_and_adding_elem_nonce":"86a7832a2a","load_mobile_nonce":"ec05872196","delete_item_nonce":"74b7410ba2","save_title_nonce":"f638aac7a9","save_privacy_nonce":"519d76fa22","load_fragments_nonce":"9fe401de99"},"redirect_after_ask_estimate":"","ask_estimate_redirect_url":"https://accent-systems.com","enable_notices":""};
//# sourceURL=jquery-yith-wcwl-js-extra
( function( domain, translations ) {
var localeData = translations.locale_data[ domain ] || translations.locale_data.messages;
localeData[""].domain = domain;
wp.i18n.setLocaleData( localeData, domain );
} )( "contact-form-7", {"translation-revision-date":"2025-12-01 15:45:40+0000","generator":"GlotPress\/4.0.3","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","plural-forms":"nplurals=2; plural=n != 1;","lang":"es"},"This contact form is placed in the wrong place.":["Este formulario de contacto est\u00e1 situado en el lugar incorrecto."],"Error:":["Error:"]}},"comment":{"reference":"includes\/js\/index.js"}} );
//# sourceURL=contact-form-7-js-translations
var elementorFrontendConfig = {"environmentMode":{"edit":false,"wpPreview":false,"isScriptDebug":false},"i18n":{"shareOnFacebook":"Compartir en Facebook","shareOnTwitter":"Compartir en Twitter","pinIt":"Pinear","download":"Descargar","downloadImage":"Descargar imagen","fullscreen":"Pantalla completa","zoom":"Zoom","share":"Compartir","playVideo":"Reproducir v\u00eddeo","previous":"Anterior","next":"Siguiente","close":"Cerrar","a11yCarouselPrevSlideMessage":"Diapositiva anterior","a11yCarouselNextSlideMessage":"Diapositiva siguiente","a11yCarouselFirstSlideMessage":"Esta es la primera diapositiva","a11yCarouselLastSlideMessage":"Esta es la \u00faltima diapositiva","a11yCarouselPaginationBulletMessage":"Ir a la diapositiva"},"is_rtl":false,"breakpoints":{"xs":0,"sm":480,"md":768,"lg":991,"xl":1440,"xxl":1600},"responsive":{"breakpoints":{"mobile":{"label":"M\u00f3vil vertical","value":767,"default_value":767,"direction":"max","is_enabled":true},"mobile_extra":{"label":"M\u00f3vil horizontal","value":880,"default_value":880,"direction":"max","is_enabled":false},"tablet":{"label":"Tableta vertical","value":991,"default_value":1024,"direction":"max","is_enabled":true},"tablet_extra":{"label":"Tableta horizontal","value":1200,"default_value":1200,"direction":"max","is_enabled":false},"laptop":{"label":"Port\u00e1til","value":1366,"default_value":1366,"direction":"max","is_enabled":false},"widescreen":{"label":"Pantalla grande","value":2400,"default_value":2400,"direction":"min","is_enabled":false}},"hasCustomBreakpoints":true},"version":"3.35.8","is_static":false,"experimentalFeatures":{"e_font_icon_svg":true,"additional_custom_breakpoints":true,"container":true,"e_optimized_markup":true,"e_pro_free_trial_popup":true,"nested-elements":true,"home_screen":true,"global_classes_should_enforce_capabilities":true,"e_variables":true,"cloud-library":true,"e_opt_in_v4_page":true,"e_components":true,"e_interactions":true,"e_editor_one":true,"import-export-customization":true},"urls":{"assets":"https:\/\/accent-systems.com\/wp-content\/plugins\/elementor\/assets\/","ajaxurl":"https:\/\/accent-systems.com\/wp-admin\/admin-ajax.php","uploadUrl":"https:\/\/accent-systems.com\/wp-content\/uploads"},"nonces":{"floatingButtonsClickTracking":"3b300235ba"},"swiperClass":"swiper","settings":{"page":[],"editorPreferences":[]},"kit":{"viewport_tablet":"991","active_breakpoints":["viewport_mobile","viewport_tablet"],"global_image_lightbox":"yes","lightbox_enable_counter":"yes","lightbox_enable_fullscreen":"yes","lightbox_enable_zoom":"yes","lightbox_enable_share":"yes","lightbox_title_src":"title","lightbox_description_src":"description"},"post":{"id":221807,"title":"iBKS%20Hello%20World%20para%20Android%20-%20Accent%20Systems","excerpt":"","featuredImage":false}};
//# sourceURL=elementor-frontend-js-before
var js_porto_vars = {"rtl":"","theme_url":"https://accent-systems.com/wp-content/themes/porto-child","ajax_url":"https://accent-systems.com/wp-admin/admin-ajax.php?lang=es","cart_url":"https://accent-systems.com/cart/","change_logo":"","container_width":"1140","grid_gutter_width":"30","show_sticky_header":"1","show_sticky_header_tablet":"1","show_sticky_header_mobile":"","ajax_loader_url":"//accent-systems.com/wp-content/themes/porto/images/ajax-loader@2x.gif","category_ajax":"","compare_popup":"1","compare_popup_title":"","prdctfltr_ajax":"","slider_loop":"1","slider_autoplay":"","slider_autoheight":"","slider_speed":"5000","slider_nav":"","slider_nav_hover":"1","slider_margin":"","slider_dots":"1","slider_animatein":"","slider_animateout":"","product_thumbs_count":"4","product_zoom":"1","product_zoom_mobile":"1","product_image_popup":"1","zoom_type":"inner","zoom_scroll":"1","zoom_lens_size":"200","zoom_lens_shape":"square","zoom_contain_lens":"1","zoom_lens_border":"1","zoom_border_color":"#888888","zoom_border":"0","screen_xl":"1170","screen_xxl":"1420","mfp_counter":"%curr% of %total%","mfp_img_error":"\u003Ca href=\"%url%\"\u003EThe image\u003C/a\u003E could not be loaded.","mfp_ajax_error":"\u003Ca href=\"%url%\"\u003EThe content\u003C/a\u003E could not be loaded.","popup_close":"Close","popup_prev":"Previous","popup_next":"Next","request_error":"The requested content cannot be loaded.\u003Cbr/\u003EPlease try again later.","loader_text":"Loading...","submenu_back":"Back","porto_nonce":"c0a6534a6f","use_skeleton_screen":[],"user_edit_pages":"","quick_access":"Click to edit this element.","goto_type":"Go To the Type Builder.","legacy_mode":"","home_url":"https://accent-systems.com/es/inicio/","is_multisite":"","current_blog_id":"1","texts":{"search_history_title":"Search History","search_history_clear_all":"Clear"},"add_to_label":"A\u00f1adir al carrito","login_popup_waiting_msg":"Please wait...","wc_placeholder_img":"https://accent-systems.com/wp-content/uploads/woocommerce-placeholder-300x300.png","shop_filter_layout":null,"func_url":"https://accent-systems.com/wp-content/plugins/porto-functionality/","active_lang":"es"};
//# sourceURL=porto-theme-js-extra
(function() {
var data = {"lang":"es","siteUrl":"https:\/\/accent-systems.com","translations":{"Home":"Inicio","Devices":"Dispositivos","Shop":"Tienda","Products":"Productos","Categories":"Categor\u00edas"},"pageSlugMap":{"devices":"dispositivos","development-services":"servicios-desarrollo","about-us":"sobre-nosotros","contact-us":"contacto","projects":"proyectos","team":"equipo","blog":"blog-es"}};
function fixBreadcrumbs() {
// Buscar tots els breadcrumbs (NOMÉS breadcrumbs, no language switchers)
var breadcrumbs = document.querySelectorAll('.breadcrumbs-wrap, .breadcrumb, .woocommerce-breadcrumb, [class*="breadcrumb"]');
breadcrumbs.forEach(function(bc) {
// Saltar si és un language switcher
if (bc.closest('.asw-wrap') || bc.closest('.asw-lang') || bc.classList.contains('asw-wrap') || bc.classList.contains('asw-lang')) {
return;
}
var links = bc.querySelectorAll('a');
links.forEach(function(link) {
// Saltar links dins de language switchers
if (link.closest('.asw-wrap') || link.closest('.asw-lang')) {
return;
}
var text = link.textContent.trim();
var href = link.getAttribute('href');
// Traduir text
if (data.translations[text]) {
link.textContent = data.translations[text];
}
// Arreglar URLs
if (href) {
var newHref = href;
// Arreglar URL del home (va directament al site sense /es/)
if (href === data.siteUrl || href === data.siteUrl + '/') {
newHref = data.siteUrl + '/' + data.lang + '/';
}
// Arreglar pàgines amb slug EN
else {
for (var enSlug in data.pageSlugMap) {
var esSlug = data.pageSlugMap[enSlug];
var pattern = new RegExp('^' + data.siteUrl.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + '/' + enSlug + '/?$');
if (pattern.test(href)) {
newHref = data.siteUrl + '/' + data.lang + '/' + esSlug + '/';
break;
}
}
}
// Arreglar categories sense prefix d'idioma
if (href.indexOf('/product-category/') !== -1 && href.indexOf('/' + data.lang + '/') === -1) {
newHref = href.replace('/product-category/', '/' + data.lang + '/product-category/');
}
if (newHref !== href) {
link.setAttribute('href', newHref);
}
}
});
});
}
// Executar quan el DOM estigui llest
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', fixBreadcrumbs);
} else {
fixBreadcrumbs();
}
// També executar després d'un petit delay per assegurar que tot s'ha carregat
setTimeout(fixBreadcrumbs, 100);
})();