🎯 Exemplos recomendados
Balanced sample collections from various categories for you to explore
Exemplos de Programação de Rede Android Kotlin
Exemplos de programação de rede Android Kotlin incluindo solicitações HTTP, download/upload de arquivos e conexões WebSocket
💻 Solicitações HTTP kotlin
🟢 simple
⭐⭐⭐
Enviar solicitações GET e POST usando HttpURLConnection e biblioteca OkHttp com tratamento de erros apropriado
⏱️ 30 min
🏷️ kotlin, android, networking, http
Prerequisites:
Basic Kotlin knowledge, Internet permission in manifest
// Android Kotlin HTTP Request Examples
// Using HttpURLConnection and OkHttp
import android.content.Context
import kotlinx.coroutines.*
import java.io.*
import java.net.*
import okhttp3.*
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.RequestBody.Companion.toRequestBody
import org.json.JSONObject
// 1. HttpURLConnection Examples
class HttpURLConnectionExample(private val context: Context) {
// Simple GET request
suspend fun simpleGetRequest(url: String): String? = withContext(Dispatchers.IO) {
var connection: HttpURLConnection? = null
try {
val urlObj = URL(url)
connection = urlObj.openConnection() as HttpURLConnection
connection.requestMethod = "GET"
connection.connectTimeout = 10000
connection.readTimeout = 10000
val responseCode = connection.responseCode
println("Response Code: $responseCode")
if (responseCode == HttpURLConnection.HTTP_OK) {
val response = connection.inputStream.bufferedReader().use { it.readText() }
println("Response: $response")
return@withContext response
} else {
println("Error response code: $responseCode")
return@withContext null
}
} catch (e: Exception) {
println("GET Request Error: ${e.message}")
return@withContext null
} finally {
connection?.disconnect()
}
}
// POST request with JSON body
suspend fun postJsonRequest(url: String, jsonData: JSONObject): String? = withContext(Dispatchers.IO) {
var connection: HttpURLConnection? = null
try {
val urlObj = URL(url)
connection = urlObj.openConnection() as HttpURLConnection
connection.requestMethod = "POST"
connection.setRequestProperty("Content-Type", "application/json")
connection.doOutput = true
// Write JSON body
val outputStream = connection.outputStream
outputStream.write(jsonData.toString().toByteArray(Charsets.UTF_8))
outputStream.flush()
outputStream.close()
val responseCode = connection.responseCode
println("POST Response Code: $responseCode")
if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_CREATED) {
val response = connection.inputStream.bufferedReader().use { it.readText() }
println("POST Response: $response")
return@withContext response
} else {
return@withContext null
}
} catch (e: Exception) {
println("POST Request Error: ${e.message}")
return@withContext null
} finally {
connection?.disconnect()
}
}
// POST request with form data
suspend fun postFormData(url: String, params: Map<String, String>): String? = withContext(Dispatchers.IO) {
var connection: HttpURLConnection? = null
try {
val urlObj = URL(url)
connection = urlObj.openConnection() as HttpURLConnection
connection.requestMethod = "POST"
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded")
connection.doOutput = true
// Build form data
val formData = params.map { "${URLEncoder.encode(it.key, "UTF-8")}=${URLEncoder.encode(it.value, "UTF-8")}" }
.joinToString("&")
val outputStream = connection.outputStream
outputStream.write(formData.toByteArray(Charsets.UTF_8))
outputStream.flush()
outputStream.close()
val responseCode = connection.responseCode
if (responseCode == HttpURLConnection.HTTP_OK) {
val response = connection.inputStream.bufferedReader().use { it.readText() }
return@withContext response
} else {
return@withContext null
}
} catch (e: Exception) {
println("Form POST Error: ${e.message}")
return@withContext null
} finally {
connection?.disconnect()
}
}
// GET request with headers
suspend fun getRequestWithHeaders(url: String, headers: Map<String, String>): String? = withContext(Dispatchers.IO) {
var connection: HttpURLConnection? = null
try {
val urlObj = URL(url)
connection = urlObj.openConnection() as HttpURLConnection
connection.requestMethod = "GET"
// Add custom headers
headers.forEach { (key, value) ->
connection.setRequestProperty(key, value)
}
val responseCode = connection.responseCode
if (responseCode == HttpURLConnection.HTTP_OK) {
val response = connection.inputStream.bufferedReader().use { it.readText() }
return@withContext response
} else {
return@withContext null
}
} catch (e: Exception) {
println("GET with Headers Error: ${e.message}")
return@withContext null
} finally {
connection?.disconnect()
}
}
}
// 2. OkHttp Examples
class OkHttpExample(private val context: Context) {
private val client = OkHttpClient.Builder()
.connectTimeout(10, java.util.concurrent.TimeUnit.SECONDS)
.readTimeout(10, java.util.concurrent.TimeUnit.SECONDS)
.build()
// Simple GET with OkHttp
suspend fun simpleGet(url: String): String? = withContext(Dispatchers.IO) {
try {
val request = Request.Builder()
.url(url)
.build()
val response = client.newCall(request).execute()
if (response.isSuccessful) {
return@withContext response.body?.string()
} else {
return@withContext null
}
} catch (e: Exception) {
println("OkHttp GET Error: ${e.message}")
return@withContext null
}
}
// Async GET with callback
fun asyncGet(url: String, callback: (String?) -> Unit) {
val request = Request.Builder()
.url(url)
.build()
client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
println("Async GET failed: ${e.message}")
callback(null)
}
override fun onResponse(call: Call, response: Response) {
val body = response.body?.string()
callback(body)
}
})
}
// POST with JSON body
suspend fun postJson(url: String, json: JSONObject): String? = withContext(Dispatchers.IO) {
try {
val mediaType = "application/json".toMediaType()
val body = json.toString().toRequestBody(mediaType)
val request = Request.Builder()
.url(url)
.post(body)
.build()
val response = client.newCall(request).execute()
if (response.isSuccessful) {
return@withContext response.body?.string()
} else {
return@withContext null
}
} catch (e: Exception) {
println("OkHttp POST Error: ${e.message}")
return@withContext null
}
}
// POST with form data
suspend fun postForm(url: String, params: Map<String, String>): String? = withContext(Dispatchers.IO) {
try {
val formBody = FormBody.Builder()
params.forEach { (key, value) ->
formBody.add(key, value)
}
val request = Request.Builder()
.url(url)
.post(formBody.build())
.build()
val response = client.newCall(request).execute()
if (response.isSuccessful) {
return@withContext response.body?.string()
} else {
return@withContext null
}
} catch (e: Exception) {
println("Form POST Error: ${e.message}")
return@withContext null
}
}
// PUT request
suspend fun putRequest(url: String, json: JSONObject): String? = withContext(Dispatchers.IO) {
try {
val mediaType = "application/json".toMediaType()
val body = json.toString().toRequestBody(mediaType)
val request = Request.Builder()
.url(url)
.put(body)
.build()
val response = client.newCall(request).execute()
if (response.isSuccessful) {
return@withContext response.body?.string()
} else {
return@withContext null
}
} catch (e: Exception) {
println("PUT Error: ${e.message}")
return@withContext null
}
}
// DELETE request
suspend fun deleteRequest(url: String): Boolean = withContext(Dispatchers.IO) {
try {
val request = Request.Builder()
.url(url)
.delete()
.build()
val response = client.newCall(request).execute()
return@withContext response.isSuccessful
} catch (e: Exception) {
println("DELETE Error: ${e.message}")
return@withContext false
}
}
// Request with custom headers
suspend fun requestWithHeaders(
url: String,
headers: Map<String, String>,
method: String = "GET"
): String? = withContext(Dispatchers.IO) {
try {
val requestBuilder = Request.Builder()
.url(url)
// Add headers
headers.forEach { (key, value) ->
requestBuilder.addHeader(key, value)
}
// Set method
when (method.uppercase()) {
"POST" -> {
val mediaType = "application/json".toMediaType()
val body = "{}".toRequestBody(mediaType)
requestBuilder.post(body)
}
"PUT" -> {
val mediaType = "application/json".toMediaType()
val body = "{}".toRequestBody(mediaType)
requestBuilder.put(body)
}
"DELETE" -> requestBuilder.delete()
}
val response = client.newCall(requestBuilder.build()).execute()
if (response.isSuccessful) {
return@withContext response.body?.string()
} else {
return@withContext null
}
} catch (e: Exception) {
println("Request with Headers Error: ${e.message}")
return@withContext null
}
}
}
// 3. Advanced HTTP Operations
class AdvancedHttpExample(private val context: Context) {
private val client = OkHttpClient()
// Multipart upload
suspend fun uploadMultipart(
url: String,
file: File,
fileParamName: String = "file",
params: Map<String, String> = emptyMap()
): String? = withContext(Dispatchers.IO) {
try {
val requestBody = MultipartBody.Builder()
.setType(MultipartBody.FORM)
// Add parameters
params.forEach { (key, value) ->
requestBody.addFormDataPart(key, value)
}
// Add file
val mediaType = "multipart/form-data".toMediaType()
requestBody.addFormDataPart(
fileParamName,
file.name,
file.asRequestBody(mediaType)
)
val request = Request.Builder()
.url(url)
.post(requestBody.build())
.build()
val response = client.newCall(request).execute()
return@withContext response.body?.string()
} catch (e: Exception) {
println("Multipart Upload Error: ${e.message}")
return@withContext null
}
}
// Download file with progress
suspend fun downloadFileWithProgress(
url: String,
outputFile: File,
onProgress: (Long, Long) -> Unit
): Boolean = withContext(Dispatchers.IO) {
try {
val request = Request.Builder().url(url).build()
val response = client.newCall(request).execute()
if (!response.isSuccessful) {
return@withContext false
}
val inputStream = response.body?.byteStream() ?: return@withContext false
val contentLength = response.body?.contentLength() ?: 0
outputFile.outputStream().use { output ->
val buffer = ByteArray(8192)
var bytesRead: Int
var totalBytesRead = 0L
while (inputStream.read(buffer).also { bytesRead = it } != -1) {
output.write(buffer, 0, bytesRead)
totalBytesRead += bytesRead
if (contentLength > 0) {
onProgress(totalBytesRead, contentLength)
}
}
}
return@withContext true
} catch (e: Exception) {
println("Download Error: ${e.message}")
return@withContext false
}
}
// Retry mechanism
suspend fun requestWithRetry(
url: String,
maxRetries: Int = 3,
delayMillis: Long = 1000
): String? = withContext(Dispatchers.IO) {
var lastException: Exception? = null
repeat(maxRetries) { attempt ->
try {
val request = Request.Builder().url(url).build()
val response = client.newCall(request).execute()
if (response.isSuccessful) {
return@withContext response.body?.string()
}
} catch (e: Exception) {
lastException = e
println("Attempt $attempt failed: ${e.message}")
if (attempt < maxRetries - 1) {
delay(delayMillis)
}
}
}
println("All $maxRetries attempts failed")
return@withContext null
}
// Caching configuration
fun createCachedClient(cacheDir: File, cacheSize: Long = 10 * 1024 * 1024): OkHttpClient {
val cache = Cache(cacheDir, cacheSize)
return OkHttpClient.Builder()
.cache(cache)
.build()
}
// Request with timeout
suspend fun requestWithTimeout(
url: String,
timeoutSeconds: Int = 30
): String? = withContext(Dispatchers.IO) {
try {
val client = OkHttpClient.Builder()
.connectTimeout(timeoutSeconds.toLong(), java.util.concurrent.TimeUnit.SECONDS)
.readTimeout(timeoutSeconds.toLong(), java.util.concurrent.TimeUnit.SECONDS)
.build()
val request = Request.Builder().url(url).build()
val response = client.newCall(request).execute()
return@withContext response.body?.string()
} catch (e: Exception) {
println("Timeout Error: ${e.message}")
return@withContext null
}
}
}
// 4. REST API Client
class RestClient(private val baseUrl: String, private val context: Context) {
private val client = OkHttpClient()
suspend fun get(endpoint: String): String? = withContext(Dispatchers.IO) {
try {
val url = "$baseUrl$endpoint"
val request = Request.Builder()
.url(url)
.get()
.build()
val response = client.newCall(request).execute()
if (response.isSuccessful) {
return@withContext response.body?.string()
} else {
return@withContext null
}
} catch (e: Exception) {
println("GET $endpoint Error: ${e.message}")
return@withContext null
}
}
suspend fun post(endpoint: String, data: JSONObject): String? = withContext(Dispatchers.IO) {
try {
val url = "$baseUrl$endpoint"
val mediaType = "application/json".toMediaType()
val body = data.toString().toRequestBody(mediaType)
val request = Request.Builder()
.url(url)
.post(body)
.build()
val response = client.newCall(request).execute()
if (response.isSuccessful) {
return@withContext response.body?.string()
} else {
return@withContext null
}
} catch (e: Exception) {
println("POST $endpoint Error: ${e.message}")
return@withContext null
}
}
suspend fun put(endpoint: String, data: JSONObject): String? = withContext(Dispatchers.IO) {
try {
val url = "$baseUrl$endpoint"
val mediaType = "application/json".toMediaType()
val body = data.toString().toRequestBody(mediaType)
val request = Request.Builder()
.url(url)
.put(body)
.build()
val response = client.newCall(request).execute()
if (response.isSuccessful) {
return@withContext response.body?.string()
} else {
return@withContext null
}
} catch (e: Exception) {
println("PUT $endpoint Error: ${e.message}")
return@withContext null
}
}
suspend fun delete(endpoint: String): Boolean = withContext(Dispatchers.IO) {
try {
val url = "$baseUrl$endpoint"
val request = Request.Builder()
.url(url)
.delete()
.build()
val response = client.newCall(request).execute()
return@withContext response.isSuccessful
} catch (e: Exception) {
println("DELETE $endpoint Error: ${e.message}")
return@withContext false
}
}
}
// Main demonstration
suspend fun demonstrateHTTPRequests(context: Context) {
println("=== Android Kotlin HTTP Request Examples ===\n")
// 1. HttpURLConnection examples
println("--- 1. HttpURLConnection Examples ---")
val httpExample = HttpURLConnectionExample(context)
// Note: Replace with actual API endpoints for testing
// val getResult = httpExample.simpleGetRequest("https://api.example.com/data")
// println("GET Result: $getResult")
// 2. OkHttp examples
println("\n--- 2. OkHttp Examples ---")
val okHttpExample = OkHttpExample(context)
// val okHttpGet = okHttpExample.simpleGet("https://api.example.com/data")
// println("OkHttp GET: $okHttpGet")
// 3. Advanced operations
println("\n--- 3. Advanced HTTP Operations ---")
val advancedExample = AdvancedHttpExample(context)
// 4. REST client
println("\n--- 4. REST API Client ---")
val restClient = RestClient("https://api.example.com", context)
println("\n=== All HTTP Request Examples Completed ===")
}
💻 Download/Upload de Arquivos kotlin
🟡 intermediate
⭐⭐⭐⭐
Baixar e enviar arquivos com rastreamento de progresso, funcionalidade de pausa/retomada e gerenciamento de tarefas em segundo plano
⏱️ 35 min
🏷️ kotlin, android, networking, download, upload
Prerequisites:
Intermediate Kotlin, Storage permissions
// Android Kotlin File Download/Upload Examples
// Using DownloadManager, WorkManager, and OkHttp
import android.app.DownloadManager
import android.content.Context
import android.database.Cursor
import android.net.Uri
import android.webkit.MimeTypeMap
import androidx.work.*
import kotlinx.coroutines.*
import okhttp3.*
import java.io.*
import java.net.HttpURLConnection
import java.net.URL
// 1. DownloadManager (System-managed downloads)
class SystemDownloadExample(private val context: Context) {
private val downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
// Simple download using DownloadManager
fun downloadFile(url: String, title: String, description: String): Long {
val request = DownloadManager.Request(Uri.parse(url)).apply {
setTitle(title)
setDescription(description)
setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI or DownloadManager.Request.NETWORK_MOBILE)
// Set destination
val fileName = URL(url).file.substringAfterLast("/")
val mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(
fileName.substringAfterLast('.')
)
setMimeType(mimeType)
// Save to external storage
setDestinationInExternalFilesDir(
context,
Environment.DIRECTORY_DOWNLOADS,
fileName
)
}
return downloadManager.enqueue(request)
}
// Query download status
fun getDownloadStatus(downloadId: Long): Int {
val query = DownloadManager.Query().setFilterById(downloadId)
val cursor: Cursor = downloadManager.query(query)
var status = -1
if (cursor.moveToFirst()) {
status = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_STATUS))
}
cursor.close()
return status
}
// Get download progress
fun getDownloadProgress(downloadId: Long): Int {
val query = DownloadManager.Query().setFilterById(downloadId)
val cursor: Cursor = downloadManager.query(query)
var progress = 0
if (cursor.moveToFirst()) {
val bytesDownloaded = cursor.getInt(
cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR)
)
val bytesTotal = cursor.getInt(
cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_TOTAL_SIZE_BYTES)
)
if (bytesTotal > 0) {
progress = (bytesDownloaded * 100 / bytesTotal)
}
}
cursor.close()
return progress
}
// Cancel download
fun cancelDownload(downloadId: Long) {
downloadManager.remove(downloadId)
}
}
// 2. Manual Download with Progress
class ManualDownloadExample(private val context: Context) {
// Download file with progress callback
suspend fun downloadFile(
url: String,
outputFile: File,
onProgress: (bytesRead: Long, contentLength: Long) -> Unit
): Boolean = withContext(Dispatchers.IO) {
var connection: HttpURLConnection? = null
try {
val urlObj = URL(url)
connection = urlObj.openConnection() as HttpURLConnection
connection.connectTimeout = 10000
connection.readTimeout = 10000
connection.requestMethod = "GET"
val responseCode = connection.responseCode
if (responseCode != HttpURLConnection.HTTP_OK) {
return@withContext false
}
val contentLength = connection.contentLengthLong
val inputStream = connection.inputStream
val outputStream = FileOutputStream(outputFile)
val buffer = ByteArray(8192)
var bytesRead: Int
var totalBytesRead = 0L
while (inputStream.read(buffer).also { bytesRead = it } != -1) {
outputStream.write(buffer, 0, bytesRead)
totalBytesRead += bytesRead
onProgress(totalBytesRead, contentLength)
}
outputStream.flush()
outputStream.close()
inputStream.close()
return@withContext true
} catch (e: Exception) {
println("Download Error: ${e.message}")
return@withContext false
} finally {
connection?.disconnect()
}
}
// Download with OkHttp
private val okHttpClient = OkHttpClient()
suspend fun downloadWithOkHttp(
url: String,
outputFile: File,
onProgress: (bytesRead: Long, contentLength: Long) -> Unit
): Boolean = withContext(Dispatchers.IO) {
try {
val request = Request.Builder().url(url).build()
val response = okHttpClient.newCall(request).execute()
if (!response.isSuccessful) {
return@withContext false
}
val inputStream = response.body?.byteStream() ?: return@withContext false
val contentLength = response.body?.contentLength() ?: 0
outputFile.outputStream().use { output ->
val buffer = ByteArray(8192)
var bytesRead: Int
var totalBytesRead = 0L
while (inputStream.read(buffer).also { bytesRead = it } != -1) {
output.write(buffer, 0, bytesRead)
totalBytesRead += bytesRead
onProgress(totalBytesRead, contentLength)
}
}
return@withContext true
} catch (e: Exception) {
println("OkHttp Download Error: ${e.message}")
return@withContext false
}
}
// Resumeable download
data class DownloadState(
val url: String,
val outputFile: File,
val downloadedBytes: Long = 0
)
suspend fun resumeableDownload(
state: DownloadState,
onProgress: (bytesRead: Long, contentLength: Long) -> Unit
): Boolean = withContext(Dispatchers.IO) {
var connection: HttpURLConnection? = null
try {
val urlObj = URL(state.url)
connection = urlObj.openConnection() as HttpURLConnection
// Set range header for resume
if (state.downloadedBytes > 0 && state.outputFile.exists()) {
connection.setRequestProperty(
"Range",
"bytes=${state.downloadedBytes}-"
)
}
connection.connectTimeout = 10000
connection.readTimeout = 10000
val responseCode = connection.responseCode
if (responseCode !in listOf(HttpURLConnection.HTTP_OK, HttpURLConnection.HTTP_PARTIAL)) {
return@withContext false
}
val contentLength = if (responseCode == HttpURLConnection.HTTP_PARTIAL) {
connection.contentLength + state.downloadedBytes
} else {
state.downloadedBytes
}
val inputStream = connection.inputStream
val outputStream = if (state.downloadedBytes > 0) {
FileOutputStream(state.outputFile, true)
} else {
FileOutputStream(state.outputFile)
}
val buffer = ByteArray(8192)
var bytesRead: Int
var totalBytesRead = state.downloadedBytes
while (inputStream.read(buffer).also { bytesRead = it } != -1) {
outputStream.write(buffer, 0, bytesRead)
totalBytesRead += bytesRead
onProgress(totalBytesRead, contentLength)
}
outputStream.flush()
outputStream.close()
inputStream.close()
return@withContext true
} catch (e: Exception) {
println("Resumeable Download Error: ${e.message}")
return@withContext false
} finally {
connection?.disconnect()
}
}
}
// 3. File Upload
class FileUploadExample(private val context: Context) {
private val client = OkHttpClient()
// Upload single file
suspend fun uploadFile(
url: String,
file: File,
paramName: String = "file",
additionalParams: Map<String, String> = emptyMap()
): String? = withContext(Dispatchers.IO) {
try {
val requestBody = MultipartBody.Builder()
.setType(MultipartBody.FORM)
// Add additional parameters
additionalParams.forEach { (key, value) ->
requestBody.addFormDataPart(key, value)
}
// Add file
val mimeType = getMimeType(file)
requestBody.addFormDataPart(
paramName,
file.name,
file.asRequestBody(mimeType.toMediaTypeOrNull())
)
val request = Request.Builder()
.url(url)
.post(requestBody.build())
.build()
val response = client.newCall(request).execute()
if (response.isSuccessful) {
return@withContext response.body?.string()
} else {
return@withContext null
}
} catch (e: Exception) {
println("Upload Error: ${e.message}")
return@withContext null
}
}
// Upload multiple files
suspend fun uploadMultipleFiles(
url: String,
files: List<File>,
paramName: String = "files"
): String? = withContext(Dispatchers.IO) {
try {
val requestBody = MultipartBody.Builder()
.setType(MultipartBody.FORM)
files.forEach { file ->
val mimeType = getMimeType(file)
requestBody.addFormDataPart(
paramName,
file.name,
file.asRequestBody(mimeType.toMediaTypeOrNull())
)
}
val request = Request.Builder()
.url(url)
.post(requestBody.build())
.build()
val response = client.newCall(request).execute()
if (response.isSuccessful) {
return@withContext response.body?.string()
} else {
return@withContext null
}
} catch (e: Exception) {
println("Multiple Upload Error: ${e.message}")
return@withContext null
}
}
// Upload with progress
suspend fun uploadFileWithProgress(
url: String,
file: File,
paramName: String = "file",
onProgress: (bytesWritten: Long, contentLength: Long) -> Unit
): Boolean = withContext(Dispatchers.IO) {
try {
// Create counting request body
val countingRequestBody = object : RequestBody() {
override fun contentType(): okhttp3.MediaType? {
return getMimeType(file).toMediaTypeOrNull()
}
override fun writeTo(sink: BufferedSink) {
val source = file.source().buffer()
val contentLength = file.length()
var bytesWritten = 0L
val buffer = ByteArray(8192)
var bytesRead: Int
while (source.read(buffer).also { bytesRead = it } != -1) {
sink.write(buffer, 0, bytesRead)
bytesWritten += bytesRead
onProgress(bytesWritten, contentLength)
}
}
override fun contentLength(): Long = file.length()
}
val requestBody = MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart(paramName, file.name, countingRequestBody)
.build()
val request = Request.Builder()
.url(url)
.post(requestBody)
.build()
val response = client.newCall(request).execute()
return@withContext response.isSuccessful
} catch (e: Exception) {
println("Upload with Progress Error: ${e.message}")
return@withContext false
}
}
private fun getMimeType(file: File): String {
val extension = file.extension.lowercase()
return when (extension) {
"jpg", "jpeg" -> "image/jpeg"
"png" -> "image/png"
"gif" -> "image/gif"
"pdf" -> "application/pdf"
"txt" -> "text/plain"
"json" -> "application/json"
"mp4" -> "video/mp4"
"mp3" -> "audio/mpeg"
else -> "application/octet-stream"
}
}
}
// 4. Background Upload with WorkManager
class UploadWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {
override suspend fun doWork(): Result {
val fileUrl = inputData.getString("fileUrl") ?: return Result.failure()
val uploadUrl = inputData.getString("uploadUrl") ?: return Result.failure()
val file = File(fileUrl)
val uploader = FileUploadExample(applicationContext)
val result = uploader.uploadFile(uploadUrl, file)
return if (result != null) {
Result.success(workDataOf("response" to result))
} else {
Result.failure()
}
}
companion object {
fun enqueueUpload(context: Context, file: File, uploadUrl: String): UUID {
val data = workDataOf(
"fileUrl" to file.absolutePath,
"uploadUrl" to uploadUrl
)
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.setRequiresBatteryNotLow(true)
.build()
val uploadRequest = OneTimeWorkRequestBuilder<UploadWorker>()
.setConstraints(constraints)
.setInputData(data)
.build()
WorkManager.getInstance(context).enqueue(uploadRequest)
return uploadRequest.id
}
}
}
// Main demonstration
suspend fun demonstrateFileDownloadUpload(context: Context) {
println("=== Android Kotlin File Download/Upload Examples ===\n")
// 1. System download
println("--- 1. System Download (DownloadManager) ---")
val systemDownload = SystemDownloadExample(context)
// Note: Replace with actual URL
// val downloadId = systemDownload.downloadFile(
// url = "https://example.com/file.pdf",
// title = "File Download",
// description = "Downloading file..."
// )
// 2. Manual download with progress
println("\n--- 2. Manual Download with Progress ---")
val manualDownload = ManualDownloadExample(context)
// val outputFile = File(context.getExternalFilesDir(null), "downloaded_file.pdf")
// manualDownload.downloadFile(
// url = "https://example.com/file.pdf",
// outputFile = outputFile,
// onProgress = { bytesRead, totalBytes ->
// val progress = (bytesRead * 100 / totalBytes).toInt()
// println("Download progress: $progress%")
// }
// )
// 3. File upload
println("\n--- 3. File Upload ---")
val uploadExample = FileUploadExample(context)
// val fileToUpload = File(context.filesDir, "upload.txt")
// uploadExample.uploadFile(
// url = "https://example.com/upload",
// file = fileToUpload,
// additionalParams = mapOf("userId" to "123")
// )
println("\n=== All File Download/Upload Examples Completed ===")
}
💻 Conexão WebSocket kotlin
🟡 intermediate
⭐⭐⭐⭐
Estabelecer conexões WebSocket, enviar/receber mensagens e gerenciar ciclo de vida da conexão
⏱️ 30 min
🏷️ kotlin, android, networking, websocket
Prerequisites:
Intermediate Kotlin, OkHttp library
// Android Kotlin WebSocket Examples
// Using OkHttp WebSocket and Java-WebSocket
import android.content.Context
import kotlinx.coroutines.*
import okhttp3.*
import okio.ByteString
import org.json.JSONObject
import java.util.concurrent.TimeUnit
// 1. Basic WebSocket with OkHttp
class BasicWebSocketExample(private val context: Context) {
private val client = OkHttpClient.Builder()
.readTimeout(0, TimeUnit.MILLISECONDS)
.build()
private var webSocket: WebSocket? = null
// Connect to WebSocket
fun connect(url: String) {
val request = Request.Builder()
.url(url)
.build()
val listener = object : WebSocketListener() {
override fun onOpen(ws: WebSocket, response: Response) {
println("WebSocket Connected")
println("Server response: ${response.message}")
// Send welcome message
ws.send("Hello from Android!")
}
override fun onMessage(ws: WebSocket, text: String) {
println("Received text: $text")
}
override fun onMessage(ws: WebSocket, bytes: ByteString) {
println("Received bytes: ${bytes.hex()}")
}
override fun onClosing(ws: WebSocket, code: Int, reason: String) {
println("Closing: $code $reason")
ws.close(code, reason)
}
override fun onClosed(ws: WebSocket, code: Int, reason: String) {
println("WebSocket Closed: $code $reason")
}
override fun onFailure(ws: WebSocket, t: Throwable, response: Response?) {
println("WebSocket Error: ${t.message}")
}
}
webSocket = client.newWebSocket(request, listener)
}
// Send text message
fun sendMessage(message: String) {
webSocket?.send(message)
}
// Send JSON message
fun sendJson(json: JSONObject) {
webSocket?.send(json.toString())
}
// Send binary data
fun sendBinary(data: ByteArray) {
webSocket?.send(ByteString.of(*data))
}
// Close connection
fun close() {
webSocket?.close(1000, "Goodbye!")
webSocket = null
}
}
// 2. Advanced WebSocket with Reconnection
class AdvancedWebSocketExample(
private val context: Context,
private val url: String
) {
private val client = OkHttpClient.Builder()
.readTimeout(0, TimeUnit.MILLISECONDS)
.build()
private var webSocket: WebSocket? = null
private var isConnected = false
private var reconnectAttempts = 0
private val maxReconnectAttempts = 5
private val reconnectDelay = 3000L // 3 seconds
private val messageQueue = mutableListOf<String>()
// Message callback interface
interface WebSocketCallback {
fun onConnected()
fun onMessage(text: String)
fun onMessage(bytes: ByteString)
fun onDisconnected()
fun onError(error: String)
}
private var callback: WebSocketCallback? = null
fun setCallback(cb: WebSocketCallback) {
this.callback = cb
}
// Connect with auto-reconnect
fun connect() {
val request = Request.Builder()
.url(url)
.addHeader("Origin", context.packageName)
.build()
val listener = object : WebSocketListener() {
override fun onOpen(ws: WebSocket, response: Response) {
println("WebSocket Connected")
isConnected = true
reconnectAttempts = 0
callback?.onConnected()
// Send queued messages
synchronized(messageQueue) {
messageQueue.forEach { message ->
ws.send(message)
}
messageQueue.clear()
}
}
override fun onMessage(ws: WebSocket, text: String) {
println("Received: $text")
callback?.onMessage(text)
}
override fun onMessage(ws: WebSocket, bytes: ByteString) {
println("Received bytes: ${bytes.hex()}")
callback?.onMessage(bytes)
}
override fun onClosing(ws: WebSocket, code: Int, reason: String) {
println("Closing: $code $reason")
}
override fun onClosed(ws: WebSocket, code: Int, reason: String) {
println("WebSocket Closed: $code $reason")
isConnected = false
callback?.onDisconnected()
// Attempt reconnection
attemptReconnect()
}
override fun onFailure(ws: WebSocket, t: Throwable, response: Response?) {
println("WebSocket Error: ${t.message}")
isConnected = false
callback?.onError(t.message ?: "Unknown error")
// Attempt reconnection
attemptReconnect()
}
}
webSocket = client.newWebSocket(request, listener)
}
// Attempt reconnection
private fun attemptReconnect() {
if (reconnectAttempts < maxReconnectAttempts) {
reconnectAttempts++
CoroutineScope(Dispatchers.IO).launch {
delay(reconnectDelay)
println("Reconnecting... Attempt $reconnectAttempts")
connect()
}
} else {
println("Max reconnection attempts reached")
}
}
// Send message with queueing
fun sendMessage(message: String) {
if (isConnected) {
webSocket?.send(message)
} else {
// Queue message for later
synchronized(messageQueue) {
messageQueue.add(message)
}
println("Message queued: $message")
}
}
// Close connection
fun close() {
reconnectAttempts = maxReconnectAttempts // Stop reconnection
webSocket?.close(1000, "User closing")
webSocket = null
isConnected = false
}
}
// 3. WebSocket Chat Example
class ChatWebSocket(private val context: Context) {
private val client = OkHttpClient.Builder()
.readTimeout(0, TimeUnit.MILLISECONDS)
.build()
private var webSocket: WebSocket? = null
data class ChatMessage(
val type: String, // "join", "message", "leave"
val username: String,
val content: String,
val timestamp: Long = System.currentTimeMillis()
)
interface ChatCallback {
fun onMessage(message: ChatMessage)
fun onUserJoined(username: String)
fun onUserLeft(username: String)
fun onConnectionStatus(connected: Boolean)
}
private var callback: ChatCallback? = null
fun setCallback(cb: ChatCallback) {
this.callback = cb
}
// Connect to chat server
fun connect(serverUrl: String, username: String) {
val request = Request.Builder()
.url(serverUrl)
.build()
val listener = object : WebSocketListener() {
override fun onOpen(ws: WebSocket, response: Response) {
println("Chat Connected as: $username")
callback?.onConnectionStatus(true)
// Send join message
val joinMessage = ChatMessage(
type = "join",
username = username,
content = ""
)
ws.send(toJson(joinMessage))
}
override fun onMessage(ws: WebSocket, text: String) {
val message = fromJson(text)
message?.let {
when (it.type) {
"join" -> callback?.onUserJoined(it.username)
"leave" -> callback?.onUserLeft(it.username)
"message" -> callback?.onMessage(it)
}
}
}
override fun onClosed(ws: WebSocket, code: Int, reason: String) {
println("Chat Closed")
callback?.onConnectionStatus(false)
}
override fun onFailure(ws: WebSocket, t: Throwable, response: Response?) {
println("Chat Error: ${t.message}")
callback?.onConnectionStatus(false)
}
}
webSocket = client.newWebSocket(request, listener)
}
// Send chat message
fun sendMessage(username: String, content: String) {
val message = ChatMessage(
type = "message",
username = username,
content = content
)
webSocket?.send(toJson(message))
}
// Leave chat
fun leave(username: String) {
val leaveMessage = ChatMessage(
type = "leave",
username = username,
content = ""
)
webSocket?.send(toJson(leaveMessage))
// Close connection
webSocket?.close(1000, "User leaving")
webSocket = null
}
private fun toJson(message: ChatMessage): String {
val json = JSONObject()
json.put("type", message.type)
json.put("username", message.username)
json.put("content", message.content)
json.put("timestamp", message.timestamp)
return json.toString()
}
private fun fromJson(json: String): ChatMessage? {
return try {
val obj = JSONObject(json)
ChatMessage(
type = obj.optString("type"),
username = obj.optString("username"),
content = obj.optString("content"),
timestamp = obj.optLong("timestamp", System.currentTimeMillis())
)
} catch (e: Exception) {
null
}
}
}
// 4. WebSocket Heartbeat/Ping
class HeartbeatWebSocket(
private val context: Context,
private val url: String
) {
private val client = OkHttpClient.Builder()
.readTimeout(0, TimeUnit.MILLISECONDS)
.pingInterval(30, TimeUnit.SECONDS) // Send ping every 30 seconds
.build()
private var webSocket: WebSocket? = null
private var heartbeatJob: Job? = null
// Connect with heartbeat
fun connect() {
val request = Request.Builder()
.url(url)
.build()
val listener = object : WebSocketListener() {
override fun onOpen(ws: WebSocket, response: Response) {
println("Heartbeat WebSocket Connected")
startHeartbeat(ws)
}
override fun onMessage(ws: WebSocket, text: String) {
println("Received: $text")
}
override fun onClosing(ws: WebSocket, code: Int, reason: String) {
stopHeartbeat()
}
override fun onClosed(ws: WebSocket, code: Int, reason: String) {
stopHeartbeat()
}
override fun onFailure(ws: WebSocket, t: Throwable, response: Response?) {
stopHeartbeat()
}
}
webSocket = client.newWebSocket(request, listener)
}
// Start heartbeat
private fun startHeartbeat(ws: WebSocket) {
heartbeatJob = CoroutineScope(Dispatchers.IO).launch {
while (isActive) {
delay(15000) // Send custom heartbeat every 15 seconds
val heartbeat = JSONObject().apply {
put("type", "heartbeat")
put("timestamp", System.currentTimeMillis())
}
ws.send(heartbeat.toString())
println("Heartbeat sent")
}
}
}
// Stop heartbeat
private fun stopHeartbeat() {
heartbeatJob?.cancel()
heartbeatJob = null
}
// Close connection
fun close() {
stopHeartbeat()
webSocket?.close(1000, "Closing")
webSocket = null
}
}
// 5. WebSocket Manager (Singleton)
class WebSocketManager private constructor(private val context: Context) {
companion object {
@Volatile
private var instance: WebSocketManager? = null
fun getInstance(context: Context): WebSocketManager {
return instance ?: synchronized(this) {
instance ?: WebSocketManager(context.applicationContext).also { instance = it }
}
}
}
private val connections = mutableMapOf<String, WebSocket>()
data class WebSocketConfig(
val url: String,
val key: String = url,
val autoReconnect: Boolean = true,
val reconnectDelay: Long = 3000L
)
// Connect with config
fun connect(config: WebSocketConfig, listener: WebSocketListener) {
val client = OkHttpClient.Builder()
.readTimeout(0, TimeUnit.MILLISECONDS)
.build()
val request = Request.Builder()
.url(config.url)
.build()
val ws = client.newWebSocket(request, listener)
connections[config.key] = ws
}
// Send message
fun send(key: String, message: String) {
connections[key]?.send(message)
}
// Close specific connection
fun close(key: String) {
connections[key]?.close(1000, "Closing")
connections.remove(key)
}
// Close all connections
fun closeAll() {
connections.values.forEach { it.close(1000, "Closing all") }
connections.clear()
}
}
// Main demonstration
fun demonstrateWebSocket(context: Context) {
println("=== Android Kotlin WebSocket Examples ===\n")
// 1. Basic WebSocket
println("--- 1. Basic WebSocket ---")
val basicWs = BasicWebSocketExample(context)
// basicWs.connect("wss://echo.websocket.org")
// basicWs.sendMessage("Hello WebSocket!")
// 2. Advanced WebSocket with reconnection
println("\n--- 2. Advanced WebSocket with Reconnection ---")
val advancedWs = AdvancedWebSocketExample(context, "wss://echo.websocket.org")
// advancedWs.setCallback(object : AdvancedWebSocketExample.WebSocketCallback {
// override fun onConnected() { println("Connected!") }
// override fun onMessage(text: String) { println("Message: $text") }
// override fun onMessage(bytes: ByteString) { println("Bytes received") }
// override fun onDisconnected() { println("Disconnected") }
// override fun onError(error: String) { println("Error: $error") }
// })
// advancedWs.connect()
// 3. Chat WebSocket
println("\n--- 3. Chat WebSocket ---")
val chatWs = ChatWebSocket(context)
// chatWs.connect("wss://chat.example.com", "User123")
// chatWs.sendMessage("User123", "Hello everyone!")
// 4. WebSocket Manager
println("\n--- 4. WebSocket Manager ---")
val wsManager = WebSocketManager.getInstance(context)
// wsManager.connect(
// WebSocketManager.WebSocketConfig("wss://echo.websocket.org"),
// listener
// )
println("\n=== All WebSocket Examples Completed ===")
}