Чат, вложения
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
package core.utils
|
||||
|
||||
import android.app.DownloadManager
|
||||
import android.content.ContentValues
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Environment
|
||||
import android.provider.MediaStore
|
||||
import android.widget.Toast
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.net.URL
|
||||
|
||||
object DownloadUtils {
|
||||
|
||||
suspend fun downloadMedia(context: Context, url: String, fileName: String?) {
|
||||
withContext(Dispatchers.IO) {
|
||||
try {
|
||||
val name = fileName ?: url.substringAfterLast("/")
|
||||
val extension = name.substringAfterLast(".", "jpg")
|
||||
val isImage = extension in listOf("jpg", "jpeg", "png", "webp", "gif")
|
||||
val isVideo = extension in listOf("mp4", "webm", "mkv", "mov")
|
||||
|
||||
if (isImage || isVideo) {
|
||||
saveToGallery(context, url, name, isImage)
|
||||
} else {
|
||||
useDownloadManager(context, url, name)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
withContext(Dispatchers.Main) {
|
||||
Toast.makeText(context, "Ошибка скачивания: ${e.localizedMessage}", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun useDownloadManager(context: Context, url: String, fileName: String) {
|
||||
val request = DownloadManager.Request(Uri.parse(url))
|
||||
.setTitle(fileName)
|
||||
.setDescription("Downloading...")
|
||||
.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
|
||||
.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName)
|
||||
.setAllowedOverMetered(true)
|
||||
.setAllowedOverRoaming(true)
|
||||
|
||||
val downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
|
||||
downloadManager.enqueue(request)
|
||||
|
||||
// Show feedback
|
||||
(context as? android.app.Activity)?.runOnUiThread {
|
||||
Toast.makeText(context, "Загрузка началась: $fileName", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun saveToGallery(context: Context, url: String, fileName: String, isImage: Boolean) {
|
||||
val resolver = context.contentResolver
|
||||
val contentValues = ContentValues().apply {
|
||||
put(MediaStore.MediaColumns.DISPLAY_NAME, fileName)
|
||||
put(MediaStore.MediaColumns.MIME_TYPE, if (isImage) "image/jpeg" else "video/mp4")
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
put(MediaStore.MediaColumns.RELATIVE_PATH, if (isImage) Environment.DIRECTORY_PICTURES else Environment.DIRECTORY_MOVIES)
|
||||
put(MediaStore.MediaColumns.IS_PENDING, 1)
|
||||
}
|
||||
}
|
||||
|
||||
val collection = if (isImage) {
|
||||
MediaStore.Images.Media.EXTERNAL_CONTENT_URI
|
||||
} else {
|
||||
MediaStore.Video.Media.EXTERNAL_CONTENT_URI
|
||||
}
|
||||
|
||||
val uri = resolver.insert(collection, contentValues)
|
||||
uri?.let {
|
||||
URL(url).openStream().use { input ->
|
||||
resolver.openOutputStream(it).use { output ->
|
||||
input.copyTo(output!!)
|
||||
}
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
contentValues.clear()
|
||||
contentValues.put(MediaStore.MediaColumns.IS_PENDING, 0)
|
||||
resolver.update(it, contentValues, null, null)
|
||||
}
|
||||
withContext(Dispatchers.Main) {
|
||||
Toast.makeText(context, "Сохранено в галерею", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,8 +8,16 @@ import java.util.UUID
|
||||
|
||||
fun copyUriToFile(context: Context, uri: Uri): File? {
|
||||
return try {
|
||||
val cursor = context.contentResolver.query(uri, null, null, null, null)
|
||||
val originalName = cursor?.use {
|
||||
if (it.moveToFirst()) {
|
||||
val index = it.getColumnIndex(android.provider.OpenableColumns.DISPLAY_NAME)
|
||||
if (index != -1) it.getString(index) else null
|
||||
} else null
|
||||
} ?: "${UUID.randomUUID()}.tmp"
|
||||
|
||||
val inputStream = context.contentResolver.openInputStream(uri)
|
||||
val file = File(context.cacheDir, "${UUID.randomUUID()}.tmp")
|
||||
val file = File(context.cacheDir, originalName)
|
||||
val outputStream = FileOutputStream(file)
|
||||
inputStream?.use { input ->
|
||||
outputStream.use { output ->
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
package core.utils
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.graphics.Matrix
|
||||
import android.net.Uri
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.util.UUID
|
||||
|
||||
object ImageUtils {
|
||||
fun compressImage(context: Context, uri: Uri, maxWidth: Int = 1280, maxHeight: Int = 1280, quality: Int = 80): File? {
|
||||
return try {
|
||||
val inputStream = context.contentResolver.openInputStream(uri)
|
||||
val options = BitmapFactory.Options().apply {
|
||||
inJustDecodeBounds = true
|
||||
}
|
||||
BitmapFactory.decodeStream(inputStream, null, options)
|
||||
inputStream?.close()
|
||||
|
||||
var inSampleSize = 1
|
||||
if (options.outHeight > maxHeight || options.outWidth > maxWidth) {
|
||||
val halfHeight = options.outHeight / 2
|
||||
val halfWidth = options.outWidth / 2
|
||||
while (halfHeight / inSampleSize >= maxHeight && halfWidth / inSampleSize >= maxWidth) {
|
||||
inSampleSize *= 2
|
||||
}
|
||||
}
|
||||
|
||||
val decodeOptions = BitmapFactory.Options().apply {
|
||||
inSampleSize = inSampleSize
|
||||
}
|
||||
val finalInputStream = context.contentResolver.openInputStream(uri)
|
||||
var bitmap = BitmapFactory.decodeStream(finalInputStream, null, decodeOptions)
|
||||
finalInputStream?.close()
|
||||
|
||||
if (bitmap == null) return null
|
||||
|
||||
// Resize if still too large
|
||||
if (bitmap.width > maxWidth || bitmap.height > maxHeight) {
|
||||
val scale = Math.min(maxWidth.toFloat() / bitmap.width, maxHeight.toFloat() / bitmap.height)
|
||||
val matrix = Matrix().apply { postScale(scale, scale) }
|
||||
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)
|
||||
}
|
||||
|
||||
val file = File(context.cacheDir, "compressed_${UUID.randomUUID()}.jpg")
|
||||
val out = FileOutputStream(file)
|
||||
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, out)
|
||||
out.flush()
|
||||
out.close()
|
||||
|
||||
file
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user