From 86222d60244c748bc58710f57ae70553b017ecf1 Mon Sep 17 00:00:00 2001 From: spurdow Date: Thu, 28 Oct 2021 00:55:04 +0800 Subject: [PATCH] Added configurable background mode --- android/build.gradle | 4 +- .../beaconsandroid/BeaconsAndroidModule.java | 288 ++++++++++++------ .../beaconsandroid/NotificationHelper.java | 55 ++++ .../notif/NotificationData.java | 102 +++++++ lib/next/module.types.js | 21 ++ lib/next/new.module.android.js | 37 +++ typings/react-native-beacons-manager.d.ts | 26 ++ 7 files changed, 439 insertions(+), 94 deletions(-) create mode 100644 android/src/main/java/com/mackentoch/beaconsandroid/NotificationHelper.java create mode 100644 android/src/main/java/com/mackentoch/beaconsandroid/notif/NotificationData.java diff --git a/android/build.gradle b/android/build.gradle index d2567825..fbd7602e 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -21,7 +21,7 @@ android { buildToolsVersion project.hasProperty('buildToolsVersion') ? project.buildToolsVersion : DEFAULT_BUILD_TOOLS_VERSION defaultConfig { - minSdkVersion 16 + minSdkVersion 21 targetSdkVersion project.hasProperty('targetSdkVersion') ? project.targetSdkVersion : DEFAULT_TARGET_SDK_VERSION versionCode 1 versionName "1.0" @@ -105,5 +105,5 @@ dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.facebook.react:react-native:0.6+' implementation 'com.intellij:annotations:+@jar' - compile 'org.altbeacon:android-beacon-library:2.16.1' + implementation 'org.altbeacon:android-beacon-library:2.19.3' } diff --git a/android/src/main/java/com/mackentoch/beaconsandroid/BeaconsAndroidModule.java b/android/src/main/java/com/mackentoch/beaconsandroid/BeaconsAndroidModule.java index ffe8173a..f66bdbef 100644 --- a/android/src/main/java/com/mackentoch/beaconsandroid/BeaconsAndroidModule.java +++ b/android/src/main/java/com/mackentoch/beaconsandroid/BeaconsAndroidModule.java @@ -1,23 +1,34 @@ package com.mackentoch.beaconsandroid; +import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.app.TaskStackBuilder; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; +import android.os.Build; import android.os.RemoteException; import org.jetbrains.annotations.Nullable; import android.util.Log; +import androidx.annotation.RequiresApi; +import androidx.core.app.NotificationCompat; + import com.facebook.react.bridge.Callback; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.WritableArray; import com.facebook.react.bridge.WritableMap; import com.facebook.react.bridge.WritableNativeArray; import com.facebook.react.bridge.WritableNativeMap; import com.facebook.react.modules.core.DeviceEventManagerModule; +import com.mackentoch.beaconsandroid.notif.NotificationData; import org.altbeacon.beacon.Beacon; import org.altbeacon.beacon.BeaconConsumer; @@ -34,14 +45,18 @@ import java.util.Collection; import java.util.HashMap; import java.util.Map; +import java.util.Objects; -public class BeaconsAndroidModule extends ReactContextBaseJavaModule implements BeaconConsumer { +public class BeaconsAndroidModule extends ReactContextBaseJavaModule implements MonitorNotifier, RangeNotifier { private static final String LOG_TAG = "BeaconsAndroidModule"; private static final int RUNNING_AVG_RSSI_FILTER = 0; private static final int ARMA_RSSI_FILTER = 1; + private static final String TAG = BeaconsAndroidModule.class.getSimpleName(); private BeaconManager mBeaconManager; private Context mApplicationContext; private ReactApplicationContext mReactContext; + private boolean isDebug = false; + private NotificationData notifData = null; public BeaconsAndroidModule(ReactApplicationContext reactContext) { super(reactContext); @@ -49,13 +64,32 @@ public BeaconsAndroidModule(ReactApplicationContext reactContext) { this.mReactContext = reactContext; } + @RequiresApi(api = Build.VERSION_CODES.KITKAT) @Override public void initialize() { this.mApplicationContext = this.mReactContext.getApplicationContext(); + this.mBeaconManager = BeaconManager.getInstanceForApplication(mApplicationContext); // need to bind at instantiation so that service loads (to test more) - mBeaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout("m:0-3=4c000215,i:4-19,i:20-21,i:22-23,p:24-24")); - bindManager(); + // mBeaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout("m:0-3=4c000215,i:4-19,i:20-21,i:22-23,p:24-24")); + mBeaconManager.getBeaconParsers().clear(); + + // If we were monitoring *different* regions on the last run of this app, they will be + // remembered. In this case we need to disable them here + for (Region region: this.mBeaconManager.getMonitoredRegions()) { + this.mBeaconManager.stopMonitoring(region); + this.mBeaconManager.stopRangingBeacons(region); + } + + this.mBeaconManager.removeAllMonitorNotifiers(); + this.mBeaconManager.removeAllRangeNotifiers(); + + Log.d(TAG, "setting up background monitoring in app onCreate"); + this.mBeaconManager.addMonitorNotifier(this); + this.mBeaconManager.addRangeNotifier(this); + + + } @Override @@ -81,17 +115,88 @@ public void setHardwareEqualityEnforced(Boolean e) { Beacon.setHardwareEqualityEnforced(e.booleanValue()); } - public void bindManager() { - if (!mBeaconManager.isBound(this)) { - Log.d(LOG_TAG, "BeaconsAndroidModule - bindManager: "); - mBeaconManager.bind(this); + private Notification generateNotification(String extraMessage){ + NotificationManager notificationManager = + (NotificationManager) this.mApplicationContext.getSystemService(Context.NOTIFICATION_SERVICE); + NotificationCompat.Builder builder; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + NotificationChannel channel = new NotificationChannel(notifData.getChannelId(), + "Beacon Service", NotificationManager.IMPORTANCE_HIGH); + channel.enableLights(false); + channel.enableVibration(false); + channel.setLockscreenVisibility(notifData.getVisibility()); + notificationManager.createNotificationChannel(channel); + builder = new NotificationCompat.Builder(this.mApplicationContext, channel.getId()); + } + else { + builder = new NotificationCompat.Builder(this.mApplicationContext); + builder.setPriority(Notification.PRIORITY_HIGH); + } + + TaskStackBuilder stackBuilder = TaskStackBuilder.create(this.mApplicationContext); + Class cls = mReactContext.hasCurrentActivity() ? Objects.requireNonNull(mReactContext.getCurrentActivity()).getClass() : Objects.requireNonNull(mReactContext.getApplicationContext()).getClass(); + stackBuilder.addNextIntent(new Intent(this.mApplicationContext, cls)); + PendingIntent resultPendingIntent = + stackBuilder.getPendingIntent( + 0, + PendingIntent.FLAG_UPDATE_CURRENT + ); + builder.setSmallIcon(notifData.getDrawableIcon()); + builder.setContentTitle(notifData.getContentTitle()); + if(!extraMessage.isEmpty()){ + String fullText = notifData.getContentMessage() + " " + extraMessage; + builder.setContentText(fullText); + builder.setStyle(new NotificationCompat.BigTextStyle() + .bigText(fullText)); + } + else{ + builder.setContentText(notifData.getContentMessage()); + } + + builder.setContentIntent(resultPendingIntent); + builder.setShowWhen(notifData.isShowWhen()); + + return builder.build(); + } + + @ReactMethod + public void startForegroundService(ReadableMap readableMap, Callback resolve, Callback reject){ + try { + notifData = new NotificationData(this.mApplicationContext, readableMap); + + + mBeaconManager.enableForegroundServiceScanning(generateNotification(""), notifData.getNotificationId()); + mBeaconManager.setEnableScheduledScanJobs(false); + mBeaconManager.setBackgroundBetweenScanPeriod(0); + mBeaconManager.setBackgroundScanPeriod(1100); + + resolve.invoke(notifData.getNotificationId()); + }catch(Exception e){ + Log.d(TAG, "Notif Exception " + e); + reject.invoke(e.getMessage()); } } - public void unbindManager() { - if (mBeaconManager.isBound(this)) { - Log.d(LOG_TAG, "BeaconsAndroidModule - unbindManager: "); - mBeaconManager.unbind(this); + @ReactMethod + public void stopForegroundService(Callback resolve, Callback reject){ + try{ + if(mBeaconManager.isAnyConsumerBound()){ + for (Region region: mBeaconManager.getMonitoredRegions()) { + mBeaconManager.stopMonitoring(region); + mBeaconManager.stopRangingBeacons(region); + + } + mBeaconManager.removeAllRangeNotifiers(); + mBeaconManager.removeAllMonitorNotifiers(); + } + mBeaconManager.disableForegroundServiceScanning(); + mBeaconManager.setEnableScheduledScanJobs(true); + mBeaconManager.setBackgroundBetweenScanPeriod(mBeaconManager.getForegroundBetweenScanPeriod()); + mBeaconManager.setBackgroundScanPeriod(mBeaconManager.getBackgroundScanPeriod()); + notifData = null; + resolve.invoke(!mBeaconManager.isAnyConsumerBound()); + }catch(Exception e){ + reject.invoke(e.getMessage()); } } @@ -99,9 +204,7 @@ public void unbindManager() { public void addParser(String parser, Callback resolve, Callback reject) { try { Log.d(LOG_TAG, "BeaconsAndroidModule - addParser: " + parser); - unbindManager(); mBeaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout(parser)); - bindManager(); resolve.invoke(); } catch (Exception e) { reject.invoke(e.getMessage()); @@ -112,9 +215,7 @@ public void addParser(String parser, Callback resolve, Callback reject) { public void removeParser(String parser, Callback resolve, Callback reject) { try { Log.d(LOG_TAG, "BeaconsAndroidModule - removeParser: " + parser); - unbindManager(); mBeaconManager.getBeaconParsers().remove(new BeaconParser().setBeaconLayout(parser)); - bindManager(); resolve.invoke(); } catch (Exception e) { reject.invoke(e.getMessage()); @@ -124,13 +225,11 @@ public void removeParser(String parser, Callback resolve, Callback reject) { @ReactMethod public void addParsersListToDetection(ReadableArray parsers, Callback resolve, Callback reject) { try { - unbindManager(); for (int i = 0; i < parsers.size(); i++) { String parser = parsers.getString(i); Log.d(LOG_TAG, "addParsersListToDetection - add parser: " + parser); mBeaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout(parser)); } - bindManager(); resolve.invoke(parsers); } catch (Exception e) { reject.invoke(e.getMessage()); @@ -140,19 +239,34 @@ public void addParsersListToDetection(ReadableArray parsers, Callback resolve, C @ReactMethod public void removeParsersListToDetection(ReadableArray parsers, Callback resolve, Callback reject) { try { - unbindManager(); for (int i = 0; i < parsers.size(); i++) { String parser = parsers.getString(i); Log.d(LOG_TAG, "removeParsersListToDetection - remove parser: " + parser); mBeaconManager.getBeaconParsers().remove(new BeaconParser().setBeaconLayout(parser)); } - bindManager(); resolve.invoke(parsers); } catch (Exception e) { reject.invoke(e.getMessage()); } } + @ReactMethod + public void setDebug(boolean debug){ + this.isDebug = debug; + BeaconManager.setDebug(debug); + } + + + @ReactMethod + public void setEnableScheduledScanJobs(boolean enableScheduledScanJobs){ + mBeaconManager.setEnableScheduledScanJobs(enableScheduledScanJobs); + } + + @ReactMethod + public void setBackgroundMode(boolean newMode) { + mBeaconManager.setBackgroundMode(newMode); + } + @ReactMethod public void setBackgroundScanPeriod(int period) { mBeaconManager.setBackgroundScanPeriod((long) period); @@ -226,36 +340,6 @@ public void getRangedRegions(Callback callback) { callback.invoke(array); } - /*********************************************************************************************** - * BeaconConsumer - **********************************************************************************************/ - @Override - public void onBeaconServiceConnect() { - Log.v(LOG_TAG, "onBeaconServiceConnect"); - - // deprecated since v2.9 (see github: https://github.com/AltBeacon/android-beacon-library/releases/tag/2.9) - // mBeaconManager.setMonitorNotifier(mMonitorNotifier); - // mBeaconManager.setRangeNotifier(mRangeNotifier); - mBeaconManager.addMonitorNotifier(mMonitorNotifier); - mBeaconManager.addRangeNotifier(mRangeNotifier); - sendEvent(mReactContext, "beaconServiceConnected", null); - } - - @Override - public Context getApplicationContext() { - return mApplicationContext; - } - - @Override - public void unbindService(ServiceConnection serviceConnection) { - mApplicationContext.unbindService(serviceConnection); - } - - @Override - public boolean bindService(Intent intent, ServiceConnection serviceConnection, int i) { - return mApplicationContext.bindService(intent, serviceConnection, i); - } - /*********************************************************************************************** * Monitoring **********************************************************************************************/ @@ -269,7 +353,7 @@ public void startMonitoring(String regionId, String beaconUuid, int minor, int m String.valueOf(minor).equals("-1") ? "" : String.valueOf(minor), String.valueOf(major).equals("-1") ? "" : String.valueOf(major) ); - mBeaconManager.startMonitoringBeaconsInRegion(region); + mBeaconManager.startMonitoring(region); resolve.invoke(); } catch (Exception e) { Log.e(LOG_TAG, "startMonitoring, error: ", e); @@ -277,36 +361,6 @@ public void startMonitoring(String regionId, String beaconUuid, int minor, int m } } - private MonitorNotifier mMonitorNotifier = new MonitorNotifier() { - @Override - public void didEnterRegion(Region region) { - sendEvent(mReactContext, "regionDidEnter", createMonitoringResponse(region)); - } - - @Override - public void didExitRegion(Region region) { - sendEvent(mReactContext, "regionDidExit", createMonitoringResponse(region)); - } - - @Override - public void didDetermineStateForRegion(int i, Region region) { - String state = "unknown"; - switch (i) { - case MonitorNotifier.INSIDE: - state = "inside"; - break; - case MonitorNotifier.OUTSIDE: - state = "outside"; - break; - default: - break; - } - WritableMap map = createMonitoringResponse(region); - map.putString("state", state); - sendEvent(mReactContext, "didDetermineState", map); - } - }; - private WritableMap createMonitoringResponse(Region region) { WritableMap map = new WritableNativeMap(); map.putString("identifier", region.getUniqueId()); @@ -328,7 +382,7 @@ public void stopMonitoring(String regionId, String beaconUuid, int minor, int ma ); try { - mBeaconManager.stopMonitoringBeaconsInRegion(region); + mBeaconManager.stopMonitoring(region); resolve.invoke(); } catch (Exception e) { Log.e(LOG_TAG, "stopMonitoring, error: ", e); @@ -344,7 +398,7 @@ public void startRanging(String regionId, String beaconUuid, Callback resolve, C Log.d(LOG_TAG, "startRanging, rangingRegionId: " + regionId + ", rangingBeaconUuid: " + beaconUuid); try { Region region = createRegion(regionId, beaconUuid); - mBeaconManager.startRangingBeaconsInRegion(region); + mBeaconManager.startRangingBeacons(region); resolve.invoke(); } catch (Exception e) { Log.e(LOG_TAG, "startRanging, error: ", e); @@ -352,15 +406,6 @@ public void startRanging(String regionId, String beaconUuid, Callback resolve, C } } - private RangeNotifier mRangeNotifier = new RangeNotifier() { - @Override - public void didRangeBeaconsInRegion(Collection beacons, Region region) { - Log.d(LOG_TAG, "rangingConsumer didRangeBeaconsInRegion, beacons: " + beacons.toString()); - Log.d(LOG_TAG, "rangingConsumer didRangeBeaconsInRegion, region: " + region.toString()); - sendEvent(mReactContext, "beaconsDidRange", createRangingResponse(beacons, region)); - } - }; - private WritableMap createRangingResponse(Collection beacons, Region region) { WritableMap map = new WritableNativeMap(); map.putString("identifier", region.getUniqueId()); @@ -406,7 +451,7 @@ private String getProximity(double distance) { public void stopRanging(String regionId, String beaconUuid, Callback resolve, Callback reject) { Region region = createRegion(regionId, beaconUuid); try { - mBeaconManager.stopRangingBeaconsInRegion(region); + mBeaconManager.stopRangingBeacons(region); resolve.invoke(); } catch (Exception e) { Log.e(LOG_TAG, "stopRanging, error: ", e); @@ -451,4 +496,63 @@ private Region createRegion(String regionId, String beaconUuid, String minor, St minor.length() > 0 ? Identifier.parse(minor) : null ); } + + /*********************************************************************************************** + * Monitor Notifier + **********************************************************************************************/ + @Override + public void didEnterRegion(Region region) { + sendEvent(mReactContext, "regionDidEnter", createMonitoringResponse(region)); + } + + @Override + public void didExitRegion(Region region) { + sendEvent(mReactContext, "regionDidExit", createMonitoringResponse(region)); + } + + /*********************************************************************************************** + * Determine State Monitor Notifier + **********************************************************************************************/ + @Override + public void didDetermineStateForRegion(int i, Region region) { + String state = "unknown"; + switch (i) { + case MonitorNotifier.INSIDE: + state = "inside"; + break; + case MonitorNotifier.OUTSIDE: + state = "outside"; + break; + default: + break; + } + WritableMap map = createMonitoringResponse(region); + map.putString("state", state); + sendEvent(mReactContext, "didDetermineState", map); + } + + /*********************************************************************************************** + * Range Notifier + **********************************************************************************************/ + @Override + public void didRangeBeaconsInRegion(Collection beacons, Region region) { + Log.d(LOG_TAG, "rangingConsumer didRangeBeaconsInRegion, beacons: " + beacons.toString()); + Log.d(LOG_TAG, "rangingConsumer didRangeBeaconsInRegion, region: " + region.toString()); + sendEvent(mReactContext, "beaconsDidRange", createRangingResponse(beacons, region)); + StringBuilder stringBuilder = new StringBuilder(); + int count = 0; + if(isDebug){ + NotificationManager notificationManager = + (NotificationManager) this.mReactContext.getSystemService(Context.NOTIFICATION_SERVICE); + for(Beacon beacon : beacons){ + if (beacon.getIdentifiers().size() > 2) { + stringBuilder.append("\nmajor:").append(beacon.getId2().toInt()); + stringBuilder.append(",minor:").append(beacon.getId3().toInt()); + count++; + } + } + notificationManager.notify(notifData.getNotificationId(), generateNotification("\nFound " + ((count > 0) ? count : beacons.size()) + " beacon/s" + stringBuilder.toString())); + } + + } } diff --git a/android/src/main/java/com/mackentoch/beaconsandroid/NotificationHelper.java b/android/src/main/java/com/mackentoch/beaconsandroid/NotificationHelper.java new file mode 100644 index 00000000..f2dbed23 --- /dev/null +++ b/android/src/main/java/com/mackentoch/beaconsandroid/NotificationHelper.java @@ -0,0 +1,55 @@ +package com.mackentoch.beaconsandroid; + +import android.content.Context; + +import androidx.annotation.DrawableRes; +import androidx.core.app.NotificationCompat; + +public final class NotificationHelper { + + public static final int DEFAULT_NOTIFICATION_ID = 99999; + public static final String DEFAULT_CHANNEL_ID = "Beacon-Notification"; + public static final int DEFAULT_NOTIF_PRIORITY = NotificationCompat.PRIORITY_DEFAULT; + public static final int DEFAULT_VISIBILITY = NotificationCompat.VISIBILITY_PUBLIC; + + + public static int getResourceIdForResourceName(Context context, String resourceName) { + int resourceId = context.getResources().getIdentifier(resourceName, "drawable", context.getPackageName()); + if (resourceId == 0) { + resourceId = context.getResources().getIdentifier(resourceName, "mipmap", context.getPackageName()); + } + return resourceId; + } + + public static int getPriority(String priorityString) { + if (priorityString != null) { + switch(priorityString.toLowerCase()) { + case "max": + return NotificationCompat.PRIORITY_MAX; + case "low": + return NotificationCompat.PRIORITY_LOW; + case "min": + return NotificationCompat.PRIORITY_MIN; + case "default": + return NotificationCompat.PRIORITY_DEFAULT; + default: + return NotificationCompat.PRIORITY_HIGH; + } + } + return NotificationCompat.PRIORITY_HIGH; + } + + public static int getVisibility(String visibilityString){ + if (visibilityString != null) { + switch(visibilityString.toLowerCase()) { + case "private": + return NotificationCompat.VISIBILITY_PRIVATE; + case "secret": + return NotificationCompat.VISIBILITY_SECRET; + default: + return NotificationCompat.VISIBILITY_PUBLIC; + } + } + return NotificationCompat.VISIBILITY_PUBLIC; + } +} diff --git a/android/src/main/java/com/mackentoch/beaconsandroid/notif/NotificationData.java b/android/src/main/java/com/mackentoch/beaconsandroid/notif/NotificationData.java new file mode 100644 index 00000000..0987ab10 --- /dev/null +++ b/android/src/main/java/com/mackentoch/beaconsandroid/notif/NotificationData.java @@ -0,0 +1,102 @@ +package com.mackentoch.beaconsandroid.notif; + +import android.app.Notification; +import android.content.Context; + +import androidx.annotation.DrawableRes; + +import com.facebook.react.bridge.ReadableMap; +import com.mackentoch.beaconsandroid.NotificationHelper; + +public class NotificationData { + + private String channelId; + private int notificationId; + + private String contentTitle; + private String contentMessage; + private @DrawableRes + int drawableIcon; + private boolean showWhen; + private int priority ; + private int visibility; + + private Context mContext; + + public NotificationData(Context mContext, ReadableMap mMap) throws IllegalArgumentException { + this.mContext = mContext; + + if (!mMap.hasKey("channelId") || + !mMap.hasKey("notificationId") || + !mMap.hasKey("contentTitle") || + !mMap.hasKey("contentMessage") || + !mMap.hasKey("drawableIcon") || + !mMap.hasKey("showWhen") + ){ + throw new IllegalArgumentException("Missing required arguments from readable map.."); + } + channelId = mMap.getString("channelId"); + notificationId = mMap.getInt("notificationId"); + contentTitle = mMap.getString("contentTitle"); + contentMessage = mMap.getString("contentMessage"); + drawableIcon = NotificationHelper.getResourceIdForResourceName(mContext, mMap.getString("drawableIcon")); + showWhen = mMap.getBoolean("showWhen"); + if(mMap.hasKey("priority")){ + priority = NotificationHelper.getPriority(mMap.getString("priority")); + }else{ + priority = NotificationHelper.DEFAULT_NOTIF_PRIORITY; + } + + if(mMap.hasKey("visibility")){ + visibility = NotificationHelper.getVisibility(mMap.getString("visibility")); + }else{ + visibility = NotificationHelper.DEFAULT_VISIBILITY; + } + } + + public String getChannelId() { + return channelId; + } + + public int getNotificationId() { + return notificationId; + } + + public String getContentTitle() { + return contentTitle; + } + + public String getContentMessage() { + return contentMessage; + } + + public int getDrawableIcon() { + return drawableIcon; + } + + public boolean isShowWhen() { + return showWhen; + } + + public int getPriority() { + return priority; + } + + public int getVisibility() { + return visibility; + } + + @Override + public String toString() { + return "NotificationData{" + + "channelId='" + channelId + '\'' + + ", notificationId=" + notificationId + + ", contentTitle='" + contentTitle + '\'' + + ", contentMessage='" + contentMessage + '\'' + + ", drawableIcon=" + drawableIcon + + ", showWhen=" + showWhen + + ", priority=" + priority + + ", visibility=" + visibility + + '}'; + } +} diff --git a/lib/next/module.types.js b/lib/next/module.types.js index 81799022..9c2a682e 100644 --- a/lib/next/module.types.js +++ b/lib/next/module.types.js @@ -49,6 +49,17 @@ export const transmissionSupport: Array = [ export type Parser = string | number; +export type NotificationData = { + channelId: string, + notificationId: number, + contentTitle: string, + contentMessage: string, + drawableIcon: string, + showWhen: boolean, + priority?: string, + visibility?: string, +}; + export type BeaconsManagerIOS = { // specific to iOS: requestAlwaysAuthorization: () => void, @@ -72,6 +83,10 @@ export type BeaconsManagerANDROID = { // specific to android: setHardwareEqualityEnforced: (flag: boolean) => void, + + startForegroundService: ( notifData: NotificationData, resolve: () => any, reject: () => any) => void, + stopForegroundService: (resolve: () => any, reject: () => any) => void, + addParser: (parser: Parser, resolve: () => any, reject: () => any) => void, addParsersListToDetection: ( parsers: Array, @@ -117,6 +132,12 @@ export type BeaconsManagerANDROID = { addCustomBeaconLayoutDetection: () => Promise, removeCustomBeaconLayoutDetection: () => Promise, + + + + setDebug: (debug: boolean) => void, + setEnableScheduledScanJobs: (enableScanJobs: boolean) => void, + setBackgroundMode: (newMode: boolean) => void, setBackgroundScanPeriod: (period: number) => void, setBackgroundBetweenScanPeriod: (period: number) => void, setForegroundScanPeriod: (period: number) => void, diff --git a/lib/next/new.module.android.js b/lib/next/new.module.android.js index 24e39854..0684c541 100644 --- a/lib/next/new.module.android.js +++ b/lib/next/new.module.android.js @@ -28,10 +28,29 @@ const ARMA_RSSI_FILTER = BeaconsManager && BeaconsManager.ARMA_RSSI_FILTER || un const RUNNING_AVG_RSSI_FILTER = BeaconsManager && BeaconsManager.RUNNING_AVG_RSSI_FILTER || undefined; // #endregion +/** + * Configures whether a the bluetoothAddress (mac address) must be the same for two Beacons + * to be configured equal. This setting applies to all beacon instances in the same process. + * Defaults to false for backward compatibility. + * @param {boolean} flag + */ function setHardwareEqualityEnforced(flag: boolean): void { BeaconsManager.setHardwareEqualityEnforced(flag); } + +function startForegroundService(notifData: NotificationData) { + return new Promise((resolve, reject) => { + BeaconsManager.startForegroundService(notifData, resolve, reject); + }); +} + +function stopForegroundService(){ + return new Promise((resolve, reject) => { + BeaconsManager.stopForegroundService(resolve, reject); + }); +} + // #region iBeacon /** * set beacon layout for iBeacon @@ -232,6 +251,18 @@ function removeParsersListToDetection(parsers: Array) { } // #endregion +function setDebug(debug: boolean): void { + BeaconsManager.setDebug(debug); +} + +function setEnableScheduledScanJobs(enableScanJobs: boolean): void { + BeaconsManager.setEnableScheduledScanJobs(enableScanJobs); +} + +function setBackgroundMode(newMode: boolean): void { + BeaconsManager.setBackgroundMode(newMode); +} + function setBackgroundScanPeriod(period: number): void { BeaconsManager.setBackgroundScanPeriod(period); } @@ -399,6 +430,9 @@ module.exports = { BeaconsEventEmitter, setHardwareEqualityEnforced, + // Android only + startForegroundService, + stopForegroundService, // iBeacons: detectIBeacons, addIBeaconsDetection, @@ -431,6 +465,9 @@ module.exports = { addParsersListToDetection, removeParsersListToDetection, + setDebug, + setEnableScheduledScanJobs, + setBackgroundMode, setBackgroundScanPeriod, setBackgroundBetweenScanPeriod, setForegroundScanPeriod, diff --git a/typings/react-native-beacons-manager.d.ts b/typings/react-native-beacons-manager.d.ts index 2a0d91c2..117a1d2f 100644 --- a/typings/react-native-beacons-manager.d.ts +++ b/typings/react-native-beacons-manager.d.ts @@ -7,6 +7,17 @@ declare module 'react-native-beacons-manager' { major?: number } + export interface NotificationData { + channelId: string, + notificationId: number, + contentTitle: string, + contentMessage: string, + drawableIcon: string, + showWhen: boolean, + priority?: string, + visibility?: string, + } + export type AuthorizationStatus = | 'authorizedAlways' | 'authorizedWhenInUse' @@ -55,6 +66,9 @@ declare module 'react-native-beacons-manager' { flag: boolean ): void; + startForegroundService(notifData: NotificationData): Promise; + stopForegroundService(): Promise; + detectIBeacons(): void; detectAltBeacons(): void; @@ -71,6 +85,18 @@ declare module 'react-native-beacons-manager' { parser: number ): void; + setDebug( + debug: boolean + ): void; + + setEnableScheduledScanJobs( + enableScanJobs: boolean + ): void; + + setBackgroundMode( + newMode: boolean + ): void; + setBackgroundScanPeriod( period: number ): void;