Skip to content

Commit f5b360d

Browse files
[Jetsurvey] Saving the image cleaned up
1 parent 1bb7948 commit f5b360d

File tree

9 files changed

+71
-129
lines changed

9 files changed

+71
-129
lines changed

Jetsurvey/app/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ dependencies {
102102
implementation Libs.AndroidX.Compose.runtime
103103
implementation Libs.AndroidX.Compose.runtimeLivedata
104104

105+
implementation Libs.Accompanist.coil
106+
105107
androidTestImplementation Libs.junit
106108
androidTestImplementation Libs.AndroidX.Test.core
107109
androidTestImplementation Libs.AndroidX.Test.espressoCore

Jetsurvey/app/src/main/AndroidManifest.xml

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,6 @@
2727
android:label="@string/app_name"
2828
android:supportsRtl="true"
2929
android:theme="@style/Theme.Jetsurvey">
30-
<provider
31-
android:name="androidx.core.content.FileProvider"
32-
android:authorities="com.example.compose.jetsurvey.fileprovider"
33-
android:exported="false"
34-
android:grantUriPermissions="true">
35-
<meta-data
36-
android:name="android.support.FILE_PROVIDER_PATHS"
37-
android:resource="@xml/filepaths" />
38-
</provider>
3930
<activity
4031
android:name=".MainActivity"
4132
android:label="@string/app_name">
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright 2020 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.compose.jetsurvey.survey
18+
19+
import android.content.ContentValues
20+
import android.provider.MediaStore
21+
22+
val photoCollection by lazy {
23+
MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
24+
}
25+
26+
fun getPhotoDetails() = ContentValues().apply {
27+
put(MediaStore.Images.Media.DISPLAY_NAME, generateFilename())
28+
put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")
29+
}
30+
31+
/**
32+
* Create a unique file name based on the time the photo is taken
33+
*/
34+
private fun generateFilename() = "selfie-${System.currentTimeMillis()}.jpg"

Jetsurvey/app/src/main/java/com/example/compose/jetsurvey/survey/Survey.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
package com.example.compose.jetsurvey.survey
1818

19-
import android.graphics.Bitmap
19+
import android.net.Uri
2020
import androidx.annotation.StringRes
2121

2222
data class SurveyResult(
@@ -44,7 +44,7 @@ enum class SurveyActionType { PICK_DATE, TAKE_PHOTO, SELECT_CONTACT }
4444

4545
sealed class SurveyActionResult {
4646
data class Date(val date: String) : SurveyActionResult()
47-
data class Photo(val bitmap: Bitmap) : SurveyActionResult()
47+
data class Photo(val uri: Uri) : SurveyActionResult()
4848
data class Contact(val contact: String) : SurveyActionResult()
4949
}
5050

Jetsurvey/app/src/main/java/com/example/compose/jetsurvey/survey/SurveyFragment.kt

Lines changed: 10 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,8 @@
1616

1717
package com.example.compose.jetsurvey.survey
1818

19-
import android.content.ContentValues
19+
import android.net.Uri
2020
import android.os.Bundle
21-
import android.provider.MediaStore
22-
import android.util.Log
2321
import android.view.LayoutInflater
2422
import android.view.View
2523
import android.view.ViewGroup
@@ -36,29 +34,13 @@ class SurveyFragment : Fragment() {
3634

3735
private val viewModel: SurveyViewModel by viewModels { SurveyViewModelFactory() }
3836

39-
// Add a specific media item.
40-
val resolver by lazy { requireContext().contentResolver }
37+
private val resolver by lazy { requireContext().contentResolver }
38+
// Uri used to save photos taken with the camera
39+
private var uri: Uri? = null
4140

42-
// Find all audio files on the primary external storage device.
43-
// On API <= 28, use VOLUME_EXTERNAL instead.
44-
val photoCollection by lazy {
45-
MediaStore.Images.Media.getContentUri(
46-
MediaStore.VOLUME_EXTERNAL_PRIMARY
47-
)
48-
}
49-
50-
val newPhotoDetails by lazy {
51-
ContentValues().apply {
52-
put(MediaStore.Images.Media.DISPLAY_NAME, "photo")
53-
put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")
54-
}
55-
}
56-
val uri by lazy { resolver.insert(photoCollection, newPhotoDetails) }
57-
58-
private val takePicture = registerForActivityResult(TakePicture()) { saved ->
59-
if (saved) {
60-
Log.d("flo", "saved: $saved")
61-
// viewModel.saveImageFromCamera(bitmap, imagesFolder)
41+
private val takePicture = registerForActivityResult(TakePicture()) { photoSaved ->
42+
if (photoSaved) {
43+
uri?.let { viewModel.onImageSaved(it) }
6244
}
6345
}
6446

@@ -101,7 +83,7 @@ class SurveyFragment : Fragment() {
10183
private fun handleSurveyAction(questionId: Int, actionType: SurveyActionType) {
10284
when (actionType) {
10385
SurveyActionType.PICK_DATE -> showDatePicker(questionId)
104-
SurveyActionType.TAKE_PHOTO -> takeAPhoto(questionId)
86+
SurveyActionType.TAKE_PHOTO -> takeAPhoto()
10587
SurveyActionType.SELECT_CONTACT -> selectContact(questionId)
10688
}
10789
}
@@ -116,9 +98,8 @@ class SurveyFragment : Fragment() {
11698
}
11799
}
118100

119-
120-
@Suppress("UNUSED_PARAMETER")
121-
private fun takeAPhoto(questionId: Int) {
101+
private fun takeAPhoto() {
102+
uri = resolver.insert(photoCollection, getPhotoDetails())
122103
takePicture.launch(uri)
123104
}
124105

Jetsurvey/app/src/main/java/com/example/compose/jetsurvey/survey/SurveyQuestions.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
package com.example.compose.jetsurvey.survey
1818

19-
import androidx.compose.foundation.Image
2019
import androidx.compose.foundation.BorderStroke
2120
import androidx.compose.foundation.ScrollableColumn
2221
import androidx.compose.foundation.background
@@ -26,7 +25,7 @@ import androidx.compose.foundation.layout.Column
2625
import androidx.compose.foundation.layout.PaddingValues
2726
import androidx.compose.foundation.layout.Row
2827
import androidx.compose.foundation.layout.Spacer
29-
import androidx.compose.foundation.layout.defaultMinSizeConstraints
28+
import androidx.compose.foundation.layout.fillMaxSize
3029
import androidx.compose.foundation.layout.fillMaxWidth
3130
import androidx.compose.foundation.layout.padding
3231
import androidx.compose.foundation.layout.preferredHeight
@@ -49,12 +48,13 @@ import androidx.compose.runtime.remember
4948
import androidx.compose.runtime.setValue
5049
import androidx.compose.ui.Alignment
5150
import androidx.compose.ui.Modifier
52-
import androidx.compose.ui.graphics.asImageAsset
5351
import androidx.compose.ui.res.stringResource
5452
import androidx.compose.ui.unit.dp
5553
import androidx.ui.tooling.preview.Preview
5654
import com.example.compose.jetsurvey.R
5755
import com.example.compose.jetsurvey.theme.JetsurveyTheme
56+
import com.example.compose.jetsurvey.theme.questionBackground
57+
import dev.chrisbanes.accompanist.coil.CoilImage
5858

5959
@Composable
6060
fun Question(
@@ -276,9 +276,9 @@ private fun ActionQuestion(
276276
)
277277
}
278278
is SurveyActionResult.Photo -> {
279-
Image(
280-
asset = answer.result.bitmap.asImageAsset(),
281-
modifier = Modifier.defaultMinSizeConstraints(minWidth = 500.dp, minHeight = 500.dp)
279+
CoilImage(
280+
data = answer.result.uri,
281+
modifier = Modifier.fillMaxSize()
282282
)
283283
}
284284
is SurveyActionResult.Contact -> TODO()

Jetsurvey/app/src/main/java/com/example/compose/jetsurvey/survey/SurveyViewModel.kt

Lines changed: 12 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -16,26 +16,13 @@
1616

1717
package com.example.compose.jetsurvey.survey
1818

19-
import android.content.Context
20-
import android.content.res.XmlResourceParser
21-
import android.graphics.Bitmap
22-
import android.graphics.BitmapFactory
23-
import android.graphics.Canvas
24-
import android.graphics.Paint
25-
import android.graphics.Rect
26-
import android.util.Log
19+
import android.net.Uri
2720
import androidx.lifecycle.LiveData
2821
import androidx.lifecycle.MutableLiveData
2922
import androidx.lifecycle.ViewModel
3023
import androidx.lifecycle.ViewModelProvider
3124
import androidx.lifecycle.viewModelScope
32-
import kotlinx.coroutines.Dispatchers
3325
import kotlinx.coroutines.launch
34-
import kotlinx.coroutines.withContext
35-
import java.io.File
36-
import java.io.FileOutputStream
37-
38-
private const val FILEPATH_XML_KEY = "files-path"
3926

4027
class SurveyViewModel(private val surveyRepository: SurveyRepository) : ViewModel() {
4128

@@ -76,6 +63,12 @@ class SurveyViewModel(private val surveyRepository: SurveyRepository) : ViewMode
7663
updateStateWithActionResult(questionId, SurveyActionResult.Date(date))
7764
}
7865

66+
fun onImageSaved(uri: Uri) {
67+
getLatestQuestionId()?.let { questionId ->
68+
updateStateWithActionResult(questionId, SurveyActionResult.Photo(uri))
69+
}
70+
}
71+
7972
private fun updateStateWithActionResult(questionId: Int, result: SurveyActionResult) {
8073
val latestState = _uiState.value
8174
if (latestState != null && latestState is SurveyState.Questions) {
@@ -88,59 +81,15 @@ class SurveyViewModel(private val surveyRepository: SurveyRepository) : ViewMode
8881
}
8982
}
9083

91-
92-
fun saveImageFromCamera(bitmap: Bitmap, imagesFolder: File) {
93-
val imageFile = File(imagesFolder, generateFilename("CAMERA"))
94-
val imageStream = FileOutputStream(imageFile)
95-
96-
viewModelScope.launch {
97-
withContext(Dispatchers.IO) {
98-
try {
99-
// bitmap.compress(Bitmap.CompressFormat.JPEG, 100, imageStream)
100-
val grayscaleBitmap = withContext(Dispatchers.Default) {
101-
applyGrayscaleFilter(bitmap)
102-
}
103-
grayscaleBitmap.compress(Bitmap.CompressFormat.JPEG, 100, imageStream)
104-
imageStream.flush()
105-
imageStream.close()
106-
107-
Log.d("flo", "Camera image saved")
108-
109-
} catch (e: Exception) {
110-
Log.e(javaClass.simpleName, "Error writing bitmap", e)
111-
}
112-
}
113-
}
114-
115-
Log.d("flo", "filename: ${imageFile.path}")
116-
val newBitmap = BitmapFactory.decodeFile(imageFile.absolutePath)
117-
updateStateWithActionResult(975, SurveyActionResult.Photo(newBitmap))
118-
}
119-
}
120-
121-
fun getImagesFolder(context: Context): File {
122-
return File(context.filesDir, "images/").also {
123-
if (!it.exists()) {
124-
it.mkdir()
84+
private fun getLatestQuestionId(): Int? {
85+
val latestState = _uiState.value
86+
if (latestState != null && latestState is SurveyState.Questions) {
87+
return latestState.questionsState[0].question.id
12588
}
89+
return null
12690
}
12791
}
12892

129-
fun generateFilename(source: String) = "$source-${System.currentTimeMillis()}.jpg"
130-
131-
suspend fun applyGrayscaleFilter(original: Bitmap): Bitmap = withContext(Dispatchers.Default) {
132-
val height = original.height
133-
val width = original.width
134-
135-
val modifiedBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565)
136-
val canvas = Canvas(modifiedBitmap)
137-
val paint = Paint()
138-
canvas.drawBitmap(original, null, Rect(0, 0, original.width, original.height), paint)
139-
140-
modifiedBitmap
141-
}
142-
143-
14493
class SurveyViewModelFactory : ViewModelProvider.Factory {
14594
@Suppress("UNCHECKED_CAST")
14695
override fun <T : ViewModel?> create(modelClass: Class<T>): T {

Jetsurvey/app/src/main/res/xml/filepaths.xml

Lines changed: 0 additions & 20 deletions
This file was deleted.

Jetsurvey/buildSrc/src/main/java/com/example/compose/jetsurvey/buildsrc/dependencies.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ object Libs {
2828

2929
const val material = "com.google.android.material:material:1.1.0"
3030

31+
object Accompanist {
32+
private const val version = "0.3.2"
33+
const val coil = "dev.chrisbanes.accompanist:accompanist-coil:$version"
34+
}
35+
3136
object Kotlin {
3237
private const val version = "1.4.10"
3338
const val stdlib = "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$version"

0 commit comments

Comments
 (0)