Open kiritm-nimblechapps opened 6 years ago
@kiritnim for IOS enable Acts as a Bluetooth LE Accessory in Capabilities -> Background Modes, the detection wasn't working while the screen was locked.
Does anybody have a working app for Android? As @kiritnim said it's working fine for foreground background, but not when the app is killed.
there is any update if the app killed ?
For iOS, open RNiBeacon.m
and add following code to it:
- (instancetype)init
{
if (self = [super init]) {
...
self.locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
self.locationManager.allowsBackgroundLocationUpdates = true;
...
}
return self;
}
RCT_EXPORT_METHOD(startMonitoringForRegion:(NSDictionary *) dict)
{
[self.locationManager startMonitoringSignificantLocationChanges]; // Add this
...
}
RCT_EXPORT_METHOD(stopMonitoringForRegion:(NSDictionary *) dict)
{
[self.locationManager stopMonitoringSignificantLocationChanges]; // Add this
...
}
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{
NSLog(@"[Beacon][Native] didUpdateToLocation");
}
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{
NSLog(@"[Beacon][Native] didUpdateLocations");
}
When you kill the app from Task (Double Home), you will need to send a push notification with content_available=true to user device to start the app in background (without UI)
For me, i have modified the AppDelegate.m
with following:
- (void)applicationWillTerminate:(UIApplication *)application {
NSLog(@"[Beacon] The application has been terminated, sending out notification to launch application in background");
// Get data from AsyncStorage with Persist plugin
NSDictionary *json = [self jsonFromLocalRNStrogeForKey:@"persist:root"];
NSString *auth = [json valueForKeyPath:@"auth"];
auth = [auth substringFromIndex:1]; //
auth = [auth substringToIndex:[auth length] - 1];
auth = [auth stringByReplacingOccurrencesOfString:@"\\\""
withString:@"\""];
NSLog(@"auth %@", auth);
NSError *authDataError;
NSDictionary *authJson = [NSJSONSerialization JSONObjectWithData:[auth dataUsingEncoding:NSUTF8StringEncoding] options:0 error:&authDataError];
if(authDataError == nil) {
NSString *accessToken = [authJson valueForKeyPath:@"data.accessToken"]; // Get access token
NSString *userId = [authJson valueForKeyPath:@"data.currentUser.id"]; // Get current user id
NSString *apiUrl = [ReactNativeConfig envFor:@"API_URL"]; // get domain api from react-native-config
NSString *notificationTitle = [ReactNativeConfig envFor:@"NotificationTitle"];
NSString *requestUrl = [NSString stringWithFormat:@"%@/notification", apiUrl];
NSDictionary *jsonData = [[NSDictionary alloc] initWithObjectsAndKeys:
@"true", @"content_available",
notificationTitle, @"title",
userId, @"userId",
@"The app has entered the background", @"message",
nil];
NSError* error;
NSData* data = [NSJSONSerialization dataWithJSONObject:jsonData options:0 error:&error];
NSString *dataString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"POST DATA: %@", dataString);
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setHTTPMethod:@"POST"];
NSLog(@"URL: %@", requestUrl);
[request setURL:[NSURL URLWithString:requestUrl]];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
NSString *authorizationToken = [NSString stringWithFormat:@"Bearer %@", accessToken];
[request setValue:authorizationToken forHTTPHeaderField:@"Authorization"];
[request setHTTPBody:[dataString dataUsingEncoding:NSUTF8StringEncoding]];
NSLog(@"Request Headers:");
for (NSString *header in [request allHTTPHeaderFields])
{
NSLog(@"%@: %@", header,[request valueForHTTPHeaderField:header]);
}
NSError *responseError;
NSURLResponse *response = nil;
sleep(2);
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&responseError];
if (!error) {
NSLog(@"Response String : %@", [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding]);
id json = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:nil];
NSLog(@"Parsed Data : %@", json);
}
}
}
I have modified the code on my fork, feel free to use it https://github.com/MacKentoch/react-native-beacons-manager or install with npm $ npm install @nois/react-native-beacons-manager
In my fork, i have modified Android code as well to make it start the application automatically when user enter the Beacon Region.
In the react-native side, remember do not remove beacon event on componentWillUnmount, it will stop the beacon from scanning because when you kill the app, the component will be destroyed as well.
react-native code example:
## Android
constructor(props) {
super(props);
this.region = {
identifier: Config.beaconIdentifier,
uuid: Config.beaconUUID
};
}
componentDidMount() {
// Tells the library to detect iBeacons
Beacons.setForegroundScanPeriod(5000);
Beacons.setBackgroundScanPeriod(5000);
Beacons.detectIBeacons();
this.beaconEventListener = Beacons.BeaconsEventEmitter.addListener('beaconsDidRange', this.beaconsDidRange);
/*
Monitoring: actions triggered on entering/exiting region’s range;
works no matter whether the app is running, suspended, or killed (if the app's not running when an enter/exit even comes,
iOS will launch it into the background for a few seconds to handle the event)
*/
Beacons.startMonitoringForRegion(this.region);
/*
Ranging: actions triggered based on proximity to a beacon; works only when the app is running
(e.g., it's displayed on screen, or running in the background in response to a monitoring event, etc.)
*/
Beacons.startRangingBeaconsInRegion(this.region);
}
## iOS
constructor(props) {
super(props);
this.region = {
identifier: Config.beaconIdentifier,
uuid: Config.beaconUUID
};
}
componentDidMount() {
// Listen for beacon changes
this.beaconEventListener = Beacons.BeaconsEventEmitter.addListener(
'beaconsDidRange',
this.beaconsDidRange
);
this.regionDidEnterListener = Beacons.BeaconsEventEmitter.addListener(
'regionDidEnter',
this.regionDidEnter
);
this.didDetermineStateListener = Beacons.BeaconsEventEmitter.addListener(
'didDetermineState',
this.didDetermineState
);
this.authorizationStatusDidChangeListener = Beacons.BeaconsEventEmitter.addListener(
'authorizationStatusDidChange',
this.authorizationStatusDidChange
);
Beacons.requestAlwaysAuthorization();
Beacons.allowsBackgroundLocationUpdates(true);
/*
Monitoring: actions triggered on entering/exiting region’s range;
works no matter whether the app is running, suspended, or killed (if the app's not running when an enter/exit even comes,
iOS will launch it into the background for a few seconds to handle the event)
*/
Beacons.startMonitoringForRegion(this.region);
/*
Ranging: actions triggered based on proximity to a beacon; works only when the app is running
(e.g., it's displayed on screen, or running in the background in response to a monitoring event, etc.)
*/
Beacons.startRangingBeaconsInRegion(this.region);
Beacons.startUpdatingLocation();
}
Hope this helps someone.
@daominhsangvn
in android i just remove the componentWillUnmount and it will work normally after app killed?
sorry for bad english
@daominhsangvn
in android i just remove the componentWillUnmount and it will work normally after app killed?
sorry for bad english
Not really, you will need to use the RegionBootstrap as well. Check this https://altbeacon.github.io/android-beacon-library/resume-after-terminate.html
@daominhsangvn in android i just remove the componentWillUnmount and it will work normally after app killed? sorry for bad english
Not really, you will need to use the RegionBootstrap as well. Check this https://altbeacon.github.io/android-beacon-library/resume-after-terminate.html
@daominhsangvn how to use RegionBootstrap in react native or in this plugin ? i didnt understand ?
Sorry again
@daominhsangvn i could not find your fork
@daominhsangvn in android i just remove the componentWillUnmount and it will work normally after app killed? sorry for bad english
Not really, you will need to use the RegionBootstrap as well. Check this https://altbeacon.github.io/android-beacon-library/resume-after-terminate.html
@daominhsangvn how to use RegionBootstrap in react native or in this plugin ? i didnt understand ?
Sorry again
You need to use it inside the plugin.
@daominhsangvn i could not find your fork
Here the Github: https://github.com/newoceaninfosys/react-native-beacons-manager Npm: https://www.npmjs.com/package/@nois/react-native-beacons-manager
@daominhsangvn Thank you so much for the fork, I was going through the commits you made, and i come across the REST API ping with the location and notification when the app in a killed state, I was wondering If i can ask you some questions, my discord is @e-nouri, I also have wechat if you prefer, my id is Nnouri
@daominhsangvn I tried your fork on iOS, but it seems to be crashing the app immediately
Also, in your example above, what is this.didDetermineState supposed to be doing?
Also, do your changes to AppDelegate.m have any peer dependencies? I was getting some errors for react native config and NSJsonSerialization (even though I tried installing react-native-config)
@daominhsangvn i could not find your fork
Here the Github: https://github.com/newoceaninfosys/react-native-beacons-manager Npm: https://www.npmjs.com/package/@nois/react-native-beacons-manager
Crashes on app start :'( Why not submit a pull request?
I have use the react-native-beacons-manager library for beacon scan. it working fine in foreground and background. but when I will killed the app that stop to scan beacon.
Please give me solution.
I also ask the question on : https://stackoverflow.com/questions/49787641/app-killed-state-doesnt-scan-beacon-in-react-native