- [iOS] Code-sign
TSBackgroundFetch.xcframework
with new Apple Organization (9224-2932 Quebec Inc) certificate.
- [iOS] Implement new iOS Privacy Manifest
- [iOS] codesign
TSBackgroundFetch.xcframework
- [iOS] Only allow registration of
BGProcessingTasks
(Permitted background task scheduler identifiers) inInfo.plist
which are prefixed withcom.transistorsoft
. Any other task identifier will be ignored.
- [Android] Detect and dispose of duplicate events. Android
JobService
has a bug for devices running <= Android M where multiplebackground-fetch
events could fire within the same second.
- [Android] Android 14 (SDK 34) support.
- [Android] Android 14 (SDK 34) support: When using
forceAlarmManager: true
, you must now optionally add the permissionandroid.permission.USE_EXACT_ALARM
to yourAndroidManifest
to schedule exact alarms. OtherwiseAlarmManager
will use in-exact alarms. NOTE You must include the permission exactly as-shown withandroid:minSdkVersion="34"
.
📂 AndroidManifest
<platform name="android">
<config-file parent="/manifest" target="app/src/main/AndroidManifest.xml">
<uses-permission android:minSdkVersion="34" android:name="android.permission.USE_EXACT_ALARM" />
</config-file>
.
.
.
</platform>
- [Android] Add Cordova
onDestroy
listener to manually setLifecycleManager.setHeadless(true)
.
- [Android] Use
LifecycleManager
for modern headless-detection instead of legacy mechanism requiring permissionGET_TASKS
.
- Mixup in version code mismatch between package.json and plugin.xml
- [Android] Update for Android 12. Add new required permission android.permission.SCHEDULE_EXACT_ALARM
- [Changed][Android] Allow multiple calls to .configure to allow re-configuring the fetch task. Existing task will be cancelled and a new periodic fetch task re-scheduled according to new config.
- [Changed][Android] Ignore initial fetch task fired immediately.
- [Changed][Android]
android:exported="false"
onBootReceiver
to resolve reported security analysis.
- [Fixed][Android] Android failed to detect Capacitor v3 apps. capacitor.config.json vs capacitor.config.[js|ts]
- [Fixed][Android] Fix
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.transistorsoft.tsbackgroundfetch.BGTask.getTaskId()' on a null object reference
-
[Added][iOS] Implement two new iOS options for
BackgroundFetch.scheduleTask
:bool requiresNetworkConnectivity
bool requiresCharging
(previously Android-only).
-
[Changed][iOS] Migrate
TSBackgroundFetch.framework
to new.xcframework
for MacCatalyst support with new Apple silcon.
iOS' new .xcframework
requires cocoapods >= 1.10+:
$ pod --version
// if < 1.10.0
$ sudo gem install cocoapods
- [Added] task-timeout callback, executed when the operating system has signalled your remaining background-time is about to expire. You must stop what you're doing and immediately call
BackgroundFetch.finish(taskId)
The method-signature for BackgroundFetch.configure
has dramatically changed and now returns Promise<BackgroundFetchStatus>
.
When BackgroundFetch
failed to start (eg: user disabled "Background Fetch" permission in your app settings), the 2nd argument failureCallback
would fire with the current BackgroundFetchStatus
.
BackgroundFetch.configure(eventCallback, failureCallback, config);
let status = await BackgroundFetch.configure(config, eventCallback, timeoutCallback);
The current BackgroundFetchStatus
is now returned as a Promise
when calling .configure()
. The BackgroundFetchConfig
has moved from 3rd position to 1st position. The 3rd argument is now timeoutCallback
, executed when OS has signalled your allowed background time is about to expire:
@param BackgroundFetchConfig
Configuration object.@param Function
Event callback function.@param Function
Event timeout callback function. This callback will be executed when the operating system has signalled your background-time is about to expire.
// Usual config object.
let config = {minimumFetchInterval: 15};
// Usual BackgroundFetch event handler.
let eventCallback = async (taskId) => { // <-- task callback.
console.log('[BackgroundFetch] task: ', taskId);
// Do your background work...
BackgroundFetch.finish(taskId);
}
// NEW: Timeout callback is executed when your Task has exceeded its allowed running-time.
// You must stop what you're doing immediately BackgroundFetch.finish(taskId)
let timeoutCallback = async (taskId) => {
console.warn('[BackgroundFetch] TIMEOUT task: ', taskId);
BackgroundFetch.finish(taskId);
}
// BackgroundFetch now returns a Promise<BackgroundFetchStatus> and the order-of-arguments
// has significantly changed.
let status = await BackgroundFetch.configure(config, eventCallback, timeoutCallback);
console.log('[BackgroundFetch] configure status: ', status);
- In order to differentiate task timeout events, the Android Headless Task now receives a
BGTask task
instance instead ofString taskId
. When the OS signals your allowed background-time is about to expire,task.getTimedOut()
will returntrue
.taskId
is available viatask.getTaskId()
.
package com.transistorsoft.cordova.backgroundfetch;
import android.content.Context;
import android.util.Log;
import com.transistorsoft.tsbackgroundfetch.BackgroundFetch;
import com.transistorsoft.tsbackgroundfetch.BGTask; // <-- NEW: import BGTask
public class BackgroundFetchHeadlessTask implements HeadlessTask {
@Override
public void onFetch(Context context, BGTask task) { // <-- NEW: BGTask instead of String taskId.
String taskId = task.getTaskId();
boolean isTimeout = task.getTimedOut();
if (isTimeout) {
// The operating system has signalled your background-time is about to expire.
// You must stop what you're doing and immediately call .finish(taskId).
Log.d(BackgroundFetch.TAG, "BackgroundFetchHeadlessTask onFetch TIMEOUT taskId: " + task.getTaskId());
BackgroundFetch.getInstance(context).finish(taskId);
return;
}
Log.d(BackgroundFetch.TAG, "BackgroundFetchHeadlessTask onFetch: taskId: " + task.getTaskId());
// Do your background work here...
BackgroundFetch.getInstance(context).finish(taskId);
}
}
[Fixed] Modify plugin.xml
to copy android libs
to platforms/android/libs
rather than referencing from /plugins/src/android/libs
-- this was not possible with PhoneGap Build.
- [Fixed][Android] *
com.android.tools.build:gradle:4.0.0
no longer allows "direct local aar dependencies". Re-packagetslocationmanager.aar
as a maven repo and addmaven url
inbuild.gradle
.
- [Fixed] Android could fail to restart events when configured with forceAlarmManager: true.
- [Fixed] Android check
wakeLock.isHeld()
before executingwakeLock.release()
.
- [Fixed][Android] Update gradle file for Capacitor-detection relative to
$projectDir
instead of$userDir
.
- [Fixed] [Android] Fixed bug related to
6.0.5
referencing non existentBackgroundGeolocationHeadlessTask
. Define class-name as a hard-coded String instead.
- [Changed] Don't install default
BackgroundGeolocationHeadlessTask.java
- [Fixed][iOS] Fix bug calling BackgroundFetch.start after BackgroundFetch.stop.
- [Fixed] [Android] Remove unused imports in
CDVBackgroundGeocation.java
causing problems with AndroidX. Fixes #121.
- [Fixed] [Android]
stopOnTerminate
not cancelling scheduled job / Alarm when fired task fired after terminate.
- [Android] Fix Android NPE on
hasTaskId
when launched first time after upgrading to v6
- [Added] [Android-only] New option
forceAlarmManager
for bypassingJobScheduler
mechanism in favour ofAlarmManager
for more precise scheduling task execution. - [Changed] Migrate iOS deprecated "background-fetch" API to new BGTaskScheduler. See new required steps in iOS Setup.
- [Added] Added new
BackgroundFetch.scheduleTask
method (along with corresponding#stopTask
) for scheduling custom "onehot" and periodic tasks in addition to the default fetch-task.
BackgroundFetch.configure({
minimumFetchInterval: 15,
stopOnTerminate: false
}, (taskId) => { // <-- [NEW] taskId provided to Callback
console.log("[BackgroundFetch] taskId: ", taskId);
switch(taskId) {
case 'foo':
// Handle scheduleTask 'foo'
break;
default:
// Handle default fetch event.
break;
}
BackgroundFetch.finish(taskId); // <-- [NEW] Provided taskId to #finish method.
});
// This event will end up in Callback provided to #configure above.
BackgroundFetch.scheduleTask({
taskId: 'foo', //<-- required
delay: 60000,
periodic: false
});
- With the introduction of ability to execute custom tasks via
#scheduleTask
, all tasks are executed in the Callback provided to#configure
. As a result, this Callback is now provided an argumentString taskId
. ThistaskId
must now be provided to the#finish
method, so that the SDK knows which task is being#finish
ed.
BackgroundFetch.configure({
minimumFetchInterval: 15,
stopOnTerminate: false
), (taskId) => { // <-- [NEW] taskId provided to Callback
console.log("[BackgroundFetch] taskId: ", taskId);
BackgroundFetch.finish(taskId); // <-- [NEW] Provided taskId to #finish method.
});
And with the Headless Task, as well:
public class BackgroundFetchHeadlessTask implements HeadlessTask {
@Override
public void onFetch(Context context, String taskId) { // <-- 1. Added String taskId as 2nd argument
Log.d(BackgroundFetch.TAG, "BackgroundFetchHeadlessTask onFetch: " + taskId);
BackgroundFetch.getInstance(context).finish(taskId); // <-- 2. Provide taskId to #finish.
}
}
- [Fixed] Resolve Android issues exposed by booting app in StrictMode, typically from loading SharedPreferences on Main Thread.
- [Added] Capacitor support
- [Added] Typescript API
- [Added] Android
JobInfo
criteriarequiredNetworkType
,requiresCharging
,requiresBatteryNotLow
,requiresDeviceIdle
,requiresStorageNotLow
. - [Added]
finish
now acceptsBackgroundFetch.FETCH_RESULT_*
(eg:BackgroundFetch.FETCH_RESULT_NO_DATA
).
- [Changed] Decrease required cordova version from
8.0.0
->7.1.0
.
- [Added]
cordova-android @ 7.0.0
support.
- [Changed] The Android library
tsbackgroundfetch.aar
has been composed as a Maven repository. Purely structural change; no implementation has changed with this version.
- [Added] Android implementation using
JobScheduler
/AlarmManager