Skip to content

Commit a6fb1b2

Browse files
committed
Added foreground service support
Signed-off-by: ddeviatilov <9.tilov@gmail.com>
1 parent f0b45d5 commit a6fb1b2

File tree

4 files changed

+55
-2
lines changed

4 files changed

+55
-2
lines changed

tunnel/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ android {
6868
dependencies {
6969
implementation(libs.androidx.annotation)
7070
implementation(libs.androidx.collection)
71+
implementation(libs.androidx.core.ktx)
7172
compileOnly(libs.jsr305)
7273
testImplementation(libs.junit)
7374
}

tunnel/src/main/AndroidManifest.xml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,15 @@
55

66
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
77

8+
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SYSTEM_EXEMPTED" />
9+
810
<application>
911
<service
1012
android:name="com.wireguard.android.backend.GoBackend$VpnService"
1113
android:permission="android.permission.BIND_VPN_SERVICE"
12-
android:exported="false">
14+
android:exported="false"
15+
android:persistent="true"
16+
android:foregroundServiceType="systemExempted">
1317
<intent-filter>
1418
<action android:name="android.net.VpnService" />
1519
</intent-filter>

tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,13 @@
55

66
package com.wireguard.android.backend;
77

8+
import android.app.ForegroundServiceStartNotAllowedException;
9+
import android.app.Notification;
10+
import android.app.NotificationChannel;
11+
import android.app.NotificationManager;
812
import android.content.Context;
913
import android.content.Intent;
14+
import android.content.pm.ServiceInfo;
1015
import android.os.Build;
1116
import android.os.ParcelFileDescriptor;
1217
import android.system.OsConstants;
@@ -24,7 +29,6 @@
2429
import com.wireguard.util.NonNullForAll;
2530

2631
import java.net.InetAddress;
27-
import java.time.Instant;
2832
import java.util.Collections;
2933
import java.util.Set;
3034
import java.util.concurrent.ExecutionException;
@@ -35,6 +39,8 @@
3539

3640
import androidx.annotation.Nullable;
3741
import androidx.collection.ArraySet;
42+
import androidx.core.app.NotificationCompat;
43+
import androidx.core.app.ServiceCompat;
3844

3945
/**
4046
* Implementation of {@link Backend} that uses the wireguard-go userspace implementation to provide
@@ -392,6 +398,9 @@ public GhettoCompletableFuture<V> newIncompleteFuture() {
392398
* {@link android.net.VpnService} implementation for {@link GoBackend}
393399
*/
394400
public static class VpnService extends android.net.VpnService {
401+
402+
private static final int NOTIFICATION_ID = 999;
403+
private static final String CHANNEL_ID = "WireGuardChannel";
395404
@Nullable private GoBackend owner;
396405

397406
public Builder getBuilder() {
@@ -423,6 +432,7 @@ public void onDestroy() {
423432

424433
@Override
425434
public int onStartCommand(@Nullable final Intent intent, final int flags, final int startId) {
435+
startForeground();
426436
vpnService.complete(this);
427437
if (intent == null || intent.getComponent() == null || !intent.getComponent().getPackageName().equals(getPackageName())) {
428438
Log.d(TAG, "Service started by Always-on VPN feature");
@@ -435,5 +445,42 @@ public int onStartCommand(@Nullable final Intent intent, final int flags, final
435445
public void setOwner(final GoBackend owner) {
436446
this.owner = owner;
437447
}
448+
449+
private void startForeground() {
450+
try {
451+
createNotificationChannel();
452+
final Notification notification = new NotificationCompat
453+
.Builder(this, CHANNEL_ID)
454+
.build();
455+
ServiceCompat.startForeground(this, NOTIFICATION_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_SYSTEM_EXEMPTED);
456+
} catch (final Exception ex) {
457+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S &&
458+
ex instanceof ForegroundServiceStartNotAllowedException
459+
) {
460+
Log.d(TAG, "App not in a valid state to start foreground service");
461+
}
462+
}
463+
}
464+
465+
private void createNotificationChannel() {
466+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
467+
final NotificationManager notificationManager =
468+
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
469+
470+
if (notificationManager.getNotificationChannel(CHANNEL_ID) == null) {
471+
final NotificationChannel channel = new NotificationChannel(
472+
CHANNEL_ID,
473+
"WireGuard VPN Service",
474+
NotificationManager.IMPORTANCE_LOW
475+
);
476+
channel.setDescription("VPN connection status notifications");
477+
channel.setShowBadge(false);
478+
channel.enableLights(false);
479+
channel.enableVibration(false);
480+
481+
notificationManager.createNotificationChannel(channel);
482+
}
483+
}
484+
}
438485
}
439486
}

wireguard-android

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Subproject commit f0b45d50f332cd532ee9f62cd51582da6fea7e49

0 commit comments

Comments
 (0)