Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,10 @@ dependencies {
implementation "com.github.bumptech.glide:glide:4.10.0"
implementation "com.jakewharton.timber:timber:4.7.1"
implementation "org.jetbrains.kotlin:kotlin-stdlib:$versions.kotlin"

// Room components
implementation "androidx.room:room-ktx:$versions.room"
kapt "androidx.room:room-compiler:$versions.room"
androidTestImplementation "androidx.room:room-testing:$versions.room"

}
16 changes: 3 additions & 13 deletions app/src/main/java/com/example/background/BlurViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import androidx.work.OneTimeWorkRequest
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkInfo
import androidx.work.WorkManager
import androidx.work.workDataOf
import com.example.background.workers.BlurWorker
import com.example.background.workers.CleanupWorker
import com.example.background.workers.SaveImageToFileWorker
Expand All @@ -48,18 +49,6 @@ class BlurViewModel(application: Application) : AndroidViewModel(application) {
workManager.cancelUniqueWork(IMAGE_MANIPULATION_WORK_NAME)
}

/**
* Creates the input data bundle which includes the Uri to operate on
* @return Data which contains the Image Uri as a String
*/
private fun createInputDataForUri(): Data {
val builder = Data.Builder()
imageUri?.let {
builder.putString(KEY_IMAGE_URI, imageUri.toString())
}
return builder.build()
}

/**
* Create the WorkRequest to apply the blur and save the resulting image
* @param blurLevel The amount to blur the image
Expand All @@ -81,7 +70,8 @@ class BlurViewModel(application: Application) : AndroidViewModel(application) {
// After the first blur operation the input will be the output of previous
// blur operations.
if (i == 0) {
blurBuilder.setInputData(createInputDataForUri())
val data = workDataOf(KEY_IMAGE_URI to imageUri.toString())
blurBuilder.setInputData(data)
}

continuation = continuation.then(blurBuilder.build())
Expand Down
35 changes: 35 additions & 0 deletions app/src/main/java/com/example/background/data/BlurredImage.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.example.background.data

import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey

/**
* A basic class representing an entity that is a row in a one-column database table.
*
* @ Entity - You must annotate the class as an entity and supply a table name if not class name.
* @ PrimaryKey - You must identify the primary key.
* @ ColumnInfo - You must supply the column name if it is different from the variable name.
*
* See the documentation for the full rich set of annotations.
* https://developer.android.com/topic/libraries/architecture/room.html
*/

@Entity(tableName = "images_table")
data class BlurredImage(@PrimaryKey @ColumnInfo(name = "uri") val uri: String)
42 changes: 42 additions & 0 deletions app/src/main/java/com/example/background/data/BlurredImageDao.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.example.background.data

import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import kotlinx.coroutines.flow.Flow

/**
* The Room Magic is in this file, where you map a method call to an SQL query.
*
* When you are using complex data types, such as Date, you have to also supply type converters.
* To keep this example basic, no types that require type converters are used.
* See the documentation at
* https://developer.android.com/topic/libraries/architecture/room.html#type-converters
*/

@Dao
interface BlurredImageDao {

@Query("SELECT * FROM images_table")
fun getBlurredImages(): Flow<List<BlurredImage>>

@Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insert(blurredImage: BlurredImage)
}
53 changes: 53 additions & 0 deletions app/src/main/java/com/example/background/data/ImagesDatabase.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.example.background.data

import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase

/**
* This is the backend. The database. This used to be done by the OpenHelper.
* The fact that this has very few comments emphasizes its coolness.
*/
@Database(entities = [BlurredImage::class], version = 1)
abstract class ImagesDatabase : RoomDatabase() {

abstract fun blurredImageDao(): BlurredImageDao

companion object {
@Volatile
private var INSTANCE: ImagesDatabase? = null

fun getDatabase(context: Context): ImagesDatabase {
// if the INSTANCE is not null, then return it,
// if it is, then create the database
return INSTANCE ?: synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,
ImagesDatabase::class.java,
"images_database"
).build()
INSTANCE = instance
// return instance
instance
}
}

}
}
51 changes: 30 additions & 21 deletions app/src/main/java/com/example/background/workers/BlurWorker.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,45 +19,54 @@ package com.example.background.workers
import android.content.Context
import android.graphics.BitmapFactory
import android.net.Uri
import android.text.TextUtils
import androidx.work.Worker
import androidx.work.CoroutineWorker
import androidx.work.Data
import androidx.work.WorkerParameters
import androidx.work.workDataOf
import com.example.background.KEY_IMAGE_URI
import com.example.background.data.BlurredImage
import com.example.background.data.ImagesDatabase
import timber.log.Timber

class BlurWorker(ctx: Context, params: WorkerParameters) : Worker(ctx, params) {

override fun doWork(): Result {
val appContext = applicationContext
class BlurWorker(ctx: Context, params: WorkerParameters) : CoroutineWorker(ctx, params) {

override suspend fun doWork(): Result {
val resourceUri = inputData.getString(KEY_IMAGE_URI)

makeStatusNotification("Blurring image", appContext)
sleep()
makeStatusNotification("Blurring image", applicationContext)

return try {
if (TextUtils.isEmpty(resourceUri)) {
if (resourceUri.isNullOrEmpty()) {
Timber.e("Invalid input uri")
throw IllegalArgumentException("Invalid input uri")
}

val resolver = appContext.contentResolver

val picture = BitmapFactory.decodeStream(
resolver.openInputStream(Uri.parse(resourceUri)))

val output = blurBitmap(picture, appContext)

// Write bitmap to a temp file
val outputUri = writeBitmapToFile(appContext, output)

val outputData = workDataOf(KEY_IMAGE_URI to outputUri.toString())

val outputData = blurAndWriteImageToFile(resourceUri)
recordImageSaved(resourceUri)
Result.success(outputData)
} catch (throwable: Throwable) {
Timber.e(throwable, "Error applying blur")
Result.failure()
}
}

private suspend fun recordImageSaved(resourceUri: String) {
val imageDao = ImagesDatabase.getDatabase(applicationContext).blurredImageDao()
imageDao.insert(BlurredImage(resourceUri))
}

private fun blurAndWriteImageToFile(resourceUri: String): Data {
val resolver = applicationContext.contentResolver

val picture = BitmapFactory.decodeStream(
resolver.openInputStream(Uri.parse(resourceUri)))

val output = blurBitmap(picture, applicationContext)

// Write bitmap to a temp file
val outputUri = writeBitmapToFile(applicationContext, output)

val outputData = workDataOf(KEY_IMAGE_URI to outputUri.toString())
return outputData
}
}
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ buildscript {
versions.targetSdk = 29
versions.kotlin = '1.4.10'
versions.work = "2.4.0"
versions.room = '2.2.5'

repositories {
google()
Expand Down