├── .circleci
└── config.yml
├── .eslintignore
├── .eslintrc.js
├── .github
└── dependabot.yml
├── .gitignore
├── .prettierrc
├── LICENSE
├── README.md
├── android
├── build.gradle
└── src
│ └── main
│ ├── AndroidManifest.xml
│ └── java
│ └── com
│ └── ocetnik
│ └── timer
│ ├── BackgroundTimerModule.java
│ └── BackgroundTimerPackage.java
├── index.js
├── ios
├── RNBackgroundTimer.h
├── RNBackgroundTimer.m
└── RNBackgroundTimer.xcodeproj
│ ├── project.pbxproj
│ └── xcuserdata
│ └── jlexyc.xcuserdatad
│ └── xcschemes
│ └── xcschememanagement.plist
├── package-lock.json
├── package.json
├── react-native-background-timer.podspec
└── yarn.lock
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | # Javascript Node CircleCI 2.0 configuration file
2 | #
3 | # Check https://circleci.com/docs/2.0/language-javascript/ for more details
4 | #
5 | version: 2
6 | jobs:
7 | build:
8 | docker:
9 | # specify the version you desire here
10 | - image: circleci/node:current
11 |
12 | # Specify service dependencies here if necessary
13 | # CircleCI maintains a library of pre-built images
14 | # documented at https://circleci.com/docs/2.0/circleci-images/
15 | # - image: circleci/mongo:3.4.4
16 |
17 | working_directory: ~/repo
18 |
19 | steps:
20 | - checkout
21 |
22 | # Download and cache dependencies
23 | - restore_cache:
24 | keys:
25 | - v1-dependencies-{{ checksum "package.json" }}
26 | # fallback to using the latest cache if no exact match is found
27 | - v1-dependencies-
28 |
29 | - run: yarn install
30 |
31 | - save_cache:
32 | paths:
33 | - node_modules
34 | key: v1-dependencies-{{ checksum "package.json" }}
35 |
36 | # run eslint
37 | - run: yarn eslint
38 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: ['airbnb', 'prettier'],
3 | plugins: ['import', 'jsx-a11y', 'prettier', 'react', 'react-hooks'],
4 | rules: {
5 | 'class-methods-use-this': ['error', { exceptMethods: ['start', 'stop'] }],
6 | 'prettier/prettier': ['error'],
7 | },
8 | };
9 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: npm
4 | directory: "/"
5 | schedule:
6 | interval: monthly
7 | time: "04:00"
8 | open-pull-requests-limit: 10
9 | versioning-strategy: increase
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.log
2 | .DS_Store
3 | .idea
4 | node_modules
5 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "trailingComma": "all"
4 | }
5 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Dávid Ocetník
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # React Native Background Timer
2 | Emit event periodically (even when app is in the background).
3 |
4 | ## Installation
5 | 1. If you use Expo to create a project [you'll just need to](https://facebook.github.io/react-native/docs/getting-started#caveats) "[eject](https://docs.expo.io/versions/latest/expokit/eject)".
6 |
7 | ```bash
8 | expo eject
9 | ```
10 |
11 | 2. Install React Native Background Timer package.
12 |
13 | ```bash
14 | yarn add react-native-background-timer
15 | # or using npm
16 | npm install react-native-background-timer --save
17 | ```
18 |
19 | 3. Link React Native Background Timer library. This step is not necessary when you use React Native >= 0.60 (and your app is not ejected from Expo).
20 |
21 | ```bash
22 | react-native link react-native-background-timer
23 | ```
24 |
25 | 4. If you use CocoaPods or React Native >= 0.60 (and your app is not ejected from Expo) or your app is ejected from Expo, then before running your app on iOS, make sure you have CocoaPods installed and run:
26 |
27 | ```bash
28 | cd ios
29 | pod install
30 | ```
31 |
32 | Link the library manually if you get errors:
33 |
34 | - Android: `TypeError: Cannot read property 'setTimeout' of undefined` or `TypeError: null is not an object (evaluating 'RNBackgroundTimer.setTimeout')`
35 | - iOS: `Native module cannot be null`
36 |
37 |
38 | Android manual linking
39 |
40 | - `android/settings.gradle`
41 |
42 | ```diff
43 | + include ':react-native-background-timer'
44 | + project(':react-native-background-timer').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-background-timer/android')
45 | ```
46 |
47 | - `android/app/build.gradle`
48 |
49 | ```diff
50 | dependencies {
51 | + implementation project(':react-native-background-timer')
52 | }
53 | ```
54 |
55 | - `android/app/src/main/java/com/your-app/MainApplication.java`
56 |
57 | ```diff
58 | + import com.ocetnik.timer.BackgroundTimerPackage;
59 |
60 | @Override
61 | protected List getPackages() {
62 | return Arrays.asList(
63 | + new BackgroundTimerPackage()
64 | );
65 | }
66 | ```
67 |
68 |
69 |
70 | iOS manual linking
71 |
72 | - `ios/Podfile`
73 |
74 | ```diff
75 | + pod 'react-native-background-timer', :path => '../node_modules/react-native-background-timer'
76 | ```
77 |
78 |
79 | ## Usage
80 |
81 | ```js
82 | import BackgroundTimer from 'react-native-background-timer';
83 | ```
84 |
85 | ### Crossplatform
86 | To use the same code both on Android and iOS use runBackgroundTimer() and stopBackgroundTimer(). There can be used only one background timer to keep code consistent.
87 |
88 | ```js
89 | BackgroundTimer.runBackgroundTimer(() => {
90 | //code that will be called every 3 seconds
91 | },
92 | 3000);
93 | //rest of code will be performing for iOS on background too
94 |
95 | BackgroundTimer.stopBackgroundTimer(); //after this call all code on background stop run.
96 | ```
97 |
98 | ### iOS
99 | After iOS update logic of background task little bit changed. So we can't use as it was.
100 | You have to use only start() and stop() without parameters. And all code that is performing will continue performing on background including all setTimeout() timers.
101 |
102 | Example:
103 | ```js
104 | BackgroundTimer.start();
105 | // Do whatever you want incuding setTimeout;
106 | BackgroundTimer.stop();
107 | ```
108 |
109 | > If you call stop() on background no new tasks will be started!
110 | > Don't call .start() twice, as it stop performing previous background task and starts new.
111 | > If it will be called on backgound no tasks will run.
112 |
113 | ### Android
114 | You can use the `setInterval` and `setTimeout` functions.
115 | This API is identical to that of `react-native` and can be used to quickly replace existing timers
116 | with background timers.
117 |
118 | ```js
119 | // Start a timer that runs continuous after X milliseconds
120 | const intervalId = BackgroundTimer.setInterval(() => {
121 | // this will be executed every 200 ms
122 | // even when app is the the background
123 | console.log('tic');
124 | }, 200);
125 |
126 | // Cancel the timer when you are done with it
127 | BackgroundTimer.clearInterval(intervalId);
128 | ```
129 |
130 | ```js
131 | // Start a timer that runs once after X milliseconds
132 | const timeoutId = BackgroundTimer.setTimeout(() => {
133 | // this will be executed once after 10 seconds
134 | // even when app is the the background
135 | console.log('tac');
136 | }, 10000);
137 |
138 | // Cancel the timeout if necessary
139 | BackgroundTimer.clearTimeout(timeoutId);
140 | ```
141 |
142 | ### Obsolete
143 | Obsolete usage which doesn't support multiple background timers.
144 |
145 | ```js
146 | import {
147 | DeviceEventEmitter,
148 | NativeAppEventEmitter,
149 | Platform,
150 | } from 'react-native';
151 |
152 | import BackgroundTimer from 'react-native-background-timer';
153 | ```
154 |
155 | ```js
156 | const EventEmitter = Platform.select({
157 | ios: () => NativeAppEventEmitter,
158 | android: () => DeviceEventEmitter,
159 | })();
160 | ```
161 |
162 | ```js
163 | // start a global timer
164 | BackgroundTimer.start(5000); // delay in milliseconds only for Android
165 | ```
166 | ```js
167 | // listen for event
168 | EventEmitter.addListener('backgroundTimer', () => {
169 | // this will be executed once after 5 seconds
170 | console.log('toe');
171 | });
172 | ```
173 | ```js
174 | // stop the timer
175 | BackgroundTimer.stop();
176 | ```
177 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | def safeExtGet(prop, fallback) {
4 | rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
5 | }
6 |
7 | android {
8 | compileSdkVersion safeExtGet('compileSdkVersion', 28)
9 |
10 | defaultConfig {
11 | minSdkVersion safeExtGet('minSdkVersion', 16)
12 | targetSdkVersion safeExtGet('targetSdkVersion', 28)
13 | versionCode 1
14 | versionName "1.0"
15 | }
16 | }
17 |
18 | dependencies {
19 | implementation 'com.facebook.react:react-native:+'
20 | }
21 |
--------------------------------------------------------------------------------
/android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/android/src/main/java/com/ocetnik/timer/BackgroundTimerModule.java:
--------------------------------------------------------------------------------
1 | package com.ocetnik.timer;
2 |
3 | import android.os.Handler;
4 | import android.os.PowerManager;
5 |
6 | import com.facebook.react.bridge.LifecycleEventListener;
7 | import com.facebook.react.bridge.ReactApplicationContext;
8 | import com.facebook.react.bridge.ReactContext;
9 | import com.facebook.react.bridge.ReactContextBaseJavaModule;
10 | import com.facebook.react.bridge.ReactMethod;
11 | import com.facebook.react.modules.core.DeviceEventManagerModule;
12 |
13 | import java.lang.Runnable;
14 |
15 | public class BackgroundTimerModule extends ReactContextBaseJavaModule {
16 |
17 | private Handler handler;
18 | private ReactContext reactContext;
19 | private Runnable runnable;
20 | private PowerManager powerManager;
21 | private PowerManager.WakeLock wakeLock;
22 | private final LifecycleEventListener listener = new LifecycleEventListener(){
23 | @Override
24 | public void onHostResume() {}
25 |
26 | @Override
27 | public void onHostPause() {}
28 |
29 | @Override
30 | public void onHostDestroy() {
31 | if (wakeLock.isHeld()) wakeLock.release();
32 | }
33 | };
34 |
35 | public BackgroundTimerModule(ReactApplicationContext reactContext) {
36 | super(reactContext);
37 | this.reactContext = reactContext;
38 | this.powerManager = (PowerManager) getReactApplicationContext().getSystemService(reactContext.POWER_SERVICE);
39 | this.wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "rohit_bg_wakelock");
40 | reactContext.addLifecycleEventListener(listener);
41 | }
42 |
43 | @Override
44 | public String getName() {
45 | return "RNBackgroundTimer";
46 | }
47 |
48 | @ReactMethod
49 | public void start(final int delay) {
50 | if (!wakeLock.isHeld()) wakeLock.acquire();
51 |
52 | handler = new Handler();
53 | runnable = new Runnable() {
54 | @Override
55 | public void run() {
56 | sendEvent(reactContext, "backgroundTimer");
57 | }
58 | };
59 |
60 | handler.post(runnable);
61 | }
62 |
63 | @ReactMethod
64 | public void stop() {
65 | if (wakeLock.isHeld()) wakeLock.release();
66 |
67 | // avoid null pointer exceptio when stop is called without start
68 | if (handler != null) handler.removeCallbacks(runnable);
69 | }
70 |
71 | private void sendEvent(ReactContext reactContext, String eventName) {
72 | reactContext
73 | .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
74 | .emit(eventName, null);
75 | }
76 |
77 | @ReactMethod
78 | public void setTimeout(final int id, final double timeout) {
79 | Handler handler = new Handler();
80 | handler.postDelayed(new Runnable(){
81 | @Override
82 | public void run(){
83 | if (getReactApplicationContext().hasActiveCatalystInstance()) {
84 | getReactApplicationContext()
85 | .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
86 | .emit("backgroundTimer.timeout", id);
87 | }
88 | }
89 | }, (long) timeout);
90 | }
91 |
92 | /*@ReactMethod
93 | public void clearTimeout(final int id) {
94 | // todo one day..
95 | // not really neccessary to have
96 | }*/
97 | }
98 |
--------------------------------------------------------------------------------
/android/src/main/java/com/ocetnik/timer/BackgroundTimerPackage.java:
--------------------------------------------------------------------------------
1 | package com.ocetnik.timer;
2 |
3 | import com.facebook.react.ReactPackage;
4 | import com.facebook.react.bridge.JavaScriptModule;
5 | import com.facebook.react.bridge.NativeModule;
6 | import com.facebook.react.bridge.ReactApplicationContext;
7 | import com.facebook.react.uimanager.ViewManager;
8 |
9 | import java.util.ArrayList;
10 | import java.util.Collections;
11 | import java.util.List;
12 |
13 | public class BackgroundTimerPackage implements ReactPackage {
14 |
15 | public BackgroundTimerPackage() {
16 | }
17 |
18 | @Override
19 | public List createNativeModules(ReactApplicationContext reactContext) {
20 | List modules = new ArrayList<>();
21 | modules.add(new BackgroundTimerModule(reactContext));
22 |
23 | return modules;
24 | }
25 |
26 | public List> createJSModules() {
27 | return Collections.emptyList();
28 | }
29 |
30 | @Override
31 | public List createViewManagers(ReactApplicationContext reactContext) {
32 | return Collections.emptyList();
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | import {
2 | DeviceEventEmitter,
3 | NativeAppEventEmitter,
4 | NativeEventEmitter,
5 | NativeModules,
6 | Platform,
7 | } from 'react-native';
8 |
9 | const { RNBackgroundTimer } = NativeModules;
10 | const Emitter = new NativeEventEmitter(RNBackgroundTimer);
11 |
12 | class BackgroundTimer {
13 | constructor() {
14 | this.uniqueId = 0;
15 | this.callbacks = {};
16 |
17 | Emitter.addListener('backgroundTimer.timeout', (id) => {
18 | if (this.callbacks[id]) {
19 | const callbackById = this.callbacks[id];
20 | const { callback } = callbackById;
21 | if (!this.callbacks[id].interval) {
22 | delete this.callbacks[id];
23 | } else {
24 | RNBackgroundTimer.setTimeout(id, this.callbacks[id].timeout);
25 | }
26 | callback();
27 | }
28 | });
29 | }
30 |
31 | // Original API
32 | start(delay = 0) {
33 | return RNBackgroundTimer.start(delay);
34 | }
35 |
36 | stop() {
37 | return RNBackgroundTimer.stop();
38 | }
39 |
40 | runBackgroundTimer(callback, delay) {
41 | const EventEmitter = Platform.select({
42 | ios: () => NativeAppEventEmitter,
43 | android: () => DeviceEventEmitter,
44 | })();
45 | this.start(0);
46 | this.backgroundListener = EventEmitter.addListener(
47 | 'backgroundTimer',
48 | () => {
49 | this.backgroundListener.remove();
50 | this.backgroundClockMethod(callback, delay);
51 | },
52 | );
53 | }
54 |
55 | backgroundClockMethod(callback, delay) {
56 | this.backgroundTimer = this.setTimeout(() => {
57 | callback();
58 | this.backgroundClockMethod(callback, delay);
59 | }, delay);
60 | }
61 |
62 | stopBackgroundTimer() {
63 | this.stop();
64 | this.clearTimeout(this.backgroundTimer);
65 | }
66 |
67 | // New API, allowing for multiple timers
68 | setTimeout(callback, timeout) {
69 | this.uniqueId += 1;
70 | const timeoutId = this.uniqueId;
71 | this.callbacks[timeoutId] = {
72 | callback,
73 | interval: false,
74 | timeout,
75 | };
76 | RNBackgroundTimer.setTimeout(timeoutId, timeout);
77 | return timeoutId;
78 | }
79 |
80 | clearTimeout(timeoutId) {
81 | if (this.callbacks[timeoutId]) {
82 | delete this.callbacks[timeoutId];
83 | // RNBackgroundTimer.clearTimeout(timeoutId);
84 | }
85 | }
86 |
87 | setInterval(callback, timeout) {
88 | this.uniqueId += 1;
89 | const intervalId = this.uniqueId;
90 | this.callbacks[intervalId] = {
91 | callback,
92 | interval: true,
93 | timeout,
94 | };
95 | RNBackgroundTimer.setTimeout(intervalId, timeout);
96 | return intervalId;
97 | }
98 |
99 | clearInterval(intervalId) {
100 | if (this.callbacks[intervalId]) {
101 | delete this.callbacks[intervalId];
102 | // RNBackgroundTimer.clearTimeout(intervalId);
103 | }
104 | }
105 | }
106 |
107 | export default new BackgroundTimer();
108 |
--------------------------------------------------------------------------------
/ios/RNBackgroundTimer.h:
--------------------------------------------------------------------------------
1 | //
2 | // RNBackgroundTimer.h
3 | // react-native-background-timer
4 | //
5 | // Created by IjzerenHein on 06-09-2016.
6 | // Copyright (c) ATO Gear. All rights reserved.
7 | //
8 |
9 | #import
10 | // Support React Native headers both in the React namespace, where they are in RN version 0.40+,
11 | // and no namespace, for older versions of React Native
12 | #if __has_include()
13 | #import
14 | #else
15 | #import "RCTEventEmitter.h"
16 | #endif
17 |
18 |
19 | @interface RNBackgroundTimer : RCTEventEmitter
20 |
21 | @end
22 |
--------------------------------------------------------------------------------
/ios/RNBackgroundTimer.m:
--------------------------------------------------------------------------------
1 | //
2 | // RNBackgroundTimer.m
3 | // react-native-background-timer
4 | //
5 | // Created by IjzerenHein on 06-09-2016.
6 | // Copyright (c) ATO Gear. All rights reserved.
7 | //
8 |
9 | @import UIKit;
10 | #import "RNBackgroundTimer.h"
11 |
12 | @implementation RNBackgroundTimer {
13 | UIBackgroundTaskIdentifier bgTask;
14 | int delay;
15 | }
16 |
17 | RCT_EXPORT_MODULE()
18 |
19 | - (NSArray *)supportedEvents { return @[@"backgroundTimer", @"backgroundTimer.timeout"]; }
20 |
21 | - (void) _start
22 | {
23 | [self _stop];
24 | bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithName:@"RNBackgroundTimer" expirationHandler:^{
25 | // Clean up any unfinished task business by marking where you
26 | // stopped or ending the task outright.
27 | [[UIApplication sharedApplication] endBackgroundTask:bgTask];
28 | bgTask = UIBackgroundTaskInvalid;
29 | }];
30 |
31 | UIBackgroundTaskIdentifier thisBgTask = bgTask;
32 | dispatch_async(dispatch_get_main_queue(), ^{
33 | if ([self bridge] != nil && thisBgTask == bgTask) {
34 | [self sendEventWithName:@"backgroundTimer" body:[NSNumber numberWithInt:(int)thisBgTask]];
35 | }
36 | });
37 | }
38 |
39 | - (void) _stop
40 | {
41 | if (bgTask != UIBackgroundTaskInvalid) {
42 | [[UIApplication sharedApplication] endBackgroundTask:bgTask];
43 | bgTask = UIBackgroundTaskInvalid;
44 | }
45 | }
46 |
47 | RCT_EXPORT_METHOD(start:(double)_delay
48 | resolver:(RCTPromiseResolveBlock)resolve
49 | rejecter:(RCTPromiseRejectBlock)reject)
50 | {
51 | delay = _delay;
52 | [self _start];
53 | resolve([NSNumber numberWithBool:YES]);
54 | }
55 |
56 | RCT_EXPORT_METHOD(stop:(RCTPromiseResolveBlock)resolve
57 | rejecter:(RCTPromiseRejectBlock)reject)
58 | {
59 | [self _stop];
60 | resolve([NSNumber numberWithBool:YES]);
61 | }
62 |
63 | RCT_EXPORT_METHOD(setTimeout:(int)timeoutId
64 | timeout:(double)timeout
65 | resolver:(RCTPromiseResolveBlock)resolve
66 | rejecter:(RCTPromiseRejectBlock)reject)
67 | {
68 | __block UIBackgroundTaskIdentifier task = [[UIApplication sharedApplication] beginBackgroundTaskWithName:@"RNBackgroundTimer" expirationHandler:^{
69 | [[UIApplication sharedApplication] endBackgroundTask:task];
70 | }];
71 |
72 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, timeout * NSEC_PER_MSEC), dispatch_get_main_queue(), ^{
73 | if ([self bridge] != nil) {
74 | [self sendEventWithName:@"backgroundTimer.timeout" body:[NSNumber numberWithInt:timeoutId]];
75 | }
76 | [[UIApplication sharedApplication] endBackgroundTask:task];
77 | });
78 | resolve([NSNumber numberWithBool:YES]);
79 | }
80 |
81 | /*
82 | RCT_EXPORT_METHOD(clearTimeout:(int)timeoutId
83 | resolver:(RCTPromiseResolveBlock)resolve
84 | rejecter:(RCTPromiseRejectBlock)reject)
85 | {
86 | // Do nothing :)
87 | // timeout will be ignored in javascript anyway :)
88 | }*/
89 |
90 | @end
91 |
--------------------------------------------------------------------------------
/ios/RNBackgroundTimer.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 6419269B1ECB4266009CF731 /* RNBackgroundTimer.m in Sources */ = {isa = PBXBuildFile; fileRef = B3E7B5891CC2AC0600A0062D /* RNBackgroundTimer.m */; };
11 | B3E7B58A1CC2AC0600A0062D /* RNBackgroundTimer.m in Sources */ = {isa = PBXBuildFile; fileRef = B3E7B5891CC2AC0600A0062D /* RNBackgroundTimer.m */; };
12 | /* End PBXBuildFile section */
13 |
14 | /* Begin PBXCopyFilesBuildPhase section */
15 | 58B511D91A9E6C8500147676 /* CopyFiles */ = {
16 | isa = PBXCopyFilesBuildPhase;
17 | buildActionMask = 2147483647;
18 | dstPath = "include/$(PRODUCT_NAME)";
19 | dstSubfolderSpec = 16;
20 | files = (
21 | );
22 | runOnlyForDeploymentPostprocessing = 0;
23 | };
24 | 641926901ECB4257009CF731 /* CopyFiles */ = {
25 | isa = PBXCopyFilesBuildPhase;
26 | buildActionMask = 2147483647;
27 | dstPath = "include/$(PRODUCT_NAME)";
28 | dstSubfolderSpec = 16;
29 | files = (
30 | );
31 | runOnlyForDeploymentPostprocessing = 0;
32 | };
33 | /* End PBXCopyFilesBuildPhase section */
34 |
35 | /* Begin PBXFileReference section */
36 | 134814201AA4EA6300B7C361 /* libRNBackgroundTimer.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNBackgroundTimer.a; sourceTree = BUILT_PRODUCTS_DIR; };
37 | 641926921ECB4257009CF731 /* libRNBackgroundTimer.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNBackgroundTimer.a; sourceTree = BUILT_PRODUCTS_DIR; };
38 | B3E7B5881CC2AC0600A0062D /* RNBackgroundTimer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNBackgroundTimer.h; sourceTree = ""; };
39 | B3E7B5891CC2AC0600A0062D /* RNBackgroundTimer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNBackgroundTimer.m; sourceTree = ""; };
40 | /* End PBXFileReference section */
41 |
42 | /* Begin PBXFrameworksBuildPhase section */
43 | 58B511D81A9E6C8500147676 /* Frameworks */ = {
44 | isa = PBXFrameworksBuildPhase;
45 | buildActionMask = 2147483647;
46 | files = (
47 | );
48 | runOnlyForDeploymentPostprocessing = 0;
49 | };
50 | 6419268F1ECB4257009CF731 /* Frameworks */ = {
51 | isa = PBXFrameworksBuildPhase;
52 | buildActionMask = 2147483647;
53 | files = (
54 | );
55 | runOnlyForDeploymentPostprocessing = 0;
56 | };
57 | /* End PBXFrameworksBuildPhase section */
58 |
59 | /* Begin PBXGroup section */
60 | 134814211AA4EA7D00B7C361 /* Products */ = {
61 | isa = PBXGroup;
62 | children = (
63 | 134814201AA4EA6300B7C361 /* libRNBackgroundTimer.a */,
64 | );
65 | name = Products;
66 | sourceTree = "";
67 | };
68 | 58B511D21A9E6C8500147676 = {
69 | isa = PBXGroup;
70 | children = (
71 | B3E7B5881CC2AC0600A0062D /* RNBackgroundTimer.h */,
72 | B3E7B5891CC2AC0600A0062D /* RNBackgroundTimer.m */,
73 | 134814211AA4EA7D00B7C361 /* Products */,
74 | 641926921ECB4257009CF731 /* libRNBackgroundTimer.a */,
75 | );
76 | sourceTree = "";
77 | };
78 | /* End PBXGroup section */
79 |
80 | /* Begin PBXNativeTarget section */
81 | 58B511DA1A9E6C8500147676 /* RNBackgroundTimer */ = {
82 | isa = PBXNativeTarget;
83 | buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNBackgroundTimer" */;
84 | buildPhases = (
85 | 58B511D71A9E6C8500147676 /* Sources */,
86 | 58B511D81A9E6C8500147676 /* Frameworks */,
87 | 58B511D91A9E6C8500147676 /* CopyFiles */,
88 | );
89 | buildRules = (
90 | );
91 | dependencies = (
92 | );
93 | name = RNBackgroundTimer;
94 | productName = RCTDataManager;
95 | productReference = 134814201AA4EA6300B7C361 /* libRNBackgroundTimer.a */;
96 | productType = "com.apple.product-type.library.static";
97 | };
98 | 641926911ECB4257009CF731 /* RNBackgroundTimer-tvOS */ = {
99 | isa = PBXNativeTarget;
100 | buildConfigurationList = 6419269A1ECB4257009CF731 /* Build configuration list for PBXNativeTarget "RNBackgroundTimer-tvOS" */;
101 | buildPhases = (
102 | 6419268E1ECB4257009CF731 /* Sources */,
103 | 6419268F1ECB4257009CF731 /* Frameworks */,
104 | 641926901ECB4257009CF731 /* CopyFiles */,
105 | );
106 | buildRules = (
107 | );
108 | dependencies = (
109 | );
110 | name = "RNBackgroundTimer-tvOS";
111 | productName = "RNBackgroundTimer-tvOS";
112 | productReference = 641926921ECB4257009CF731 /* libRNBackgroundTimer.a */;
113 | productType = "com.apple.product-type.library.static";
114 | };
115 | /* End PBXNativeTarget section */
116 |
117 | /* Begin PBXProject section */
118 | 58B511D31A9E6C8500147676 /* Project object */ = {
119 | isa = PBXProject;
120 | attributes = {
121 | LastUpgradeCheck = 0610;
122 | ORGANIZATIONNAME = Facebook;
123 | TargetAttributes = {
124 | 58B511DA1A9E6C8500147676 = {
125 | CreatedOnToolsVersion = 6.1.1;
126 | };
127 | 641926911ECB4257009CF731 = {
128 | CreatedOnToolsVersion = 8.3.2;
129 | ProvisioningStyle = Automatic;
130 | };
131 | };
132 | };
133 | buildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RNBackgroundTimer" */;
134 | compatibilityVersion = "Xcode 3.2";
135 | developmentRegion = English;
136 | hasScannedForEncodings = 0;
137 | knownRegions = (
138 | en,
139 | );
140 | mainGroup = 58B511D21A9E6C8500147676;
141 | productRefGroup = 58B511D21A9E6C8500147676;
142 | projectDirPath = "";
143 | projectRoot = "";
144 | targets = (
145 | 58B511DA1A9E6C8500147676 /* RNBackgroundTimer */,
146 | 641926911ECB4257009CF731 /* RNBackgroundTimer-tvOS */,
147 | );
148 | };
149 | /* End PBXProject section */
150 |
151 | /* Begin PBXSourcesBuildPhase section */
152 | 58B511D71A9E6C8500147676 /* Sources */ = {
153 | isa = PBXSourcesBuildPhase;
154 | buildActionMask = 2147483647;
155 | files = (
156 | B3E7B58A1CC2AC0600A0062D /* RNBackgroundTimer.m in Sources */,
157 | );
158 | runOnlyForDeploymentPostprocessing = 0;
159 | };
160 | 6419268E1ECB4257009CF731 /* Sources */ = {
161 | isa = PBXSourcesBuildPhase;
162 | buildActionMask = 2147483647;
163 | files = (
164 | 6419269B1ECB4266009CF731 /* RNBackgroundTimer.m in Sources */,
165 | );
166 | runOnlyForDeploymentPostprocessing = 0;
167 | };
168 | /* End PBXSourcesBuildPhase section */
169 |
170 | /* Begin XCBuildConfiguration section */
171 | 58B511ED1A9E6C8500147676 /* Debug */ = {
172 | isa = XCBuildConfiguration;
173 | buildSettings = {
174 | ALWAYS_SEARCH_USER_PATHS = NO;
175 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
176 | CLANG_CXX_LIBRARY = "libc++";
177 | CLANG_ENABLE_MODULES = YES;
178 | CLANG_ENABLE_OBJC_ARC = YES;
179 | CLANG_WARN_BOOL_CONVERSION = YES;
180 | CLANG_WARN_CONSTANT_CONVERSION = YES;
181 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
182 | CLANG_WARN_EMPTY_BODY = YES;
183 | CLANG_WARN_ENUM_CONVERSION = YES;
184 | CLANG_WARN_INT_CONVERSION = YES;
185 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
186 | CLANG_WARN_UNREACHABLE_CODE = YES;
187 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
188 | COPY_PHASE_STRIP = NO;
189 | ENABLE_STRICT_OBJC_MSGSEND = YES;
190 | GCC_C_LANGUAGE_STANDARD = gnu99;
191 | GCC_DYNAMIC_NO_PIC = NO;
192 | GCC_OPTIMIZATION_LEVEL = 0;
193 | GCC_PREPROCESSOR_DEFINITIONS = (
194 | "DEBUG=1",
195 | "$(inherited)",
196 | );
197 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
198 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
199 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
200 | GCC_WARN_UNDECLARED_SELECTOR = YES;
201 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
202 | GCC_WARN_UNUSED_FUNCTION = YES;
203 | GCC_WARN_UNUSED_VARIABLE = YES;
204 | IPHONEOS_DEPLOYMENT_TARGET = 7.0;
205 | MTL_ENABLE_DEBUG_INFO = YES;
206 | ONLY_ACTIVE_ARCH = YES;
207 | SDKROOT = iphoneos;
208 | };
209 | name = Debug;
210 | };
211 | 58B511EE1A9E6C8500147676 /* Release */ = {
212 | isa = XCBuildConfiguration;
213 | buildSettings = {
214 | ALWAYS_SEARCH_USER_PATHS = NO;
215 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
216 | CLANG_CXX_LIBRARY = "libc++";
217 | CLANG_ENABLE_MODULES = YES;
218 | CLANG_ENABLE_OBJC_ARC = YES;
219 | CLANG_WARN_BOOL_CONVERSION = YES;
220 | CLANG_WARN_CONSTANT_CONVERSION = YES;
221 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
222 | CLANG_WARN_EMPTY_BODY = YES;
223 | CLANG_WARN_ENUM_CONVERSION = YES;
224 | CLANG_WARN_INT_CONVERSION = YES;
225 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
226 | CLANG_WARN_UNREACHABLE_CODE = YES;
227 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
228 | COPY_PHASE_STRIP = YES;
229 | ENABLE_NS_ASSERTIONS = NO;
230 | ENABLE_STRICT_OBJC_MSGSEND = YES;
231 | GCC_C_LANGUAGE_STANDARD = gnu99;
232 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
233 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
234 | GCC_WARN_UNDECLARED_SELECTOR = YES;
235 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
236 | GCC_WARN_UNUSED_FUNCTION = YES;
237 | GCC_WARN_UNUSED_VARIABLE = YES;
238 | IPHONEOS_DEPLOYMENT_TARGET = 7.0;
239 | MTL_ENABLE_DEBUG_INFO = NO;
240 | SDKROOT = iphoneos;
241 | VALIDATE_PRODUCT = YES;
242 | };
243 | name = Release;
244 | };
245 | 58B511F01A9E6C8500147676 /* Debug */ = {
246 | isa = XCBuildConfiguration;
247 | buildSettings = {
248 | HEADER_SEARCH_PATHS = (
249 | "$(inherited)",
250 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
251 | "$(SRCROOT)/../../../React/**",
252 | "$(SRCROOT)/../../react-native/React/**",
253 | );
254 | LIBRARY_SEARCH_PATHS = "$(inherited)";
255 | OTHER_LDFLAGS = "-ObjC";
256 | PRODUCT_NAME = RNBackgroundTimer;
257 | SKIP_INSTALL = YES;
258 | };
259 | name = Debug;
260 | };
261 | 58B511F11A9E6C8500147676 /* Release */ = {
262 | isa = XCBuildConfiguration;
263 | buildSettings = {
264 | HEADER_SEARCH_PATHS = (
265 | "$(inherited)",
266 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
267 | "$(SRCROOT)/../../../React/**",
268 | "$(SRCROOT)/../../react-native/React/**",
269 | );
270 | LIBRARY_SEARCH_PATHS = "$(inherited)";
271 | OTHER_LDFLAGS = "-ObjC";
272 | PRODUCT_NAME = RNBackgroundTimer;
273 | SKIP_INSTALL = YES;
274 | };
275 | name = Release;
276 | };
277 | 641926981ECB4257009CF731 /* Debug */ = {
278 | isa = XCBuildConfiguration;
279 | buildSettings = {
280 | CLANG_ANALYZER_NONNULL = YES;
281 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
282 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
283 | CLANG_WARN_INFINITE_RECURSION = YES;
284 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
285 | DEBUG_INFORMATION_FORMAT = dwarf;
286 | ENABLE_TESTABILITY = YES;
287 | GCC_NO_COMMON_BLOCKS = YES;
288 | OTHER_LDFLAGS = "-ObjC";
289 | PRODUCT_NAME = RNBackgroundTimer;
290 | SDKROOT = appletvos;
291 | SKIP_INSTALL = YES;
292 | TVOS_DEPLOYMENT_TARGET = 10.2;
293 | };
294 | name = Debug;
295 | };
296 | 641926991ECB4257009CF731 /* Release */ = {
297 | isa = XCBuildConfiguration;
298 | buildSettings = {
299 | CLANG_ANALYZER_NONNULL = YES;
300 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
301 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
302 | CLANG_WARN_INFINITE_RECURSION = YES;
303 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
304 | COPY_PHASE_STRIP = NO;
305 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
306 | GCC_NO_COMMON_BLOCKS = YES;
307 | OTHER_LDFLAGS = "-ObjC";
308 | PRODUCT_NAME = RNBackgroundTimer;
309 | SDKROOT = appletvos;
310 | SKIP_INSTALL = YES;
311 | TVOS_DEPLOYMENT_TARGET = 10.2;
312 | };
313 | name = Release;
314 | };
315 | /* End XCBuildConfiguration section */
316 |
317 | /* Begin XCConfigurationList section */
318 | 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RNBackgroundTimer" */ = {
319 | isa = XCConfigurationList;
320 | buildConfigurations = (
321 | 58B511ED1A9E6C8500147676 /* Debug */,
322 | 58B511EE1A9E6C8500147676 /* Release */,
323 | );
324 | defaultConfigurationIsVisible = 0;
325 | defaultConfigurationName = Release;
326 | };
327 | 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNBackgroundTimer" */ = {
328 | isa = XCConfigurationList;
329 | buildConfigurations = (
330 | 58B511F01A9E6C8500147676 /* Debug */,
331 | 58B511F11A9E6C8500147676 /* Release */,
332 | );
333 | defaultConfigurationIsVisible = 0;
334 | defaultConfigurationName = Release;
335 | };
336 | 6419269A1ECB4257009CF731 /* Build configuration list for PBXNativeTarget "RNBackgroundTimer-tvOS" */ = {
337 | isa = XCConfigurationList;
338 | buildConfigurations = (
339 | 641926981ECB4257009CF731 /* Debug */,
340 | 641926991ECB4257009CF731 /* Release */,
341 | );
342 | defaultConfigurationIsVisible = 0;
343 | };
344 | /* End XCConfigurationList section */
345 | };
346 | rootObject = 58B511D31A9E6C8500147676 /* Project object */;
347 | }
348 |
--------------------------------------------------------------------------------
/ios/RNBackgroundTimer.xcodeproj/xcuserdata/jlexyc.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | RNBackgroundTimer-tvOS.xcscheme
8 |
9 | orderHint
10 | 42
11 |
12 | RNBackgroundTimer.xcscheme
13 |
14 | orderHint
15 | 41
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-background-timer",
3 | "version": "2.4.1",
4 | "description": "Emit event periodically (even when app is in the background)",
5 | "keywords": [
6 | "react-native",
7 | "background",
8 | "timer",
9 | "android",
10 | "ios"
11 | ],
12 | "main": "index.js",
13 | "scripts": {
14 | "eslint": "eslint *.js",
15 | "eslint:fix": "yarn eslint --fix",
16 | "test": "echo \"Error: no test specified\" && exit 1"
17 | },
18 | "repository": {
19 | "type": "git",
20 | "url": "https://github.com/ocetnik/react-native-background-timer.git"
21 | },
22 | "author": "David Ocetnik",
23 | "license": "MIT",
24 | "peerDependencies": {
25 | "react-native": ">=0.47.0"
26 | },
27 | "devDependencies": {
28 | "@babel/core": "^7.21.3",
29 | "eslint": "^8.36.0",
30 | "eslint-config-airbnb": "^19.0.4",
31 | "eslint-config-prettier": "^8.6.0",
32 | "eslint-plugin-import": "^2.27.5",
33 | "eslint-plugin-jsx-a11y": "^6.7.1",
34 | "eslint-plugin-prettier": "^4.2.1",
35 | "eslint-plugin-react": "^7.32.2",
36 | "eslint-plugin-react-hooks": "^4.6.0",
37 | "husky": "^8.0.3",
38 | "lint-staged": "^13.1.2",
39 | "prettier": "^2.8.4",
40 | "react": "17.0.2",
41 | "react-native": "^0.68.6"
42 | },
43 | "husky": {
44 | "hooks": {
45 | "pre-commit": "lint-staged"
46 | }
47 | },
48 | "lint-staged": {
49 | "*.js": [
50 | "eslint --fix",
51 | "git add"
52 | ]
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/react-native-background-timer.podspec:
--------------------------------------------------------------------------------
1 | require 'json'
2 |
3 | package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
4 |
5 | Pod::Spec.new do |s|
6 |
7 | s.name = package['name']
8 | s.version = package['version']
9 | s.summary = package['description']
10 | s.homepage = package['repository']['url']
11 | s.license = package['license']
12 | s.author = package['author']
13 | s.source = { :git => s.homepage, :tag => 'v#{s.version}' }
14 |
15 | s.requires_arc = true
16 | s.ios.deployment_target = '8.0'
17 | s.tvos.deployment_target = '9.0'
18 |
19 | s.preserve_paths = 'README.md', 'package.json', 'index.js'
20 | s.source_files = 'ios/*.{h,m}'
21 |
22 | s.dependency 'React-Core'
23 |
24 | end
25 |
--------------------------------------------------------------------------------