Temporarily silencing beep on Socket 7Xi barcode scanner - ios

I am using the Socket iOS SDK with the 7Xi scanner. The scanner is fast enough to register duplicate scans in quick succession if a user holds a barcode in front of the scanner when in stand mode. To handle this, I am simply removing my scan delegate when the first scan arrives, and not setting it again until I am ready for the next scan.
Of course, the scanner itself continues scanning. Is there some way to silence the beep while I am handling the scan, so that my users don't think the scan was correctly received when the app does not. It must be fast enough that I can reliably re-enable it within a second or so.

Background
The scanner has three confirmation modes (device, sdk and app) which determines who is responsible for acknowledging a barcode was scanned. The default is device, which will acknowledge any successful scan (i.e. the barcode type is supported and the device successfully decoded the barcode).
Solutions
Option 1
Currently, you remove the scan delegate, which doesn't prevent the scanner from scanning the next barcode; It only prevents your application from receiving the event notification. You provide ScanApiHelper with a timer routine that calls doReceive to check for new events and if it finds one it calls your delegate.
You could add a flag to your timer so that it will only call doReceive when you are ready to handle the next event.
There are two limitations to this approach. There will be a delay between the device acknowledgement and feedback from the application, if important feedback is provided, when a scan is held in the queue. Second, a queue is only suitable for handling a brief burst of activity, but your application will require downtime to catch back up.
Option 2
Caveat: I'm not sure if this works in presentation mode
Switch the confirmation mode to app and have your application acknowledge the barcode after it is done processing. This has the benefit of essentially locking out the scanner (it won't beep, flash or vibrate for any scan) unless your application has received and handled the barcode.
The downside here is there is a small lag between the barcode being read and the scanner acknowledging it, when using app confirmation mode. Adding an additional delay while processing the data may not be the best user experience.

Related

Best approach for continually scanning bluetooth devices on iOS as well as storing the peripheral data in background?

I am currently using CoreBluetooth to scan for peripherals. Every 30 seconds it sends its packet of information to the cloud by using a Timer. This is working good in foreground. I would like this exact operation to function seamlessly in the background too.
I have declared a CBUUID ahead of time for it seek out the designated peripheral in the background. Upon entering background mode, the scan stops functioning after 10~ seconds. How do I continually make the scan operate continue in the background?
I was looking into Bluetooth State Preservation, would this alleviate the issue? Should it also not be on the main thread?
After the packets are advertised I would like them stored in memory. I am aware the DiscoverPeripherals logs the peripherals... is it possible to log the RSSI and additional peripheral data in chronological order and have it an operation take affect per an interval? I was looking at BGProcessingTask to fire off a function in the background. Would a better approach be to use CoreData to store the memory and clear it after? Best/easy suggestion is appreicated.
I have changed the CBUUID to the right peripheral for centralManager.scanForPeripherals(withServices: [uuid], options: nil)
with uuid being the CBUUID. That seem to be allowing the peripheral to be detected in the background. It stopped logging the scan after a short period of time. Right when I put the app in background, it functions properly for a bit. I theorize it could just be calling it on the same thread and it may not be operating in the background all together. I did test this by changing the the withServices to nil, the result was that the operating was not being logged at all once I closed to the background.
I was expecting the operation to continually be scanning on the basis of the Timer every period, after the period is up it would send it the cloud just how it was doing it in the foreground.
There are lots of restrictions on iOS apps when they are not in the foreground. Once an app moves from the foreground it is suspended and can only execute in the background for specific reasons and for limited durations.
In general, anything based on a Timer will not fire when the app is not in the foreground.
Some Core Bluetooth events are delivered while your app is in the background:
Pending connect operations can complete with a corresponding delivery to your app.
Peripheral disconnections will be delivered to your app
GATT Notify/Indicate operations from a connected peripheral will be delivered to your app.
Discovery of new peripherals advertising a service that you are specifically scanning for will be delivered to your app.
It is this last behaviour that you are relying on.
While you have done the right thing by specifying the specific service you are interested in, your plans are being thwarted by the fact that Core Bluetooth will not deliver repeated discovery notifications for a particular peripheral.
When your app is in the foreground you can use the CBCentralManagerAllowDuplicatesKey option to request a discovery notification each time a peripheral advertisement is seen, even if an advertisement from that peripheral has been seen before. This option has no effect when your app is not in the background.
The best way to gather data on a periodic basis from a peripheral (whether in the background or foreground) is for that peripheral to send its data via Notify/Indicate, however you seem to be trying to scan for the existence of peripherals rather than gather specific data from them, so this may not work for you.
When one of the supported Core Bluetooth background events occurs and your app has been jettisoned, State restoration allows your app to respond after iOS relaunches your app. It will not help you in this case.
It probably isn't possible to do what you want, at least not without changing the behaviour of your peripheral.

Cancel or Flush AirPrint Jobs from iOS App

iOS has a printing feature known as AirPrint, which does not require to install a specific device driver. My iOS App prints an image data through AirPrint, but sometimes print queue of AirPrint gets stuck. Print queue of AirPrint is FIFO and if the first job remains with some reasons such as temporary network failure, the next job will not send to the printer.
Thus I wish to flush Print queue, or cancel a dead job in case of getting stuck in Print Queue. I know we can cancel printing jobs in Print Center (background app of iOS printing system), but I wish to do that in my own iOS app.
Questions:
(1) Can we cancel or clear printing jobs in Print Queue of AirPrint from iOS app?
(I really appreciate if you have a sample code of Swift to do such a thing!)
(2) Does anyone know how long it takes for printing jobs to get timed out?
Any suggestion would be welcomed.
Reference of AirPrint:
https://developer.apple.com/library/archive/documentation/2DDrawing/Conceptual/DrawingPrintingiOS/Printing/Printing.html#//apple_ref/doc/uid/TP40010156-CH12-SW2
There is a UI available in iOS for PrintJob Management. So there might be an API available.
If an iOS-PrintJob returns the ipp job-uri you could implement print job management within your app. You'd have to implement the ipp protocol and support the Cancel-Job operation.
iOS uses CUPS as ipp client. I have analysed the behaviour of iOS by running tests against my own AirPrint implementation. The http User-Agent used is "CUPS/2.3.4 (iOS 14.4.2; iPad8,3) IPP/2.0"
iOS only cares about successful print job submission.
It does query the job state though via the Get-Job-Attributes operation. It would make sense that iOS presents a UI that allows the user to monitor (and control) a print job. We should file a bug or feature request for iOS #Apple.
iOS also queries the printer state. In my tests when I stop my AirPrint server I get notified that the printer is offline and I am presented an option to cancel or try again.
When the printer-state is 'stopped' and reason is 'paused' the print center is available!
Summary:
Job monitoring and control is available via the print center.
It depends on the AirPrint implementation wether the print center shows up.

Objective-c long-running background service for bluetooth, when app backgrounded

I can't seem to find the right documentation, tutorial or SO post to point me towards the right implementation so far... even though there are many posts about this topic floating around.
Problem
I have an app that connects (pairs) to a BT device I built. What I want, is when the user presses the home button or backgrounds the app I want to send an update through a BT service layer to a BT device on a regular interval. I am doing this now (only fires once) in the applicationWillResignActive and applicationDidEnterBackground methods and it works perfectly. The problem is that I can only perform this once it seems. Any loops, timers, background type services that I start up in these methods, die very soon there after.
What I need
Is for the application to keep looking for my BT device in the background and every 10 seconds or so and send an update to the device. I first need to check to make sure the app is still backgrounded, but once I know its in the background I wanna send the update. When the app comes back in focus I can stop the updates to the BT device but its crucial that it sends them when the app is not in focus.
Research
I have found these SO posts (long-running tasks, background task execution handler, using this in an NSTimer loop... but it dies) but they have not helped with implementation at all.
When I wrote this post I was far too new to OBJ-C and didn't quite understand the concept of delegate methods with the proper access level to fire in the background (i.e. info.plist access under bluetooth-central).
The end result a month later was to build a peripheral device that could wake up the application in a timed loop via subscribed characteristic updates. Once the app wakes up, you have 10 seconds to handle the event that has just occurred and since I am only saving off a copy of the data that the device posted, all is well.

Syncing data over BLE via iOS without App Open (or in the background)

I'm working on a device that keeps count when a door is closed. What I'd like to do is when I walk through the door, my iPhone automatically syncs the data on the device and sends that count to the server (via iPhone) without me opening the app or having it in the background. Is this possible, if so how?
Here's a diagram of what I'm thinking:
Door closes -> BLE notifies iPhone -> BLE sends count to iPhone ->
iPhone sends that value to server
All without the user (me) touching my device or opening the installed iOS application.
Your app has to be running in the background to do something, but that is OK, because Core Bluetooth background mode will take care of that for you.
First, you need to select "Uses Bluetooth accessories" background mode in your project.
Now, your program flow will be something like this:
Your user runs your app which scans for available doors and displays them to the user
Your user selects a door that they want to connect to
You save the identifier of the selected peripheral somewhere like NSUserDefaults
You connect to the peripheral
Once you get a call to the didConnectPeripheral delegate method you can read the count and update your server once you get the value
The user can now suspend your app and do something else
Eventually the peripheral will go out of range and you will get a call to didDisconnectPeripheral. In this method you immediately re-issue the connect to the peripheral.
Since you have Core Bluetooth background mode, when the peripheral is eventually seen again you will get another call to didConnectPeripheral in the background, and you can proceed as per step 5 (In this case your app is already in the background so it will just go back to suspended state after you have read the data without the user doing anything).
You update the server in step 5. This step executes regardless of whether the app is in the foreground or background. The user doesn't need to open your app.
Now eventually iOS may remove your app from the suspended state, say due to memory pressure. In order to still be able to connect to the peripheral when it is seen you need to opt in to state restoration as described in the Core Bluetooth Programming Guide
If you are up for building your own circuit board and Bluetooth LE firmware, this is pretty straightforward:
Add a contact switch that sends a voltage level change to the circuit board whenever the door opens.
Increment a counter on the microcontroller when the level changes.
Write firmware that advertises an iBeacon packet with the counter as the least significant part of the iBeacon identifier (32 bit major and minor).
A phone can then pick up this counter by using CoreLocation APIs to both monitor for the beacon (for fast background wakeups) and range for it (to read the specific identifier), then sending the counter value to the server based on the identifier read.
The advantage of using CoreLocation instead of CoreBluetooth as #paulw11 suggests in his very good answer is faster background wakeups of the app, allowing an app to reliably read the counter in the background. With CoreBluetooth, this background wakeup can be much slower, and door open events are more likely to be missed.

iBeacon background monitoring stops working

I have an app that monitors iBeacons entry/exit events. When it receives an event it forwards the event off to a server. The app continues to work (e.g., the server continues to receive updates) after the user minimizes and/or force closes it (so it works correctly in the background).
However, after a phone has been away from any iBeacons for a sufficient amount of time (e.g., overnight) and is brought near iBeacons again, the app stops receiving enter/exit updates until the user opens it up again (brings it into the foreground). If the user minimizes/closes the app at that point, updates continue to work correctly in the background.
Is anything that I need to do to allow long running monitoring updates in the background? After a while does iOS stop background monitoring?
Note: I am running iOS 9.3.1
iOS Apps are supposed to be able to detect beacons indefinitely in the background when they have been granted "always" location access.
This is the second report I have heard like this, so I wonder if it is a bug or a change in a new iOS version. Reporting your iOS version would be helpful.
One possibility: the network calls may be being blocked and not the beacon detections. You could test this hypothesis by adding NSLog statements to :
Log on beacon detection
Log on successful and unsuccessful connection to the server.
Once you add the above, reproduce the issue where you don't see events on your server. Then connect your phone to XCode and go to Devices, and look at the recent NSLog output to see:
Is there a line indicating the beacon was detected?
Was the server connection successful or not?
If you find it is the network connection that is failing, you may be able to correct the situation by requesting additional background network permissions.
EDIT: One other thing you might try when a detection is not made is launching a different beacon scanner app in the foreground like Locate. This will force an OS bluetooth scan and it might kick off your app's detection. If this works, it would tell you that bluetooth scanning had been suspended across the phone.

Resources