Loading data/src/main/java/repository/ImageRepostoryImpl.kt 0 → 100644 +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 } } } domain/src/main/java/interactor/SaveImage.kt +3 −5 Original line number Diff line number Diff line Loading @@ -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>() { Loading @@ -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 domain/src/main/java/repository/ImageRepository.kt 0 → 100644 +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 presentation/src/main/java/injection/AppModule.kt +5 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 Loading presentation/src/main/res/menu/gallery.xml +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. Loading @@ -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 Loading
data/src/main/java/repository/ImageRepostoryImpl.kt 0 → 100644 +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 } } }
domain/src/main/java/interactor/SaveImage.kt +3 −5 Original line number Diff line number Diff line Loading @@ -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>() { Loading @@ -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
domain/src/main/java/repository/ImageRepository.kt 0 → 100644 +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
presentation/src/main/java/injection/AppModule.kt +5 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 Loading
presentation/src/main/res/menu/gallery.xml +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. Loading @@ -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