File Transfers & Heavy Work
Large file transfers require special handling on Android. This guide covers best practices for reliable, battery-efficient file transfers with LiteP2P.
File Transfer Rules
Follow these rules for reliable file transfers:
| Rule | Requirement | Reason |
|---|---|---|
| Foreground Service | Mandatory | Prevents OS from killing transfer |
| Prefer Charging + Wi-Fi | Recommended | Best battery and bandwidth |
| Use QUIC for large files | Recommended | Better performance, resumability |
| Lightweight control channel | Required | Keep TCP channel for signaling only |
Required
File transfers must run during a Foreground Service. Without it, Android will terminate the transfer when the app goes to background.
Basic File Transfer
// Start foreground service first
val serviceIntent = Intent(context, LiteP2PService::class.java)
ContextCompat.startForegroundService(context, serviceIntent)
// Send file
val p2p = LiteP2P.getInstance()
val transfer = p2p.sendFile(
peerId = targetPeerId,
file = fileToSend,
options = FileTransferOptions.Builder()
.setResumeEnabled(true)
.setChunkSize(64 * 1024) // 64KB chunks
.build()
)
// Monitor progress
transfer.onProgress { progress ->
updateNotification(progress.bytesTransferred, progress.totalBytes)
}
transfer.onComplete { result ->
when (result) {
is TransferResult.Success -> {
Log.d("LiteP2P", "File sent successfully")
}
is TransferResult.Error -> {
Log.e("LiteP2P", "Transfer failed: ${result.message}")
}
}
// Stop foreground service
context.stopService(serviceIntent)
}
QUIC for Large Transfers
For files over 1MB, use QUIC transport for better performance:
val options = FileTransferOptions.Builder()
.setTransport(TransferTransport.QUIC) // Use QUIC instead of TCP
.setResumeEnabled(true) // Enable resume on disconnect
.setVerifyIntegrity(true) // SHA-256 verification
.setMaxRetries(3) // Auto-retry on failure
.build()
val transfer = p2p.sendFile(peerId, largeFile, options)
Why QUIC?
- Faster connection establishment – 0-RTT handshake
- Better on unreliable networks – Handles packet loss gracefully
- Stream multiplexing – Multiple files over one connection
- Built-in encryption – TLS 1.3 by default
- Connection migration – Survives network changes
Receiving Files
// Register file receive handler
p2p.onFileTransferRequest { request ->
// Decide whether to accept
val shouldAccept = checkStorageSpace(request.fileSize) &&
userHasApproved(request)
if (shouldAccept) {
// Start foreground service for receiving
startForegroundService()
val download = request.accept(
destination = getDownloadPath(request.fileName)
)
download.onProgress { progress ->
updateDownloadNotification(progress)
}
download.onComplete { result ->
handleDownloadComplete(result)
stopForegroundService()
}
} else {
request.reject(RejectReason.USER_DECLINED)
}
}
Waiting for Optimal Conditions
For non-urgent transfers, wait for ideal conditions:
// Check conditions before transfer
fun shouldTransferNow(): Boolean {
val battery = context.batteryManager
val connectivity = context.connectivityManager
val isCharging = battery.isCharging
val isWifi = connectivity.activeNetwork?.let { network ->
connectivity.getNetworkCapabilities(network)
?.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
} ?: false
return isCharging && isWifi
}
// Queue transfer for later
if (!shouldTransferNow()) {
p2p.queueFileTransfer(peerId, file, TransferPriority.LOW)
// Will be sent when conditions are met
p2p.setTransferConditions(
requireCharging = true,
requireWifi = true,
requireBatteryLevel = 20 // Minimum 20%
)
}
Resume Support
LiteP2P supports resuming interrupted transfers:
// Enable resume
val options = FileTransferOptions.Builder()
.setResumeEnabled(true)
.build()
// On connection restore, check for pending transfers
p2p.onConnectionRestored { peerId ->
val pendingTransfers = p2p.getPendingTransfers(peerId)
pendingTransfers.forEach { transfer ->
Log.d("LiteP2P", "Resuming transfer: ${transfer.fileName} " +
"from ${transfer.bytesTransferred}/${transfer.totalBytes}")
transfer.resume()
}
}
Best Practices
Always use Foreground Service for transfers
Show progress in notification
Enable resume for files over 1MB
Use QUIC for large transfers
Queue non-urgent transfers for Wi-Fi + charging
Verify file integrity after transfer