Rapsssito / react-native-background-actions

React Native background service library for running background tasks forever in Android & iOS.
MIT License
796 stars 116 forks source link

BackgroundService.start is create multiple task #121

Open shinnachot opened 2 years ago

shinnachot commented 2 years ago

I using this code when i want to start some task BackgroundService.start(this.taskRandom, options); When i kill app or logout i use this code to stop task BackgroundService.stop(); It's work fine but...when i try to start task again BackgroundService.start(this.taskRandom, options); it'll do a multiple task job Example start task 1 13:05PM stop start task 1 13:10PM start task 1 13:15PM <<< it will double do job like this forever

Here is my code

class Home extends Component {

    playing = BackgroundService.isRunning();

    trackBackground = async () => {
        this.playing = !this.playing;
        if (this.playing) {
            try {
                console.log('Trying to start background service');
                await BackgroundService.start(this.taskRandom, options);
                console.log('Successful start!');
            } catch (e) {
                console.log('Error', e);
            }
        } else {
            console.log('Stop background service');
            await BackgroundService.stop();
        }
    };

    taskRandom = async (taskData) => {
        if (Platform.OS === 'ios') {
            console.warn(
                'This task will not keep your app alive in the background by itself, use other library like react-native-track-player that use audio,',
                'geolocalization, etc. to keep your app alive in the background while you excute the JS from this library.'
            );
        }
        await new Promise(async (resolve) => {
            // For loop with a delay
            const { delay } = taskData;
            for (let i = 0; BackgroundService.isRunning(); i++) {
                console.log('Send data');

                await BackgroundService.updateNotification({ taskDesc: 'Tracking...' + i });
                await sleep(delay);
            }
        });
    };

    componentWillUnmount() {
        BackgroundService.stop();
    }

    componentDidMount() {
        this.trackBackground();
    }
}
Rapsssito commented 2 years ago

@shinnachot, I am not sure, but you may need to resolve your promise:

await new Promise(async (resolve) => {
            // For loop with a delay
            const { delay } = taskData;
            for (let i = 0; BackgroundService.isRunning(); i++) {
                console.log('Send data');

                await BackgroundService.updateNotification({ taskDesc: 'Tracking...' + i });
                await sleep(delay);
            }
            resolve();
        });
fabiros commented 2 years ago

+1 In my case the action start is called after a successful login. The action runs forever in the background and gets restarted during login with adjusted service values. The action always runs the amount of times the app was killed simultaneously. Personally I think the error has something todo with react native Appregistry.runApplication always creating a new RootTag

fabiros commented 2 years ago

@Rapsssito i modified the pkg code locally and when i adjust the onStartCommand like this it works.

@Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        final Bundle extras = intent.getExtras();
        if (extras == null) {
            throw new IllegalArgumentException("Extras cannot be null");
        }
        final Options bgOptions = new Options(extras);
        createNotificationChannel(bgOptions.getTaskTitle(), bgOptions.getTaskDesc()); // Necessary creating channel for API 26+
        // Create the notification
        final Notification notification = buildNotification(this, bgOptions);

        startForeground(SERVICE_NOTIFICATION_ID, notification);

        HeadlessJsTaskConfig taskConfig = this.getTaskConfig(intent);

        if (taskConfig != null) {
            this.stopForeground(false);
            this.startTask(taskConfig);
        }

        return START_NOT_STICKY;
    }

Dont know if this solves the problem, but worked for me

Rapsssito commented 2 years ago

@fabiros, could you create a PR with your code so we can have this "fix" in a branch at least?

fabiros commented 2 years ago

@Rapsssito done

Rapsssito commented 2 years ago

This issue should be fixed by #124. Feel free to reopen if the problem persists.

Rapsssito commented 2 years ago

I have reopened the issue since I had to revert the PR (#124) because it was creating another issue: #126.

shafnashah95 commented 3 months ago

Does any one found the solution for this?