From e764eed60728c079c063e40162d1d4d7ae779ccc Mon Sep 17 00:00:00 2001 From: woffu <54139773+woffu@users.noreply.github.com> Date: Thu, 15 Aug 2019 06:34:55 -0500 Subject: [PATCH 01/14] Updated package.json --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 5f3b574..adc5dfe 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { - "name": "react-native-boundary", - "version": "1.1.1", + "name": "react-native-boundary-woffu", + "version": "1.0.0", "description": "native geofencing and region monitoring", "main": "index.js", "scripts": { @@ -8,7 +8,7 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/eddieowens/react-native-boundary.git" + "url": "git+https://github.com/woffu/react-native-boundary.git" }, "typings": "typings/index.d.ts", "keywords": [ @@ -20,7 +20,7 @@ "location", "region monitoring" ], - "author": "Edward Owens", + "author": "Woffu -> Forked from Edward Owens", "license": "Apache-2.0", "peerDependencies": { "react-native": ">0.49.0" From 480be45f601db49b3e9b6609cc642e70dc0b88fb Mon Sep 17 00:00:00 2001 From: woffu <54139773+woffu@users.noreply.github.com> Date: Thu, 15 Aug 2019 06:36:57 -0500 Subject: [PATCH 02/14] Fixed RNBoundary --- ios/RNBoundary.podspec | 44 +++++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/ios/RNBoundary.podspec b/ios/RNBoundary.podspec index 3587945..056e951 100644 --- a/ios/RNBoundary.podspec +++ b/ios/RNBoundary.podspec @@ -1,24 +1,20 @@ - -Pod::Spec.new do |s| - s.name = "RNBoundary" - s.version = "1.0.0" - s.summary = "RNBoundary" - s.description = <<-DESC - RNBoundary - DESC - s.homepage = "" - s.license = "MIT" - # s.license = { :type => "MIT", :file => "FILE_LICENSE" } - s.author = { "author" => "author@domain.cn" } - s.platform = :ios, "7.0" - s.source = { :git => "https://github.com/author/RNBoundary.git", :tag => "master" } - s.source_files = "RNBoundary/**/*.{h,m}" - s.requires_arc = true - - - s.dependency "React" - #s.dependency "others" - -end - - \ No newline at end of file +require 'json' + +package = JSON.parse(File.read(File.join(__dir__, '../package.json'))) + +Pod::Spec.new do |s| + s.name = "RNBoundary" + s.version = package['version'] + s.summary = package['description'] + s.license = package['license'] + + s.authors = package['author'] + s.homepage = "https://github.com/eddieowens/react-native-boundary#readme" + s.platform = :ios, "9.0" + + s.source = { :git => "https://github.com/eddieowens/react-native-boundary.git", :tag => "#{s.version}" } + s.source_files = "*.{h,m}" + s.requires_arc = true + + s.dependency 'React' +end From 0a9bb97e7ce299d681027a74b603d89d2ac45629 Mon Sep 17 00:00:00 2001 From: woffu <54139773+woffu@users.noreply.github.com> Date: Thu, 15 Aug 2019 06:38:14 -0500 Subject: [PATCH 03/14] Updated podspec to new repo forked --- ios/RNBoundary.podspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ios/RNBoundary.podspec b/ios/RNBoundary.podspec index 056e951..e62db64 100644 --- a/ios/RNBoundary.podspec +++ b/ios/RNBoundary.podspec @@ -9,10 +9,10 @@ Pod::Spec.new do |s| s.license = package['license'] s.authors = package['author'] - s.homepage = "https://github.com/eddieowens/react-native-boundary#readme" + s.homepage = "https://github.com/woffu/react-native-boundary#readme" s.platform = :ios, "9.0" - s.source = { :git => "https://github.com/eddieowens/react-native-boundary.git", :tag => "#{s.version}" } + s.source = { :git => "https://github.com/woffu/react-native-boundary.git", :tag => "#{s.version}" } s.source_files = "*.{h,m}" s.requires_arc = true From 543926f4c09c661455de546e6dbafb94ab44e166 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=20Gim=C3=A9nez?= Date: Fri, 16 Aug 2019 03:18:38 -0500 Subject: [PATCH 04/14] Fix breaking app trying to startservice in background. --- .../BoundaryEventHeadlessTaskService.java | 36 ++++++++++++++++- .../BoundaryEventJobIntentService.java | 39 ++++++++++++++++-- package-lock.json | 40 +++++++++++++++++++ package.json | 2 +- 4 files changed, 110 insertions(+), 7 deletions(-) create mode 100644 package-lock.json diff --git a/android/src/main/java/com/eddieowens/services/BoundaryEventHeadlessTaskService.java b/android/src/main/java/com/eddieowens/services/BoundaryEventHeadlessTaskService.java index 99ffa98..9e54770 100644 --- a/android/src/main/java/com/eddieowens/services/BoundaryEventHeadlessTaskService.java +++ b/android/src/main/java/com/eddieowens/services/BoundaryEventHeadlessTaskService.java @@ -1,12 +1,20 @@ package com.eddieowens.services; +import android.app.Notification; +import android.app.NotificationManager; +import android.content.Context; import android.content.Intent; +import android.os.Build; import android.os.Bundle; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; +import androidx.core.app.NotificationCompat; +import androidx.core.content.ContextCompat; + +import com.eddieowens.R; import com.facebook.react.HeadlessJsTaskService; -import com.facebook.react.jstasks.HeadlessJsTaskConfig; import com.facebook.react.bridge.Arguments; +import com.facebook.react.jstasks.HeadlessJsTaskConfig; public class BoundaryEventHeadlessTaskService extends HeadlessJsTaskService { @Nullable @@ -18,4 +26,28 @@ protected HeadlessJsTaskConfig getTaskConfig(Intent intent) { 5000, true); } + + @Override + public void onCreate() { + super.onCreate(); + + if (Build.VERSION.SDK_INT >= 26) { + String NOTIFICATION_CHANNEL_ID = "com.woffu.app.WOFFU_CHANNEL"; + String GROUP_KEY = "com.woffu.app.WOFFU_GROUP"; + + Context context = this.getApplicationContext(); + + // Notification for the foreground service + NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID) + .setSmallIcon(R.drawable.common_google_signin_btn_icon_light_normal) + .setPriority(NotificationManager.IMPORTANCE_LOW) + .setContentTitle("Woffu Geofencing Service") + .setContentText("Woffu is not spying you, or constantly tracking your location. This is a geofence, to know when you get closer to the work location.") + .setOngoing(true) + .setColor(ContextCompat.getColor(context, R.color.accent_material_light)) + .setGroup(GROUP_KEY); + Notification notification = builder.build(); + startForeground(9999999, notification); + } + } } diff --git a/android/src/main/java/com/eddieowens/services/BoundaryEventJobIntentService.java b/android/src/main/java/com/eddieowens/services/BoundaryEventJobIntentService.java index 3997859..d6ab530 100644 --- a/android/src/main/java/com/eddieowens/services/BoundaryEventJobIntentService.java +++ b/android/src/main/java/com/eddieowens/services/BoundaryEventJobIntentService.java @@ -1,12 +1,15 @@ package com.eddieowens.services; +import android.app.ActivityManager; import android.content.Context; import android.content.Intent; +import android.os.Build; import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.v4.app.JobIntentService; import android.util.Log; +import androidx.annotation.NonNull; +import androidx.core.app.JobIntentService; + import com.eddieowens.RNBoundaryModule; import com.eddieowens.errors.GeofenceErrorMessages; import com.facebook.react.HeadlessJsTaskService; @@ -14,6 +17,7 @@ import com.google.android.gms.location.GeofencingEvent; import java.util.ArrayList; +import java.util.List; import static com.eddieowens.RNBoundaryModule.TAG; @@ -68,7 +72,34 @@ private void sendEvent(Context context, String event, ArrayList params) Intent headlessBoundaryIntent = new Intent(context, BoundaryEventHeadlessTaskService.class); headlessBoundaryIntent.putExtras(bundle); - context.startService(headlessBoundaryIntent); - HeadlessJsTaskService.acquireWakeLockNow(context); + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O || isAppOnForeground(context)) { + context.startService(headlessBoundaryIntent); + HeadlessJsTaskService.acquireWakeLockNow(context); + } + else { + // Since Oreo (8.0) and up they have restricted starting background services, and it will crash the app + // But we can create a foreground service and bring an notification to the front + // http://stackoverflow.com/questions/8489993/check-android-application-is-in-foreground-or-not + context.startForegroundService(headlessBoundaryIntent); + //HeadlessJsTaskService.acquireWakeLockNow(context); + } + } + + private boolean isAppOnForeground(Context context) { + ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); + List appProcesses = + activityManager.getRunningAppProcesses(); + if (appProcesses == null) { + return false; + } + final String packageName = context.getPackageName(); + for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) { + if (appProcess.importance == + ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND && + appProcess.processName.equals(packageName)) { + return true; + } + } + return false; } } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..450736e --- /dev/null +++ b/package-lock.json @@ -0,0 +1,40 @@ +{ + "name": "react-native-boundary-woffu", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@types/prop-types": { + "version": "15.7.1", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.1.tgz", + "integrity": "sha512-CFzn9idOEpHrgdw8JsoTkaDDyRWk1jrzIV8djzcgpq0y9tG4B4lFT+Nxh52DVpDXV+n4+NPNv7M1Dj5uMp6XFg==", + "dev": true + }, + "@types/react": { + "version": "16.9.1", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.1.tgz", + "integrity": "sha512-jGM2x8F7m7/r+81N/BOaUKVwbC5Cdw6ExlWEUpr77XPwVeNvAppnPEnMMLMfxRDYL8FPEX8MHjwtD2NQMJ0yyQ==", + "dev": true, + "requires": { + "@types/prop-types": "*", + "csstype": "^2.2.0" + } + }, + "@types/react-native": { + "version": "0.57.65", + "resolved": "https://registry.npmjs.org/@types/react-native/-/react-native-0.57.65.tgz", + "integrity": "sha512-7P5ulTb+/cnwbABWaAjzKmSYkRWeK7UCTfUwHhDpnwxdiL2X/KbdN1sPgo0B2E4zxfYE3MEoHv7FhB8Acfvf8A==", + "dev": true, + "requires": { + "@types/prop-types": "*", + "@types/react": "*" + } + }, + "csstype": { + "version": "2.6.6", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.6.tgz", + "integrity": "sha512-RpFbQGUE74iyPgvr46U9t1xoQBM8T4BL8SxrN66Le2xYAPSaDJJKeztV3awugusb3g3G9iL8StmkBBXhcbbXhg==", + "dev": true + } + } +} diff --git a/package.json b/package.json index adc5dfe..28a1450 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-boundary-woffu", - "version": "1.0.0", + "version": "1.1.0", "description": "native geofencing and region monitoring", "main": "index.js", "scripts": { From 5ecb0892002dc3b9d8db33bf8b87d20b57064fed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=20Gim=C3=A9nez?= Date: Fri, 16 Aug 2019 03:23:21 -0500 Subject: [PATCH 05/14] Added permission to start foreground service --- android/src/main/AndroidManifest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml index 2cf2922..9897398 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -3,6 +3,7 @@ + From 6d2725c07e0b0a68f788e419e2f27a7a7e522f9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=20Gim=C3=A9nez?= Date: Fri, 16 Aug 2019 04:05:26 -0500 Subject: [PATCH 06/14] Cleaned up code and improved notification channel handling --- .../BoundaryEventHeadlessTaskService.java | 51 ++++++++++++------- .../BoundaryEventJobIntentService.java | 1 - package.json | 2 +- 3 files changed, 34 insertions(+), 20 deletions(-) diff --git a/android/src/main/java/com/eddieowens/services/BoundaryEventHeadlessTaskService.java b/android/src/main/java/com/eddieowens/services/BoundaryEventHeadlessTaskService.java index 9e54770..a2e8c71 100644 --- a/android/src/main/java/com/eddieowens/services/BoundaryEventHeadlessTaskService.java +++ b/android/src/main/java/com/eddieowens/services/BoundaryEventHeadlessTaskService.java @@ -1,6 +1,7 @@ package com.eddieowens.services; import android.app.Notification; +import android.app.NotificationChannel; import android.app.NotificationManager; import android.content.Context; import android.content.Intent; @@ -17,6 +18,8 @@ import com.facebook.react.jstasks.HeadlessJsTaskConfig; public class BoundaryEventHeadlessTaskService extends HeadlessJsTaskService { + public static final String NOTIFICATION_CHANNEL_ID = "GEOFENCE_SERVICE_CHANNEL"; + @Nullable protected HeadlessJsTaskConfig getTaskConfig(Intent intent) { Bundle extras = intent.getExtras(); @@ -31,23 +34,35 @@ protected HeadlessJsTaskConfig getTaskConfig(Intent intent) { public void onCreate() { super.onCreate(); - if (Build.VERSION.SDK_INT >= 26) { - String NOTIFICATION_CHANNEL_ID = "com.woffu.app.WOFFU_CHANNEL"; - String GROUP_KEY = "com.woffu.app.WOFFU_GROUP"; - - Context context = this.getApplicationContext(); - - // Notification for the foreground service - NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID) - .setSmallIcon(R.drawable.common_google_signin_btn_icon_light_normal) - .setPriority(NotificationManager.IMPORTANCE_LOW) - .setContentTitle("Woffu Geofencing Service") - .setContentText("Woffu is not spying you, or constantly tracking your location. This is a geofence, to know when you get closer to the work location.") - .setOngoing(true) - .setColor(ContextCompat.getColor(context, R.color.accent_material_light)) - .setGroup(GROUP_KEY); - Notification notification = builder.build(); - startForeground(9999999, notification); + Context context = this.getApplicationContext(); + + // Channel for the foreground service notification + createChannel(context); + + // Notification for the foreground service + NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID) + .setSmallIcon(R.drawable.common_google_signin_btn_icon_light_normal) + .setContentTitle("Geofence Service") + .setContentText("We detected that you're close to your work location.") + .setOngoing(true) + .setColor(ContextCompat.getColor(context, R.color.accent_material_light)); + Notification notification = builder.build(); + startForeground(999999999, notification); + } + + private void createChannel(Context context) { + String NOTIFICATION_CHANNEL_NAME = "Geofence Service"; + String NOTIFICATION_CHANNEL_DESCRIPTION = "Only used to know when you're close to the work location."; + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + NotificationChannel channel = new NotificationChannel( + NOTIFICATION_CHANNEL_ID, + NOTIFICATION_CHANNEL_NAME, + NotificationManager.IMPORTANCE_LOW); + channel.setDescription(NOTIFICATION_CHANNEL_DESCRIPTION); + + NotificationManager notificationManager = context.getSystemService(NotificationManager.class); + notificationManager.createNotificationChannel(channel); } } -} +} \ No newline at end of file diff --git a/android/src/main/java/com/eddieowens/services/BoundaryEventJobIntentService.java b/android/src/main/java/com/eddieowens/services/BoundaryEventJobIntentService.java index d6ab530..4454417 100644 --- a/android/src/main/java/com/eddieowens/services/BoundaryEventJobIntentService.java +++ b/android/src/main/java/com/eddieowens/services/BoundaryEventJobIntentService.java @@ -81,7 +81,6 @@ private void sendEvent(Context context, String event, ArrayList params) // But we can create a foreground service and bring an notification to the front // http://stackoverflow.com/questions/8489993/check-android-application-is-in-foreground-or-not context.startForegroundService(headlessBoundaryIntent); - //HeadlessJsTaskService.acquireWakeLockNow(context); } } diff --git a/package.json b/package.json index 28a1450..87ad2ff 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-boundary-woffu", - "version": "1.1.0", + "version": "1.1.1", "description": "native geofencing and region monitoring", "main": "index.js", "scripts": { From 34acf6ea13cf78146b9db704c47bfa2398558ad1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=20Gim=C3=A9nez?= Date: Sat, 17 Aug 2019 02:26:40 -0500 Subject: [PATCH 07/14] Start geofenceservice onStartCommand --- .../BoundaryEventHeadlessTaskService.java | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/android/src/main/java/com/eddieowens/services/BoundaryEventHeadlessTaskService.java b/android/src/main/java/com/eddieowens/services/BoundaryEventHeadlessTaskService.java index a2e8c71..2938e98 100644 --- a/android/src/main/java/com/eddieowens/services/BoundaryEventHeadlessTaskService.java +++ b/android/src/main/java/com/eddieowens/services/BoundaryEventHeadlessTaskService.java @@ -18,7 +18,7 @@ import com.facebook.react.jstasks.HeadlessJsTaskConfig; public class BoundaryEventHeadlessTaskService extends HeadlessJsTaskService { - public static final String NOTIFICATION_CHANNEL_ID = "GEOFENCE_SERVICE_CHANNEL"; + public static final String NOTIFICATION_CHANNEL_ID = "com.eddieowens.GEOFENCE_SERVICE_CHANNEL"; @Nullable protected HeadlessJsTaskConfig getTaskConfig(Intent intent) { @@ -34,6 +34,19 @@ protected HeadlessJsTaskConfig getTaskConfig(Intent intent) { public void onCreate() { super.onCreate(); + startForegroundServiceNotification(); + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + int result = super.onStartCommand(intent, flags, startId); + + startForegroundServiceNotification(); + + return result; + } + + private void startForegroundServiceNotification() { Context context = this.getApplicationContext(); // Channel for the foreground service notification @@ -47,12 +60,12 @@ public void onCreate() { .setOngoing(true) .setColor(ContextCompat.getColor(context, R.color.accent_material_light)); Notification notification = builder.build(); - startForeground(999999999, notification); + startForeground(9999999, notification); } private void createChannel(Context context) { String NOTIFICATION_CHANNEL_NAME = "Geofence Service"; - String NOTIFICATION_CHANNEL_DESCRIPTION = "Only used to know when you're close to the work location."; + String NOTIFICATION_CHANNEL_DESCRIPTION = "Only used to know when you're close to a configured location."; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationChannel channel = new NotificationChannel( From a418bc84edc47fcb40eefd4e6686b1f73a50b84d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=20Gim=C3=A9nez?= Date: Sat, 17 Aug 2019 02:27:14 -0500 Subject: [PATCH 08/14] Increased version to 1.1.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 87ad2ff..4496b85 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-boundary-woffu", - "version": "1.1.1", + "version": "1.1.2", "description": "native geofencing and region monitoring", "main": "index.js", "scripts": { From 3dc9d147c3e4c9efd2eb2f79fbc45762ae2efac8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=20Gim=C3=A9nez?= Date: Sat, 17 Aug 2019 02:29:21 -0500 Subject: [PATCH 09/14] Updated description --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4496b85..37b89a0 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "react-native-boundary-woffu", "version": "1.1.2", - "description": "native geofencing and region monitoring", + "description": "native geofencing and region monitoring, works with React Native >= 0.60 and both iOS and Android including latest versions (8, 9, 10+).", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" From 67569b0b5bdd77e45ebd2b12b06917a7fe3b7387 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=20Gim=C3=A9nez?= Date: Sat, 17 Aug 2019 02:56:52 -0500 Subject: [PATCH 10/14] Updated service description --- .../services/BoundaryEventHeadlessTaskService.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/android/src/main/java/com/eddieowens/services/BoundaryEventHeadlessTaskService.java b/android/src/main/java/com/eddieowens/services/BoundaryEventHeadlessTaskService.java index 2938e98..85016ee 100644 --- a/android/src/main/java/com/eddieowens/services/BoundaryEventHeadlessTaskService.java +++ b/android/src/main/java/com/eddieowens/services/BoundaryEventHeadlessTaskService.java @@ -56,11 +56,12 @@ private void startForegroundServiceNotification() { NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID) .setSmallIcon(R.drawable.common_google_signin_btn_icon_light_normal) .setContentTitle("Geofence Service") - .setContentText("We detected that you're close to your work location.") + .setContentText("You're close to the configured location.") .setOngoing(true) .setColor(ContextCompat.getColor(context, R.color.accent_material_light)); Notification notification = builder.build(); - startForeground(9999999, notification); + startForeground(999999999, notification); + HeadlessJsTaskService.acquireWakeLockNow(context); } private void createChannel(Context context) { From 534c51d13048d9245f86b5a6d749316b88020a84 Mon Sep 17 00:00:00 2001 From: Julien Atanasyan Date: Sun, 26 Apr 2020 15:03:46 +0100 Subject: [PATCH 11/14] Added fix for iOS killed app --- ios/RNBoundary.h | 11 +++++++- ios/RNBoundary.m | 69 +++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 75 insertions(+), 5 deletions(-) diff --git a/ios/RNBoundary.h b/ios/RNBoundary.h index 12b5e82..cbba3d3 100644 --- a/ios/RNBoundary.h +++ b/ios/RNBoundary.h @@ -12,5 +12,14 @@ - (bool) removeBoundary:(NSString *)boundaryId; - (void) removeAllBoundaries; @property (strong, nonatomic) CLLocationManager *locationManager; +@property (strong, nonatomic) NSMutableSet *queuedEvents; +@property (assign, nonatomic) bool hasListeners; +@end + + +@interface GeofenceEvent : NSObject +- (id) initWithId:(NSString*)geofenceId forEvent:(NSString *)eventName; +@property (strong, nonatomic) NSString *geofenceId; +@property (strong, nonatomic) NSString *name; +@property (strong, nonatomic) NSDate* date; @end - diff --git a/ios/RNBoundary.m b/ios/RNBoundary.m index 4e10084..3abb040 100644 --- a/ios/RNBoundary.m +++ b/ios/RNBoundary.m @@ -1,6 +1,29 @@ - #import "RNBoundary.h" +@implementation GeofenceEvent +- (id)initWithId:(NSString*)geofenceId forEvent:(NSString *)name { + self = [super init]; + if (self) { + self.geofenceId = geofenceId; + self.name = name; + self.date = [NSDate date]; + } + + return self; +} + +- (BOOL)isEqual:(id)anObject +{ + return [self.geofenceId isEqual:((GeofenceEvent *)anObject).geofenceId]; +} + +- (NSUInteger)hash +{ + return self.geofenceId; +} +@end + + @implementation RNBoundary RCT_EXPORT_MODULE() @@ -11,6 +34,8 @@ -(instancetype)init if (self) { self.locationManager = [[CLLocationManager alloc] init]; self.locationManager.delegate = self; + + self.queuedEvents = [[NSMutableSet alloc] init]; } return self; @@ -62,6 +87,7 @@ - (void) removeAllBoundaries for(CLRegion *region in [self.locationManager monitoredRegions]) { [self.locationManager stopMonitoringForRegion:region]; } + [self.queuedEvents removeAllObjects]; } - (bool) removeBoundary:(NSString *)boundaryId @@ -83,13 +109,49 @@ - (bool) removeBoundary:(NSString *)boundaryId - (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region { NSLog(@"didEnter : %@", region); - [self sendEventWithName:@"onEnter" body:region.identifier]; + if (self.hasListeners) { + [self sendEventWithName:@"onEnter" body:region.identifier]; + } else { + GeofenceEvent *event = [[GeofenceEvent alloc] initWithId:region.identifier forEvent:@"onEnter" ]; + [self.queuedEvents addObject:event]; + } } - (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region { NSLog(@"didExit : %@", region); - [self sendEventWithName:@"onExit" body:region.identifier]; + if (self.hasListeners) { + [self sendEventWithName:@"onExit" body:region.identifier]; + } else { + GeofenceEvent *event = [[GeofenceEvent alloc] initWithId:region.identifier forEvent:@"onExit" ]; + [self.queuedEvents addObject:event]; + } +} + +- (void)startObserving { + self.hasListeners = YES; + if ([self.queuedEvents count] > 0) { + for(GeofenceEvent *event in self.queuedEvents) { + NSTimeInterval interval = [[NSDate date] timeIntervalSinceDate:[event date]]; + double minutesDiff = interval / 60.f; + // if the app was not open + // within 2 minutes of storing the event + // we discard it + if (minutesDiff < 2) { + // dispatch after 1 second + // as both events are not registered at the same time + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ + [self sendEventWithName:[event name] body:[event geofenceId]]; + }); + } + } + [self.queuedEvents removeAllObjects]; + } +} + +- (void)stopObserving { + self.hasListeners = NO; + [self.queuedEvents removeAllObjects]; } + (BOOL)requiresMainQueueSetup @@ -98,4 +160,3 @@ + (BOOL)requiresMainQueueSetup } @end - From b595172d21d763b290ba0aa4b1208f27df778aaa Mon Sep 17 00:00:00 2001 From: Julien Atanasyan Date: Sat, 9 May 2020 16:18:40 +0100 Subject: [PATCH 12/14] updated author package.json --- ios/RNBoundary.podspec | 4 ++-- package.json | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ios/RNBoundary.podspec b/ios/RNBoundary.podspec index e62db64..056e951 100644 --- a/ios/RNBoundary.podspec +++ b/ios/RNBoundary.podspec @@ -9,10 +9,10 @@ Pod::Spec.new do |s| s.license = package['license'] s.authors = package['author'] - s.homepage = "https://github.com/woffu/react-native-boundary#readme" + s.homepage = "https://github.com/eddieowens/react-native-boundary#readme" s.platform = :ios, "9.0" - s.source = { :git => "https://github.com/woffu/react-native-boundary.git", :tag => "#{s.version}" } + s.source = { :git => "https://github.com/eddieowens/react-native-boundary.git", :tag => "#{s.version}" } s.source_files = "*.{h,m}" s.requires_arc = true diff --git a/package.json b/package.json index 37b89a0..a88928e 100644 --- a/package.json +++ b/package.json @@ -1,14 +1,14 @@ { - "name": "react-native-boundary-woffu", - "version": "1.1.2", - "description": "native geofencing and region monitoring, works with React Native >= 0.60 and both iOS and Android including latest versions (8, 9, 10+).", + "name": "react-native-boundary", + "version": "1.2.0", + "description": "native geofencing and region monitoring", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "repository": { "type": "git", - "url": "git+https://github.com/woffu/react-native-boundary.git" + "url": "git+https://github.com/eddieowens/react-native-boundary.git" }, "typings": "typings/index.d.ts", "keywords": [ @@ -20,7 +20,7 @@ "location", "region monitoring" ], - "author": "Woffu -> Forked from Edward Owens", + "author": "Edward Owens", "license": "Apache-2.0", "peerDependencies": { "react-native": ">0.49.0" From 0968d573d2b4ff8da2baba4d17becb81cda2f144 Mon Sep 17 00:00:00 2001 From: Julien Atanasyan Date: Sun, 10 May 2020 16:35:36 +0100 Subject: [PATCH 13/14] added options to set title, text and icon --- .../BoundaryEventHeadlessTaskService.java | 72 ++++++++++++++----- 1 file changed, 56 insertions(+), 16 deletions(-) diff --git a/android/src/main/java/com/eddieowens/services/BoundaryEventHeadlessTaskService.java b/android/src/main/java/com/eddieowens/services/BoundaryEventHeadlessTaskService.java index 85016ee..ccab89a 100644 --- a/android/src/main/java/com/eddieowens/services/BoundaryEventHeadlessTaskService.java +++ b/android/src/main/java/com/eddieowens/services/BoundaryEventHeadlessTaskService.java @@ -5,8 +5,11 @@ import android.app.NotificationManager; import android.content.Context; import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; import android.os.Build; import android.os.Bundle; +import android.util.Log; import androidx.annotation.Nullable; import androidx.core.app.NotificationCompat; @@ -17,32 +20,71 @@ import com.facebook.react.bridge.Arguments; import com.facebook.react.jstasks.HeadlessJsTaskConfig; +import java.util.Map; +import java.util.Random; + +import static com.eddieowens.RNBoundaryModule.TAG; + public class BoundaryEventHeadlessTaskService extends HeadlessJsTaskService { public static final String NOTIFICATION_CHANNEL_ID = "com.eddieowens.GEOFENCE_SERVICE_CHANNEL"; + private static final String KEY_NOTIFICATION_TITLE = "rnboundary.notification_title"; + private static final String KEY_NOTIFICATION_TEXT = "rnboundary.notification_text"; + private static final String KEY_NOTIFICATION_ICON = "rnboundary.notification_icon"; @Nullable protected HeadlessJsTaskConfig getTaskConfig(Intent intent) { Bundle extras = intent.getExtras(); return new HeadlessJsTaskConfig( - "OnBoundaryEvent", - extras != null ? Arguments.fromBundle(extras) : null, - 5000, - true); + "OnBoundaryEvent", + extras != null ? Arguments.fromBundle(extras) : null, + 5000, + true); + } + + public NotificationCompat.Builder getNotificationBuilder() { + Context context = getApplicationContext(); + String title = "Geofencing in progress"; + String text = "You're close to the configured location"; + int iconResource = -1; + + try { + ApplicationInfo ai = context.getPackageManager().getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA); + Bundle bundle = ai.metaData; + title = bundle.getString(KEY_NOTIFICATION_TITLE, title); + text = bundle.getString(KEY_NOTIFICATION_TEXT, text); + iconResource = bundle.getInt(KEY_NOTIFICATION_ICON, -1); + } catch (Exception e) { + Log.e(TAG, "Cannot get application Bundle " + e.toString()); + } + + + // Notification for the foreground service + NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID) + .setContentTitle(title) + .setContentText(text) + .setOngoing(true) + .setColor(ContextCompat.getColor(context, R.color.accent_material_light)); + + if (iconResource > -1) { + builder.setSmallIcon(iconResource); + } + + Log.i(TAG, "LAUNCH: " + title + " " + text + " " + iconResource); + + + return builder; } @Override public void onCreate() { super.onCreate(); - startForegroundServiceNotification(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { int result = super.onStartCommand(intent, flags, startId); - startForegroundServiceNotification(); - return result; } @@ -52,15 +94,13 @@ private void startForegroundServiceNotification() { // Channel for the foreground service notification createChannel(context); - // Notification for the foreground service - NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID) - .setSmallIcon(R.drawable.common_google_signin_btn_icon_light_normal) - .setContentTitle("Geofence Service") - .setContentText("You're close to the configured location.") - .setOngoing(true) - .setColor(ContextCompat.getColor(context, R.color.accent_material_light)); + NotificationCompat.Builder builder = getNotificationBuilder(); Notification notification = builder.build(); - startForeground(999999999, notification); + + Random rand = new Random(); + int notificationId = rand.nextInt(100000); + + startForeground(notificationId, notification); HeadlessJsTaskService.acquireWakeLockNow(context); } @@ -79,4 +119,4 @@ private void createChannel(Context context) { notificationManager.createNotificationChannel(channel); } } -} \ No newline at end of file +} From fb60986c49551dbf774acd75f9e4f9312ee3f0a8 Mon Sep 17 00:00:00 2001 From: Julien Atanasyan Date: Sun, 10 May 2020 17:19:55 +0100 Subject: [PATCH 14/14] removed logs --- .../eddieowens/services/BoundaryEventHeadlessTaskService.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/android/src/main/java/com/eddieowens/services/BoundaryEventHeadlessTaskService.java b/android/src/main/java/com/eddieowens/services/BoundaryEventHeadlessTaskService.java index ccab89a..41faa64 100644 --- a/android/src/main/java/com/eddieowens/services/BoundaryEventHeadlessTaskService.java +++ b/android/src/main/java/com/eddieowens/services/BoundaryEventHeadlessTaskService.java @@ -69,9 +69,6 @@ public NotificationCompat.Builder getNotificationBuilder() { builder.setSmallIcon(iconResource); } - Log.i(TAG, "LAUNCH: " + title + " " + text + " " + iconResource); - - return builder; }