Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7a7a4811 authored by Moez Bhatti's avatar Moez Bhatti
Browse files

Add ability to save image to gallery

parent 7e7ee23d
Loading
Loading
Loading
Loading
+97 −0
Original line number Diff line number Diff line
package repository

import android.content.ContentResolver
import android.content.ContentUris
import android.content.ContentValues
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Matrix
import android.net.Uri
import android.provider.MediaStore
import android.provider.MediaStore.Images
import util.tryOrNull
import javax.inject.Inject

class ImageRepostoryImpl @Inject constructor(private val context: Context) : ImageRepository {

    override fun saveImage(uri: Uri) {
        val bitmap = tryOrNull { MediaStore.Images.Media.getBitmap(context.contentResolver, uri) }
        insertImage(context.contentResolver, bitmap, "title", "description")
    }

    /**
     * Modified from [android.provider.MediaStore.Images.Media.insertImage] to add date fields so
     * that the saved image is put at the start of the gallery
     */
    private fun insertImage(cr: ContentResolver, source: Bitmap?, title: String, description: String): String? {

        val values = ContentValues()
        values.put(Images.Media.TITLE, title)
        values.put(Images.Media.DISPLAY_NAME, title)
        values.put(Images.Media.DESCRIPTION, description)
        values.put(Images.Media.MIME_TYPE, "image/jpeg")

        // Add the date meta data to ensure the image is added at the front of the gallery
        values.put(Images.Media.DATE_ADDED, System.currentTimeMillis() / 1000)
        values.put(Images.Media.DATE_TAKEN, System.currentTimeMillis())

        var uri: Uri? = null

        try {
            uri = cr.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)

            if (source != null) {
                cr.openOutputStream(uri).use { imageOut ->
                    source.compress(Bitmap.CompressFormat.JPEG, 100, imageOut)
                }

                val id = ContentUris.parseId(uri)
                // Wait until MINI_KIND thumbnail is generated.
                val miniThumb = Images.Thumbnails.getThumbnail(cr, id, Images.Thumbnails.MINI_KIND, null)
                // This is for backward compatibility.
                storeThumbnail(cr, miniThumb, id, 50f, 50f, Images.Thumbnails.MICRO_KIND)
            } else {
                cr.delete(uri, null, null)
                uri = null
            }
        } catch (e: Exception) {
            if (uri != null) {
                cr.delete(uri, null, null)
                uri = null
            }
        }

        return uri?.toString()
    }

    /**
     * Modified from [android.provider.MediaStore.Images.Media.insertImage] to add date fields so
     * that the saved image is put at the start of the gallery
     */
    private fun storeThumbnail(cr: ContentResolver, source: Bitmap, id: Long, width: Float, height: Float, kind: Int): Bitmap? {
        val matrix = Matrix()

        val scaleX = width / source.width
        val scaleY = height / source.height

        matrix.setScale(scaleX, scaleY)

        val thumb = Bitmap.createBitmap(source, 0, 0, source.width, source.height, matrix, true)

        val values = ContentValues(4)
        values.put(Images.Thumbnails.KIND, kind)
        values.put(Images.Thumbnails.IMAGE_ID, id.toInt())
        values.put(Images.Thumbnails.HEIGHT, thumb.height)
        values.put(Images.Thumbnails.WIDTH, thumb.width)

        val url = cr.insert(Images.Thumbnails.EXTERNAL_CONTENT_URI, values)

        return tryOrNull {
            val thumbOut = cr.openOutputStream(url)
            thumb.compress(Bitmap.CompressFormat.JPEG, 100, thumbOut)
            thumbOut.close()
            thumb
        }
    }

}
+3 −5
Original line number Diff line number Diff line
@@ -18,15 +18,14 @@
 */
package interactor

import android.content.Context
import android.provider.MediaStore
import androidx.net.toUri
import io.reactivex.Flowable
import repository.ImageRepository
import repository.MessageRepository
import javax.inject.Inject

class SaveImage @Inject constructor(
        private val context: Context,
        private val imageRepository: ImageRepository,
        private val messageRepo: MessageRepository
) : Interactor<Long>() {

@@ -35,8 +34,7 @@ class SaveImage @Inject constructor(
                .map { partId -> messageRepo.getPart(partId) }
                .map { part -> part.image }
                .map { uriString -> uriString.toUri() }
                .map { uri -> MediaStore.Images.Media.getBitmap(context.contentResolver, uri) }
                .doOnNext { bitmap -> MediaStore.Images.Media.insertImage(context.contentResolver, bitmap, "title", "description") }
                .doOnNext { uri -> imageRepository.saveImage(uri) }
    }

}
 No newline at end of file
+9 −0
Original line number Diff line number Diff line
package repository

import android.net.Uri

interface ImageRepository {

    fun saveImage(uri: Uri)

}
 No newline at end of file
+5 −0
Original line number Diff line number Diff line
@@ -49,6 +49,8 @@ import mapper.CursorToRecipienImpl
import mapper.CursorToRecipient
import repository.ContactRepository
import repository.ContactRepositoryImpl
import repository.ImageRepository
import repository.ImageRepostoryImpl
import repository.MessageRepository
import repository.MessageRepositoryImpl
import repository.SyncRepository
@@ -120,6 +122,9 @@ class AppModule(private var application: Application) {
    @Provides
    fun provideContactRepository(repository: ContactRepositoryImpl): ContactRepository = repository

    @Provides
    fun provideImageRepository(repository: ImageRepostoryImpl): ImageRepository = repository

    @Provides
    fun provideMessageRepository(repository: MessageRepositoryImpl): MessageRepository = repository

+2 −4
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
<?xml version="1.0" encoding="utf-8"?><!--
  ~ Copyright (C) 2017 Moez Bhatti <moez.bhatti@gmail.com>
  ~
  ~ This file is part of QKSMS.
@@ -21,7 +20,6 @@

    <item
        android:id="@+id/save"
        android:title="@string/menu_save"
        android:visible="false" />
        android:title="@string/menu_save" />

</menu>
 No newline at end of file