Skip to content
This repository was archived by the owner on Nov 8, 2023. It is now read-only.

Commit 43a2987

Browse files
Merge pull request #162 from NativeScript/amiorkov/api-26-background-service
fix: Add implementation for background service for API 26 and above
2 parents 8e55c69 + 2c59ee1 commit 43a2987

File tree

3 files changed

+128
-42
lines changed

3 files changed

+128
-42
lines changed

demo/app/App_Resources/Android/AndroidManifest.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@
2929
android:exported="false" >
3030
</service>
3131

32+
<service android:name="com.nativescript.location.BackgroundService26"
33+
android:permission="android.permission.BIND_JOB_SERVICE"
34+
android:enabled="true"
35+
android:exported="false">
36+
</service>
37+
3238
<activity
3339
android:name="com.tns.NativeScriptActivity"
3440
android:label="@string/title_activity_kimera"

demo/app/background-service.ts

Lines changed: 88 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,95 @@
11
import * as geolocation from "nativescript-geolocation";
22
import { Accuracy } from "tns-core-modules/ui/enums";
33
import * as application from "tns-core-modules/application";
4+
import { device } from "tns-core-modules/platform";
45
import * as Toast from "nativescript-toast";
56

7+
let watchId;
8+
application.on(application.exitEvent, function (args: any) {
9+
if (watchId) {
10+
geolocation.clearWatch(watchId);
11+
}
12+
});
13+
614
if (application.android) {
7-
(<any>android.app.Service).extend("com.nativescript.location.BackgroundService", {
8-
onStartCommand: function (intent, flags, startId) {
9-
this.super.onStartCommand(intent, flags, startId);
10-
return android.app.Service.START_STICKY;
11-
},
12-
onCreate: function () {
13-
let that = this;
14-
geolocation.enableLocationRequest().then(function () {
15-
that.id = geolocation.watchLocation(
16-
function (loc) {
17-
if (loc) {
18-
let toast = Toast.makeText('Background Location: ' + loc.latitude + ' ' + loc.longitude);
19-
toast.show();
20-
console.log('Background Location: ' + loc.latitude + ' ' + loc.longitude);
21-
}
22-
},
23-
function (e) {
24-
console.log("Background watchLocation error: " + (e.message || e));
25-
},
26-
{
27-
desiredAccuracy: Accuracy.high,
28-
updateDistance: 0.1,
29-
updateTime: 3000,
30-
minimumUpdateTime: 100
31-
});
32-
}, function (e) {
33-
console.log("Background enableLocationRequest error: " + (e.message || e));
34-
});
35-
},
36-
onBind: function (intent) {
37-
console.log("on Bind Services");
38-
},
39-
onUnbind: function (intent) {
40-
console.log('UnBind Service');
41-
},
42-
onDestroy: function () {
43-
console.log('service onDestroy');
44-
geolocation.clearWatch(this.id);
45-
}
46-
});
15+
if (device.sdkVersion < "26") {
16+
(<any>android.app.Service).extend("com.nativescript.location.BackgroundService", {
17+
onStartCommand: function (intent, flags, startId) {
18+
this.super.onStartCommand(intent, flags, startId);
19+
return android.app.Service.START_STICKY;
20+
},
21+
onCreate: function () {
22+
let that = this;
23+
geolocation.enableLocationRequest().then(function () {
24+
that.id = geolocation.watchLocation(
25+
function (loc) {
26+
if (loc) {
27+
let toast = Toast.makeText('Background Location: ' + loc.latitude + ' ' + loc.longitude);
28+
toast.show();
29+
console.log('Background Location: ' + loc.latitude + ' ' + loc.longitude);
30+
}
31+
},
32+
function (e) {
33+
console.log("Background watchLocation error: " + (e.message || e));
34+
},
35+
{
36+
desiredAccuracy: Accuracy.high,
37+
updateDistance: 0.1,
38+
updateTime: 3000,
39+
minimumUpdateTime: 100
40+
});
41+
}, function (e) {
42+
console.log("Background enableLocationRequest error: " + (e.message || e));
43+
});
44+
},
45+
onBind: function (intent) {
46+
console.log("on Bind Services");
47+
},
48+
onUnbind: function (intent) {
49+
console.log('UnBind Service');
50+
},
51+
onDestroy: function () {
52+
console.log('service onDestroy');
53+
geolocation.clearWatch(this.id);
54+
}
55+
});
56+
}
57+
else {
58+
(<any>android.app).job.JobService.extend("com.nativescript.location.BackgroundService26", {
59+
onStartJob(params) {
60+
let executed = false;
61+
geolocation.enableLocationRequest().then(function () {
62+
watchId = geolocation.watchLocation(
63+
function (loc) {
64+
if (loc) {
65+
let toast = Toast.makeText('Background Location: ' + loc.latitude + ' ' + loc.longitude);
66+
toast.show();
67+
console.log('Background Location: ' + loc.latitude + ' ' + loc.longitude);
68+
}
69+
executed = true;
70+
},
71+
function (e) {
72+
console.log("Background watchLocation error: " + (e.message || e));
73+
executed = true;
74+
},
75+
{
76+
desiredAccuracy: Accuracy.high,
77+
updateDistance: 0.1,
78+
updateTime: 3000,
79+
minimumUpdateTime: 100
80+
});
81+
}, function (e) {
82+
console.log("Background enableLocationRequest error: " + (e.message || e));
83+
});
84+
85+
return executed;
86+
},
87+
88+
onStopJob() {
89+
console.log('service onStopJob');
90+
geolocation.clearWatch(watchId);
91+
return true;
92+
},
93+
});
94+
}
4795
}

demo/app/main-page.ts

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,26 @@ import { Page } from "ui/page";
55
import { MainViewModel } from "./main-view-model";
66
const utils = require("tns-core-modules/utils/utils");
77
import * as application from "tns-core-modules/application";
8+
import { device } from "tns-core-modules/platform";
9+
810
let locationService = require('./background-service');
911

1012
let page: Page;
1113
let model = new MainViewModel();
1214
let watchIds = [];
15+
let backgroundIds = [];
1316
declare var com: any;
1417

18+
application.on(application.exitEvent, function (args: any) {
19+
if (application.android && backgroundIds.length > 0) {
20+
let context = utils.ad.getApplicationContext();
21+
const jobScheduler = context.getSystemService((<any>android.content.Context).JOB_SCHEDULER_SERVICE);
22+
const service = backgroundIds.pop();
23+
jobScheduler.cancel(service);
24+
console.log(`Job Canceled: ${service}`);
25+
}
26+
});
27+
1528
export function pageLoaded(args: EventData) {
1629
page = <Page>args.object;
1730
page.bindingContext = model;
@@ -21,15 +34,34 @@ export function startBackgroundTap() {
2134
if (application.android) {
2235
let context = utils.ad.getApplicationContext();
2336
let intent = new android.content.Intent(context, com.nativescript.location.BackgroundService.class);
24-
context.startService(intent);
37+
if (device.sdkVersion >= "26") {
38+
const component = new android.content.ComponentName(context, com.nativescript.location.BackgroundService26.class);
39+
const builder = new (<any>android.app).job.JobInfo.Builder(1, component);
40+
builder.setRequiredNetworkType((<any>android.app).job.JobInfo.NETWORK_TYPE_ANY);
41+
builder.setPeriodic(15 * 60 * 1000);
42+
const jobScheduler = context.getSystemService((<any>android.content.Context).JOB_SCHEDULER_SERVICE);
43+
const service = jobScheduler.schedule(builder.build());
44+
backgroundIds.push(service);
45+
} else {
46+
context.startService(intent);
47+
}
2548
}
2649
}
2750

2851
export function stopBackgroundTap() {
2952
if (application.android) {
3053
let context = utils.ad.getApplicationContext();
3154
let intent = new android.content.Intent(context, com.nativescript.location.BackgroundService.class);
32-
context.stopService(intent);
55+
if (device.sdkVersion >= "26") {
56+
if (backgroundIds.length > 0) {
57+
const jobScheduler = context.getSystemService((<any>android.content.Context).JOB_SCHEDULER_SERVICE);
58+
const service = backgroundIds.pop();
59+
jobScheduler.cancel(service);
60+
console.log(`Job Canceled: ${service}`);
61+
}
62+
} else {
63+
context.stopService(intent);
64+
}
3365
}
3466
}
3567

0 commit comments

Comments
 (0)