Foreground Services (Mandatory)
Foreground Services are essential for reliable P2P operations on Android. This guide explains when and how to use them with LiteP2P.
Why Foreground Services Are Required
Without a Foreground Service, Android will aggressively restrict your application's ability to maintain P2P connections.
Without Foreground Service
TCP connections drop silently
Android terminates background network connections without warning
NAT mappings expire
Port mappings are not renewed, breaking incoming connections
CPU execution is suspended
Your app cannot process data or maintain state
File transfers fail
Large transfers are interrupted when the app goes to background
With Foreground Service
Network stays active
Connections are maintained even when the app is in background
CPU scheduling is stable
Your app gets consistent CPU time for processing
Long operations complete reliably
File transfers and syncs finish without interruption
When to Use a Foreground Service
You must start a Foreground Service when performing these operations:
| Operation | Foreground Service Required | Reason |
|---|---|---|
| Transferring files | ✅ Yes | Prevents transfer interruption |
| Cryptographic handshakes | ✅ Yes | Key exchange must complete atomically |
| Maintaining multiple peers | ✅ Yes | Requires sustained network access |
| Acting as a relay | ✅ Yes | Must forward traffic continuously |
| Performing heavy sync | ✅ Yes | Large data transfers need time |
| Idle / waiting | ❌ No | Use push notifications instead |
Do NOT use a Foreground Service when idle. This wastes battery and may cause your app to be flagged by Google Play for policy violations.
Implementation
Here's how to implement a Foreground Service for LiteP2P operations.
1. Declare in Manifest
<service
android:name=".LiteP2PService"
android:foregroundServiceType="dataSync"
android:exported="false" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
2. Create the Service
class LiteP2PService : Service() {
private val NOTIFICATION_ID = 1001
private val CHANNEL_ID = "litep2p_channel"
override fun onCreate() {
super.onCreate()
createNotificationChannel()
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
val notification = createNotification()
startForeground(NOTIFICATION_ID, notification)
// Start P2P operations
LiteP2P.getInstance().startActiveSync()
return START_STICKY
}
override fun onBind(intent: Intent?): IBinder? = null
private fun createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
CHANNEL_ID,
"LiteP2P Sync",
NotificationManager.IMPORTANCE_LOW
).apply {
description = "Active P2P synchronization"
}
val manager = getSystemService(NotificationManager::class.java)
manager.createNotificationChannel(channel)
}
}
private fun createNotification(): Notification {
return NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("Syncing with peers")
.setContentText("Transferring data...")
.setSmallIcon(R.drawable.ic_sync)
.setPriority(NotificationCompat.PRIORITY_LOW)
.setOngoing(true)
.build()
}
}
3. Start and Stop Appropriately
// Start when beginning file transfer
fun startFileTransfer(peerId: String, file: File) {
val intent = Intent(context, LiteP2PService::class.java)
ContextCompat.startForegroundService(context, intent)
LiteP2P.getInstance().sendFile(peerId, file) { result ->
// Stop service when complete
context.stopService(intent)
}
}
// Or use LiteP2P's built-in helper
LiteP2P.getInstance().withForegroundService(context) {
// Operations here run with foreground service protection
sendLargeFile(peerId, file)
}
Android 14+ Foreground Service Types
Starting with Android 14, you must declare a specific foreground service type. For LiteP2P operations, use:
| Operation | Service Type |
|---|---|
| Data sync / file transfer | dataSync |
| Media playback (if applicable) | mediaPlayback |
| Connected device | connectedDevice |