Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrated Deprecated AsyncTask to Kotlin Coroutines #25

Merged
merged 7 commits into from
Jan 6, 2021
Merged
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
10 changes: 7 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,25 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
- `Added` for new features.
- `Changed` for changes in existing functionality.
- `Deprecated for soon-to-be removed features.
- `Deprecated` for soon-to-be removed features.
- `Removed` for now removed features.
- `Fixed` for any bug fixes.
- `Security` in case of vulnerabilities.

## unreleased

## [1.1.1] - 03/01/20
## [2.0.0] - 06/01/21
### Changed
- AsyncTask to Kotlin Coroutines

## [1.1.1] - 03/01/21
### Added
- Ktlint
- Release using JitPack

### Changed
- Java to kotlin
- Cange icons from PNG to vectors
- Change icons from PNG to vectors

## [1.1.0] - 13/12/20
### Changed
Expand Down
15 changes: 14 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ Android Image Cropper

#### Step 3. Add permissions to manifest

```
```xml
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
```
Expand All @@ -48,6 +48,19 @@ Android Image Cropper
-keep class androidx.appcompat.widget.** { *; }
```

#### Step 5. Set source compatibility version to Java 8

- Go to app level `build.gradle` file

- Add this line inside ```android``` in build.gradle
```groovy
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
```

- This will set the java version to 8

## Using Activity

Expand Down
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
buildscript {
ext.kotlin_version = '1.4.20'
ext.kotlin_version = '1.4.21'
repositories {
maven { url "https://plugins.gradle.org/m2/" }
jcenter()
Expand Down Expand Up @@ -30,7 +30,7 @@ allprojects {
ext {
compileSdkVersion = 30
targetSdkVersion = 30
buildToolsVersion = '29.0.3'
buildToolsVersion = '30.0.2'

// AndroidX
androidXAppCompatVersion = '1.2.0'
Expand Down
4 changes: 4 additions & 0 deletions cropper/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ dependencies {
implementation "androidx.exifinterface:exifinterface:$androidXExifVersion"
implementation "androidx.core:core-ktx:1.3.2"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.2.0"
def coroutines_version = "1.4.2"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
}
repositories {
mavenCentral()
Expand Down
247 changes: 247 additions & 0 deletions cropper/src/main/java/com/canhub/cropper/BitmapCroppingWorkerJob.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
package com.canhub.cropper

import android.graphics.Bitmap
import android.net.Uri
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.lang.ref.WeakReference

class BitmapCroppingWorkerJob internal constructor(
private val activity: FragmentActivity,
private val cropImageViewReference: WeakReference<CropImageView>,
val uri: Uri?,
private val bitmap: Bitmap?,
private val cropPoints: FloatArray,
private val degreesRotated: Int,
private val orgWidth: Int,
private val orgHeight: Int,
private val fixAspectRatio: Boolean,
private val aspectRatioX: Int,
private val aspectRatioY: Int,
private val reqWidth: Int,
private val reqHeight: Int,
private val flipHorizontally: Boolean,
private val flipVertically: Boolean,
private val options: CropImageView.RequestSizeOptions,
private val saveUri: Uri?,
private val saveCompressFormat: Bitmap.CompressFormat,
private val saveCompressQuality: Int
) {
private var currentJob: Job? = null

constructor(
activity: FragmentActivity,
cropImageView: CropImageView,
bitmap: Bitmap,
cropPoints: FloatArray,
degreesRotated: Int,
fixAspectRatio: Boolean,
aspectRatioX: Int,
aspectRatioY: Int,
reqWidth: Int,
reqHeight: Int,
flipHorizontally: Boolean,
flipVertically: Boolean,
options: CropImageView.RequestSizeOptions,
saveUri: Uri,
saveCompressFormat: Bitmap.CompressFormat,
saveCompressQuality: Int
) : this(
activity,
WeakReference(cropImageView),
null,
bitmap,
cropPoints,
degreesRotated,
0,
0,
fixAspectRatio,
aspectRatioX,
aspectRatioY,
reqWidth,
reqHeight,
flipHorizontally,
flipVertically,
options,
saveUri,
saveCompressFormat,
saveCompressQuality
)

constructor(
activity: FragmentActivity,
cropImageView: CropImageView,
uri: Uri,
cropPoints: FloatArray,
degreesRotated: Int,
orgWidth: Int,
orgHeight: Int,
fixAspectRatio: Boolean,
aspectRatioX: Int,
aspectRatioY: Int,
reqWidth: Int,
reqHeight: Int,
flipHorizontally: Boolean,
flipVertically: Boolean,
options: CropImageView.RequestSizeOptions,
saveUri: Uri,
saveCompressFormat: Bitmap.CompressFormat,
saveCompressQuality: Int
) : this(
activity,
WeakReference(cropImageView),
uri,
null,
cropPoints,
degreesRotated,
orgWidth,
orgHeight,
fixAspectRatio,
aspectRatioX,
aspectRatioY,
reqWidth,
reqHeight,
flipHorizontally,
flipVertically,
options,
saveUri,
saveCompressFormat,
saveCompressQuality
)

fun start() {
currentJob = activity.lifecycleScope.launch(Dispatchers.Default) {
try {
if (isActive) {
val bitmapSampled: BitmapUtils.BitmapSampled
if (uri != null) {
bitmapSampled = BitmapUtils.cropBitmap(
activity,
uri,
cropPoints,
degreesRotated,
orgWidth,
orgHeight,
fixAspectRatio,
aspectRatioX,
aspectRatioY,
reqWidth,
reqHeight,
flipHorizontally,
flipVertically
)
} else if (bitmap != null) {
bitmapSampled = BitmapUtils.cropBitmapObjectHandleOOM(
bitmap,
cropPoints,
degreesRotated,
fixAspectRatio,
aspectRatioX,
aspectRatioY,
flipHorizontally,
flipVertically
)
} else {
onPostExecute(Result(bitmap = null, 1))
Canato marked this conversation as resolved.
Show resolved Hide resolved
return@launch
}
val resizedBitmap =
BitmapUtils.resizeBitmap(bitmapSampled.bitmap, reqWidth, reqHeight, options)
if (saveUri == null) {
onPostExecute(
Result(
resizedBitmap,
bitmapSampled.sampleSize
)
)
} else {
BitmapUtils.writeBitmapToUri(
activity,
resizedBitmap,
saveUri,
saveCompressFormat,
saveCompressQuality
)
resizedBitmap?.recycle()
onPostExecute(
Result(
saveUri,
bitmapSampled.sampleSize
)
)
}
}
} catch (e: Exception) {
onPostExecute(Result(e, saveUri != null))
}
}
}

private suspend fun onPostExecute(result: Result) {
withContext(Dispatchers.Main) {
var completeCalled = false
if (isActive) {
cropImageViewReference.get()?.let {
completeCalled = true
it.onImageCroppingAsyncComplete(result)
}
}
if (!completeCalled && result.bitmap != null) {
// fast release of unused bitmap
result.bitmap.recycle()
}
}
}

fun cancel() {
currentJob?.cancel()
}

// region: Inner class: Result
companion object class Result {

/** The cropped bitmap */
val bitmap: Bitmap?

/** The saved cropped bitmap uri */
val uri: Uri?

/** The error that occurred during async bitmap cropping. */
val error: java.lang.Exception?

/** is the cropping request was to get a bitmap or to save it to uri */
val isSave: Boolean

/** sample size used creating the crop bitmap to lower its size */
val sampleSize: Int

constructor(bitmap: Bitmap?, sampleSize: Int) {
this.bitmap = bitmap
uri = null
error = null
isSave = false
this.sampleSize = sampleSize
}

constructor(uri: Uri?, sampleSize: Int) {
bitmap = null
this.uri = uri
error = null
isSave = true
this.sampleSize = sampleSize
}

constructor(error: java.lang.Exception?, isSave: Boolean) {
bitmap = null
uri = null
this.error = error
this.isSave = isSave
sampleSize = 1
}
}
}
Loading