Skip to content

Commit 3103bd5

Browse files
authored
Compression for single image selection (#17)
Compression for single image selection - Fixed permission issue in document selection
1 parent 60c9373 commit 3103bd5

File tree

11 files changed

+120
-33
lines changed

11 files changed

+120
-33
lines changed

README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ Lassi is simplest way to pick media (either image, video, audio or doc)
3838
```groovy
3939
dependencies {
4040
...
41-
implementation 'com.github.Mindinventory:Lassi:0.1.3'
41+
implementation 'com.github.Mindinventory:Lassi:0.1.4'
4242
}
4343
```
4444
@@ -53,6 +53,7 @@ Lassi is simplest way to pick media (either image, video, audio or doc)
5353
.setMaxCount(5)
5454
.setGridSize(3)
5555
.setMediaType(MediaType.VIDEO) // MediaType : VIDEO IMAGE, AUDIO OR DOC
56+
.setCompressionRation(10) // compress image for single item selection (can be 0 to 100)
5657
.setMinTime(15) // for MediaType.VIDEO only
5758
.setMaxTime(30) // for MediaType.VIDEO only
5859
.setSupportedFileTypes("mp4", "mkv", "webm", "avi", "flv", "3gp") // Filter by limited media format (Optional)

app/src/main/java/com/lassi/app/MainActivity.kt

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ class MainActivity : AppCompatActivity(), View.OnClickListener {
5151
.setProgressBarColor(R.color.colorAccent)
5252
.setCropType(CropImageView.CropShape.OVAL)
5353
.setCropAspectRatio(1, 1)
54+
.setCompressionRation(10)
5455
.enableActualCircleCrop()
5556
.setSupportedFileTypes("jpg", "jpeg", "png", "webp", "gif")
5657
.enableFlip()

lassi/build.gradle

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ android {
1212
defaultConfig {
1313
minSdkVersion 17
1414
targetSdkVersion 29
15-
versionCode 13
16-
versionName "0.1.3"
15+
versionCode 14
16+
versionName "0.1.4"
1717
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
1818
vectorDrawables.useSupportLibrary = true
1919
}

lassi/src/main/java/com/lassi/common/utils/CropUtils.kt

+25-15
Original file line numberDiff line numberDiff line change
@@ -17,26 +17,33 @@ object CropUtils {
1717
fun beginCrop(activity: FragmentActivity, source: Uri) {
1818
with(LassiConfig.getConfig()) {
1919
CropImage.activity(source)
20-
.setGuidelines(CropImageView.Guidelines.ON)
21-
.setOutputCompressQuality(70)
22-
.setCropShape(cropType)
23-
.setAspectRatio(cropAspectRatio)
24-
.setOutputUri(createDirectory(activity))
25-
.setAllowRotation(enableRotateImage)
26-
.setAllowFlipping(enableFlipImage)
27-
.start(activity)
20+
.setGuidelines(CropImageView.Guidelines.ON)
21+
.setOutputCompressQuality((100 - compressionRation))
22+
.setCropShape(cropType)
23+
.setAspectRatio(cropAspectRatio)
24+
.setOutputUri(createDirectory(activity))
25+
.setAllowRotation(enableRotateImage)
26+
.setAllowFlipping(enableFlipImage)
27+
.start(activity)
2828
}
2929
}
3030

3131
private fun getApplicationName(context: Context): String {
3232
val applicationInfo = context.applicationInfo
3333
val stringId = applicationInfo.labelRes
34-
return if (stringId == 0) applicationInfo.nonLocalizedLabel.toString() else context.getString(stringId)
34+
return if (stringId == 0) applicationInfo.nonLocalizedLabel.toString() else context.getString(
35+
stringId
36+
)
37+
}
38+
39+
private fun getPath(context: Context): String {
40+
return Environment.getExternalStorageDirectory().absolutePath + File.separator + getApplicationName(
41+
context
42+
)
3543
}
3644

3745
private fun createDirectory(context: Context): Uri? {
38-
val path = Environment.getExternalStorageDirectory().absolutePath + File.separator + getApplicationName(context)
39-
path.let {
46+
getPath(context).let {
4047
val storageDir = File(it)
4148
if (!storageDir.exists()) {
4249
storageDir.mkdirs()
@@ -70,12 +77,15 @@ object CropUtils {
7077
// Create an image file name
7178
val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(Date())
7279
// val storageDir: File? = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)
73-
val storageDir = Environment.getExternalStorageDirectory().absolutePath + File.separator + getApplicationName(context)
80+
val storageDir =
81+
Environment.getExternalStorageDirectory().absolutePath + File.separator + getApplicationName(
82+
context
83+
)
7484

7585
return File.createTempFile(
76-
"IMG-${timeStamp}_", /* prefix */
77-
".jpeg", /* suffix */
78-
File(storageDir) /* directory */
86+
"IMG-${timeStamp}_", /* prefix */
87+
".jpeg", /* suffix */
88+
File(storageDir) /* directory */
7989
)
8090
}
8191
}

lassi/src/main/java/com/lassi/data/media/MediaDataRepository.kt lassi/src/main/java/com/lassi/data/media/MediaRepositoryImpl.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import java.io.File
1616
import java.util.*
1717
import kotlin.collections.ArrayList
1818

19-
class MediaDataRepository(private val context: Context) : MediaRepository {
19+
class MediaRepositoryImpl(private val context: Context) : MediaRepository {
2020

2121
private val minTimeInMillis = LassiConfig.getConfig().minTime * 1000L
2222
private val maxTimeInMillis = LassiConfig.getConfig().maxTime * 1000L

lassi/src/main/java/com/lassi/domain/media/LassiConfig.kt

+3-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ data class LassiConfig(
3030
var cropAspectRatio: AspectRatio? = null,
3131
var enableFlipImage: Boolean = false,
3232
var enableRotateImage: Boolean = false,
33-
var enableActualCircleCrop: Boolean = false
33+
var enableActualCircleCrop: Boolean = false,
34+
var compressionRation: Int = 0
3435
) : Parcelable {
3536
companion object {
3637

@@ -57,6 +58,7 @@ data class LassiConfig(
5758
enableFlipImage = lassiConfig.enableFlipImage
5859
enableRotateImage = lassiConfig.enableRotateImage
5960
enableActualCircleCrop = lassiConfig.enableActualCircleCrop
61+
compressionRation = lassiConfig.compressionRation
6062
}
6163
}
6264

lassi/src/main/java/com/lassi/presentation/builder/Lassi.kt

+13
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,19 @@ class Lassi(private val context: Context) {
202202
return this
203203
}
204204

205+
/**
206+
* Set compression ration between 0 to 100 (Only for single image selection)
207+
*/
208+
fun setCompressionRation(compressionRation: Int): Lassi {
209+
val compression = if (compressionRation > 100) {
210+
100
211+
} else {
212+
compressionRation
213+
}
214+
lassiConfig.compressionRation = compression
215+
return this
216+
}
217+
205218
/**
206219
* Start LassiMediaPickerActivity with config
207220
*/

lassi/src/main/java/com/lassi/presentation/docs/DocsFragment.kt

+68-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
11
package com.lassi.presentation.docs
22

3+
import android.Manifest
34
import android.app.Activity
45
import android.content.Intent
6+
import android.content.pm.PackageManager
57
import android.graphics.PorterDuff
8+
import android.net.Uri
9+
import android.os.Build
610
import android.os.Bundle
11+
import android.provider.Settings
712
import android.view.Menu
13+
import androidx.appcompat.app.AlertDialog
14+
import androidx.core.app.ActivityCompat
815
import androidx.lifecycle.ViewModelProviders
916
import androidx.recyclerview.widget.GridLayoutManager
1017
import com.lassi.R
@@ -44,6 +51,35 @@ class DocsFragment : LassiBaseViewModelFragment<DocsViewModel>() {
4451
mediaPickerConfig.progressBarColor,
4552
PorterDuff.Mode.MULTIPLY
4653
)
54+
checkPermission()
55+
}
56+
57+
private fun checkPermission() {
58+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
59+
if (ActivityCompat.checkSelfPermission(
60+
requireContext()
61+
, Manifest.permission.READ_EXTERNAL_STORAGE
62+
) != PackageManager.PERMISSION_GRANTED
63+
&& ActivityCompat.checkSelfPermission(
64+
requireContext()
65+
, Manifest.permission.WRITE_EXTERNAL_STORAGE
66+
) != PackageManager.PERMISSION_GRANTED
67+
) {
68+
this.requestPermissions(
69+
arrayOf(
70+
Manifest.permission.READ_EXTERNAL_STORAGE,
71+
Manifest.permission.WRITE_EXTERNAL_STORAGE
72+
)
73+
, KeyUtils.REQUEST_PERMISSIONS_REQUEST_CODE
74+
)
75+
return
76+
}
77+
}
78+
fetchDocs()
79+
}
80+
81+
private fun fetchDocs() {
82+
viewModel.fetchDocs()
4783
}
4884

4985
override fun initLiveDataObservers() {
@@ -62,7 +98,6 @@ class DocsFragment : LassiBaseViewModelFragment<DocsViewModel>() {
6298
}
6399
}
64100

65-
66101
private fun setImageAdapter() {
67102
rvMedia.layoutManager = GridLayoutManager(context, mediaPickerConfig.gridSize)
68103
rvMedia.adapter = mediaAdapter
@@ -97,4 +132,36 @@ class DocsFragment : LassiBaseViewModelFragment<DocsViewModel>() {
97132
activity?.setResult(Activity.RESULT_OK, intent)
98133
activity?.finish()
99134
}
135+
136+
override fun onRequestPermissionsResult(
137+
requestCode: Int, permissions: Array<out String>,
138+
grantResults: IntArray
139+
) {
140+
if (requestCode == KeyUtils.REQUEST_PERMISSIONS_REQUEST_CODE
141+
&& grantResults[0] == PackageManager.PERMISSION_GRANTED
142+
) {
143+
fetchDocs()
144+
} else {
145+
showPermissionDisableAlert()
146+
}
147+
}
148+
149+
private fun showPermissionDisableAlert() {
150+
val alertDialog = AlertDialog.Builder(requireContext())
151+
alertDialog.setMessage(R.string.storage_permission_rational)
152+
alertDialog.setCancelable(false)
153+
alertDialog.setPositiveButton(R.string.ok) { _, _ ->
154+
val intent = Intent().apply {
155+
action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
156+
data = Uri.fromParts("package", activity?.packageName, null)
157+
}
158+
startActivityForResult(intent, KeyUtils.SETTINGS_REQUEST_CODE)
159+
}
160+
alertDialog.setNegativeButton(R.string.cancel) { _, _ ->
161+
activity?.onBackPressed()
162+
}
163+
val permissionDialog = alertDialog.create()
164+
permissionDialog.setCancelable(false)
165+
permissionDialog.show()
166+
}
100167
}

lassi/src/main/java/com/lassi/presentation/docs/DocsViewModel.kt

+1-7
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,7 @@ import java.util.*
1212
class DocsViewModel(private val mediaRepository: MediaRepository) : LassiBaseViewModel() {
1313
var fetchDocsLiveData = MutableLiveData<Response<ArrayList<MiMedia>>>()
1414

15-
override fun loadPage() {
16-
super.loadPage()
17-
fetchDocs()
18-
}
19-
20-
private fun fetchDocs() {
15+
fun fetchDocs() {
2116
fetchDocsLiveData.value = Response.Loading()
2217
mediaRepository.fetchDocs()
2318
.subscribeOn(Schedulers.io())
@@ -28,5 +23,4 @@ class DocsViewModel(private val mediaRepository: MediaRepository) : LassiBaseVie
2823
fetchDocsLiveData.value = Response.Error(it)
2924
}).collect()
3025
}
31-
3226
}

lassi/src/main/java/com/lassi/presentation/docs/DocsViewModelFactory.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ package com.lassi.presentation.docs
33
import android.content.Context
44
import androidx.lifecycle.ViewModel
55
import androidx.lifecycle.ViewModelProvider
6-
import com.lassi.data.media.MediaDataRepository
6+
import com.lassi.data.media.MediaRepositoryImpl
77
import com.lassi.domain.media.MediaRepository
88

99
@Suppress("UNCHECKED_CAST")
1010
class DocsViewModelFactory(val context: Context) : ViewModelProvider.Factory {
11-
private val mediaRepository: MediaRepository = MediaDataRepository(context)
11+
private val mediaRepository: MediaRepository = MediaRepositoryImpl(context)
1212

1313
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
1414
return DocsViewModel(mediaRepository) as T

lassi/src/main/java/com/lassi/presentation/mediadirectory/FolderViewModelFactory.kt

+2-3
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,12 @@ package com.lassi.presentation.mediadirectory
33
import android.content.Context
44
import androidx.lifecycle.ViewModel
55
import androidx.lifecycle.ViewModelProvider
6-
import com.lassi.data.media.MediaDataRepository
6+
import com.lassi.data.media.MediaRepositoryImpl
77
import com.lassi.domain.media.MediaRepository
88

99
@Suppress("UNCHECKED_CAST")
1010
class FolderViewModelFactory(val context: Context) : ViewModelProvider.Factory {
11-
private val mediaRepository: MediaRepository =
12-
MediaDataRepository(context)
11+
private val mediaRepository: MediaRepository = MediaRepositoryImpl(context)
1312

1413
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
1514
return FolderViewModel(mediaRepository) as T

0 commit comments

Comments
 (0)