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"};
The App demo “iBKS Hello World” is a project that contains the most important functions to begin interacting with a Beacon.
In this document is explained how this project, implemented in swift and XCode 8.2.1, is structured and what are the functions that can be found on it.
AUDIENCE
This document is focused for App developers who have no experience in beacon communication management.
After downloading de “iBKS Hello World” project, you only have to open it on XCode, sign it with oyur developer provisioning and compile it. There are no extra libraries or steps you have to include. The project is structured to show three important functionalities, each one on a different class:
ScanViewController: scans and list the beacons that are advertising around and allows discovering services and characteristics. Services and characteristics will be printed in the XCode Output console. CoreBluetooth is used for this demo.
NotificationsViewController: Show a notification dialog on the App triggered by a specific beacon packet detected. Also includes the settings view which allows you to configure the parameters in the beacon the device is looking for. CoreLocation is used for this demo.
Background Monitoring (from AppDelegate): Starts background monitoring and ranging for beacons in a region and does some actions when detects them (send notification, open the app, …) even when the app is stopped. Background monitoring starts when APP goes to background and stops when APP comes to foreground. CoreLocation is used for this demo.
3. App permissions
Several permissions and requests are needed for this sample. Bluetooth and Location will be used for beacons scanning and ranging in foreground, and Local Notifications for the background monitoring in order to notify the user.
3.1. Location
In order to allow location in both foreground and background running mode, it is necessary to add the key “Privacy – Location Always Usage Description” in the Info.plist file. It should look like this:
Also request for location permissions in the AppDelegate in the “didFinishLaunchingWithOptions” method like thos:
The only step you should do in order to properly make Bluetooth work for this sample is enable the “Location updates” and “Uses Bluetooth LE accessories” in the Background Modes for the app Capabilities. This is needed only for the background feature.
Note that even if the CoreLocation and CoreBluetooth works properly for foreground scanning and ranging in this sample, if you plan to publish your app, adding some more privacy and usage keys for Bluetooth in the Info.plist file will be required. Please check the Apple Developers guide for more information.
The app capabilities should look like this (everything else is disabled):
3.3. Local Notifications
Request for Local Notifications is also requested in the AppDelegate inside the “didFinishLaunchingWithOptions” method right after the location permission with the following code:
let notificationSettings = UIUserNotificationSettings(types: [.sound, .alert], categories: nil)
UIApplication.shared.registerUserNotificationSettings(notificationSettings)
Same as for Bluetooth, Local Notification Usage description key may be needed in the Info.plist file if the app has to be published in the App Store.
4. Scan Bluetooth devices
All the needed functions used to scan Bluetooth devices are in ScanViewController. The steps to achieve that are:
Implement the CBCentralManagerDelegate in the ScanViewController
Define and start a CBCentralManager from “viewDidLoad” method. Assign delegate self to the central manager
When “.poweredOn” state is received in the “centralManagerDidUpdateState” method (which is necessary for the CBCentralManagerDelegate), scan can be started.
Scanned devices will be received in the “centralManager – didDiscover peripheral” method. Treat them properly according to your needs.
Optionally, connect to the device. In the project, the connection is made when a device of the list is clicked.
For the connection, CBPeripheralDelegate and its methods are needed. Once the connection starts, the status will be received in the “centralManager – didConnect” method. Then service and characteristics discovery can be started. For this feature all the steps are logged in the Output console in XCode.
The app shows a list of all Bluetooth devices detected with its own (and sorted by) RSSI, name and assigned UUID.
5. Notifications
In some cases, it’s useful to show a notification to the user when a specific beacon is detected in a particular distance range. This example is shown in NotificationsViewController. CoreLocation is used for this sample.
iOS only allow ranging for a limit of 20 devices. Set the parameters (UUID, Major, Minor, Range and Message) for the beacon you want to detect, define its region and stare ranging with CoreLocartion. These are the steps.:
Define the beacon region, with the UUID, Major and Minor of your beacon.
Start ranging for that region and wait for the beacon to be detected.
Once detected, check if it is close enough and the distance matches with the range you defined in the settings.
If the range matches for our region, show a dialog with the defined message also in settings.
6. Background Scan
Another interesting function is the background scan. This one allows to monitor the beacons in background even if the app is killed. Simple ranging is not allowed directly in background but there is a simple way to make it work.
iOS is able to monitor for a region (beacon) even if the app has been killed. It will report in “didEnterRegion” method when the beacon is detected (it can take up to 5 seconds) and it will only occur when the state switches from outside to inside the region.
It will also report in “didExitRegion” method when the beacon is not detected anymore for some time. This detection can take from 15sec. to 5min. in order to avoid false detections. This state will occur only when switching from inside to outside region.
Also, there is a “didDetermineState” method, which it is more useful as it reports the actual state and not only when switching states. It is the method used in this example. Also it is more safe to use in background according to Apple documentation.
All the background methods used for the CoreLocation are defined and delegate in the AppDelegat. For this sample, background monitoring is started in the “applicationDidEnterBackground” (and only if the switch in MainViewController is turned ON) and it will be stopped on the method “applicationWillEnterForeground”
When a beacon is detected in background by the OS, this will wake the APP for a max. period of 10 seconds in order to process any task needed. In this case, the task will be ranging the beacon in order to check its proximity and show, if necessary, a local notification. Note that as the ranging can take only 10 seconds max., if the beacon is not ranged properly or the proximity does not match the one set in settings, the notification won’t be shown, but the state will be switched anyway to inside region.
(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":"We are sorry, but this feature is available only if cookies on your browser are enabled.","added_to_cart_message":"\u003Cdiv class=\"woocommerce-notices-wrapper\"\u003E\u003Cdiv class=\"woocommerce-message\" role=\"alert\"\u003EProduct added to cart successfully\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
var elementorFrontendConfig = {"environmentMode":{"edit":false,"wpPreview":false,"isScriptDebug":false},"i18n":{"shareOnFacebook":"Share on Facebook","shareOnTwitter":"Share on Twitter","pinIt":"Pin it","download":"Download","downloadImage":"Download image","fullscreen":"Fullscreen","zoom":"Zoom","share":"Share","playVideo":"Play Video","previous":"Previous","next":"Next","close":"Close","a11yCarouselPrevSlideMessage":"Previous slide","a11yCarouselNextSlideMessage":"Next slide","a11yCarouselFirstSlideMessage":"This is the first slide","a11yCarouselLastSlideMessage":"This is the last slide","a11yCarouselPaginationBulletMessage":"Go to slide"},"is_rtl":false,"breakpoints":{"xs":0,"sm":480,"md":768,"lg":991,"xl":1440,"xxl":1600},"responsive":{"breakpoints":{"mobile":{"label":"Mobile Portrait","value":767,"default_value":767,"direction":"max","is_enabled":true},"mobile_extra":{"label":"Mobile Landscape","value":880,"default_value":880,"direction":"max","is_enabled":false},"tablet":{"label":"Tablet Portrait","value":991,"default_value":1024,"direction":"max","is_enabled":true},"tablet_extra":{"label":"Tablet Landscape","value":1200,"default_value":1200,"direction":"max","is_enabled":false},"laptop":{"label":"Laptop","value":1366,"default_value":1366,"direction":"max","is_enabled":false},"widescreen":{"label":"Widescreen","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":221075,"title":"iBKS%20Hello%20World%20for%20iOS%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=en","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/","is_multisite":"","current_blog_id":"1","texts":{"search_history_title":"Search History","search_history_clear_all":"Clear"},"add_to_label":"Add to cart","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":"en"};
//# sourceURL=porto-theme-js-extra