In iOS 10+, is there ANY way to RELIABLY wake up a

2019-02-28 11:32发布

I have been at this over 3 months and pulling my hair out. So please don't respond with beginner answers.

I am wondering if, in 2017 with iOS 10+, there is ANY way possible to wake up the app from terminated state... preferably by bluetooth peripheral... but i'll take what I can get!

I consider terminated to be when user swiped the app in task manager or when the peripheral is turned on/off and the app was already dead

I need important health related BT peripheral data (recorded by BT device) maintained in the app so I need a consistent connection or the ability to wake the app back up and handle the data. I know this is asked a lot so I am trying to find the most current understanding or solutions to this problem. I have read sooo many articles and S.O. posts on this so I know Core Bluetooth is un-reliable at best. I know the general concept is flaky and people have been saying since 2010 its not possible. However, lots keeps changing in iOS so I was hoping something would have changed.

To be clear:

BT wake up would be great but it's really not been reliable, so... I will take ANY kind of reliable wake up (location, audio, BT, etc... NOT iBeacon though since I am connected/paired to BT device). If I have to "hack" the wake up to happen on location or audio and then quickly get the data from the peripheral somehow, I will take it!

I have tried:

(SKIP THIS IF YOU DON'T CARE OR IS NOT APPLICABLE)


  • Background central mode turned on in info.plist
  • Using full state restoration, that is to say, this code...

    self.centralManager = [[CBCentralManager alloc] initWithDelegate:self
                                                               queue:nil
                                                                 options:@{CBCentralManagerOptionShowPowerAlertKey: @(YES),
                                                                           CBCentralManagerOptionRestoreIdentifierKey:@"MyDevice"}];
    

    To register the identifier key and this code...

    - (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        NSLog(@"launch options found: %@", launchOptions);
        NSArray *centralManagerIdentifiers = launchOptions[UIApplicationLaunchOptionsBluetoothCentralsKey];
    
        NSLog(@"central managers found in launch options: %@", centralManagerIdentifiers);
        [self triggerLocalNotification:[NSString stringWithFormat:@"central managers found in launch options: %@", centralManagerIdentifiers]];
    
        if([centralManagerIdentifiers count] > 0) {
            for(NSString *identifier in centralManagerIdentifiers) {
                if([identifier isEqualToString:@"MyDevice"]) {
                    [self triggerLocalNotification:[NSString stringWithFormat:@"Identifier found: %@", identifier]];
                    self.bluetoothManager = [BluetoothMgr sharedInstance];
                }
            }
        }
    
        return YES;
    }
    
    - (void)centralManager:(CBCentralManager *)central
      willRestoreState:(NSDictionary<NSString *,id> *)state {
    
        NSLog(@"************** RESTORED STATE BT **************");
        [self triggerCustomLocalNotification:@"************** RESTORED STATE BT **************"];
    
        NSLog(@"central manager object: %@", central);
        NSLog(@"state dictionary: %@", state);
    
        [self triggerCustomLocalNotification:[NSString stringWithFormat:@"state dictionary: %@", state]];
    
    
        NSArray *restoredPeripherals = [state objectForKey:@"CBCentralManagerRestoredStatePeripheralsKey"];
    
        self.centralManager = central;
        self.centralManager.delegate = self;
    
        if([restoredPeripherals count] > 0) {
            for(CBPeripheral *peripheral in restoredPeripherals) {
                if([peripheral.name rangeOfString:@"mybox-"].location != NSNotFound) {
                    NSLog(@"Restoring mybox Box: %@", peripheral);
                    [self triggerCustomLocalNotification:[NSString stringWithFormat:@"Peripheral was found in WILL RESTORE STATE! it was: %@", peripheral]];
    
                    self.myPeripheral = peripheral;
                    self.myPeripheral.delegate = self;
    
                    [self connectToDevice];
    
                    return;
                }
            }
        }
    }
    

    To restore the central manager state. This only works when the app is killed by iOS or the state is changed. Does not work when the user kills the app.

  • Subscribing to a notifying characteristic in the device (I made this custom characteristic and I have full control over the programming of the device) ... this works really well but does not always wake the app up. Works well in background though. Just not terminated.

  • Trying to disconnect completely upon termination so that I can use iBeacon to wake back up... too many hoops and in the end it does not work reliably at all.
  • Significant location updates... extremely unreliable
  • Audio recording... no methods fire when it begins recording (that I could find anyway) or methods that fire intermittently while recording

1条回答
小情绪 Triste *
2楼-- · 2019-02-28 12:21

Finally solved this problem! The solution was to use 2 Bluetooth chips in my solution. One chip to be a dedicated BT-Connected Paired/Auth/Bonded device and the other to be a dedicated iBeacon advertiser. With this solution I was able to both, wake up the app whenever I want (by power cycling the iBeacon chip at will) and connecting for BT encryption required characteristics.

Using the didEnterRegion method of the CLLocationManager class, in the background, I can start up the bluetooth manager... connect to the device in the background and then retrieve data successfully over a previously paired connection.

UPDATE: as a side note, it's good to mention that while the iBeacon is fairly reliable in waking up the application in the background, only the didEnterRegion method happens immediately when the iBeacon is found or turned on. The didExitRegion method takes me (on average) about 30 seconds to fire after I turn off the iBeacon or it is no longer in range.

查看更多
登录 后发表回答