Skip to content

Commit

Permalink
Fixed Camera opens twice when "Don't keep activities" option is ON
Browse files Browse the repository at this point in the history
Fixed Camera opens twice when "Don't keep activities" option is ON

#41
  • Loading branch information
Dhaval2404 committed Dec 9, 2019
1 parent f0b5ecd commit 7695b2d
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ class ImagePickerActivity : FragmentActivity() {
companion object {
private const val TAG = "image_picker"

/**
* Key to Save/Retrieve Image File state
*/
private const val STATE_IMAGE_FILE = "state.image_file"

internal fun getCancelledIntent(context: Context): Intent {
val intent = Intent()
val message = context.getString(R.string.error_task_cancelled)
Expand All @@ -39,37 +44,68 @@ class ImagePickerActivity : FragmentActivity() {
private lateinit var mCropProvider: CropProvider
private lateinit var mCompressionProvider: CompressionProvider

private var mOriginalFile: File? = null
/** File provided by GalleryProvider or CameraProvider */
private var mImageFile: File? = null

/** File provided by CropProvider */
private var mCropFile: File? = null

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
loadBundle()
restoreInstanceState(savedInstanceState)
loadBundle(savedInstanceState)
}

/**
* Restore saved state
*/
private fun restoreInstanceState(savedInstanceState: Bundle?) {
if (savedInstanceState != null) {
mImageFile = savedInstanceState.getSerializable(STATE_IMAGE_FILE) as File?
}
}

/**
* Save all appropriate activity state.
*/
public override fun onSaveInstanceState(outState: Bundle) {
outState.putSerializable(STATE_IMAGE_FILE, mImageFile)
mCameraProvider?.onSaveInstanceState(outState)
mCropProvider.onSaveInstanceState(outState)
super.onSaveInstanceState(outState)
}

/**
* Parse Intent Bundle and initialize variables
*/
private fun loadBundle() {
private fun loadBundle(savedInstanceState: Bundle?) {
// Create Crop Provider
mCropProvider = CropProvider(this)
mCropProvider.onRestoreInstanceState(savedInstanceState)

// Create Compression Provider
mCompressionProvider = CompressionProvider(this)

val bundle = intent?.extras
val provider = bundle?.getSerializable(ImagePicker.EXTRA_IMAGE_PROVIDER) as ImageProvider?
// Retrieve Image Provider
val provider: ImageProvider? =
intent?.getSerializableExtra(ImagePicker.EXTRA_IMAGE_PROVIDER) as ImageProvider?

// Create provider object and start process
// Create Gallery/Camera Provider
when (provider) {
ImageProvider.GALLERY -> {
mGalleryProvider = GalleryProvider(this)
mGalleryProvider?.startIntent()
// Pick Gallery Image
savedInstanceState ?: mGalleryProvider?.startIntent()
}
ImageProvider.CAMERA -> {
mCameraProvider = CameraProvider(this)
mCameraProvider?.startIntent()
mCameraProvider?.onRestoreInstanceState(savedInstanceState)
// Pick Camera Image
savedInstanceState ?: mCameraProvider?.startIntent()
}
else -> {
Log.e(TAG, "Image provider can not be null")
// Something went Wrong! This case should never happen
Log.e(TAG, "Image provider can not be null")
setError(getString(R.string.error_task_cancelled))
}
}
Expand Down Expand Up @@ -111,7 +147,7 @@ class ImagePickerActivity : FragmentActivity() {
* @param file Capture/Gallery image file
*/
fun setImage(file: File) {
mOriginalFile = file
mImageFile = file
when {
mCropProvider.isCropEnabled() -> mCropProvider.startIntent(file)
mCompressionProvider.isCompressionRequired(file) -> mCompressionProvider.compress(file)
Expand All @@ -132,8 +168,8 @@ class ImagePickerActivity : FragmentActivity() {
mCameraProvider?.let {
// Delete Camera file after crop. Else there will be two image for the same action.
// In case of Gallery Provider, we will get original image path, so we will not delete that.
mOriginalFile?.delete()
mOriginalFile = null
mImageFile?.delete()
mImageFile = null
}

if (mCompressionProvider.isCompressionRequired(file)) {
Expand All @@ -153,7 +189,7 @@ class ImagePickerActivity : FragmentActivity() {
mCameraProvider?.let {
// Delete Camera file after Compress. Else there will be two image for the same action.
// In case of Gallery Provider, we will get original image path, so we will not delete that.
mOriginalFile?.delete()
mImageFile?.delete()
}

// If crop file is not null, Delete it after crop
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.github.dhaval2404.imagepicker.provider

import android.content.ContextWrapper
import android.os.Bundle
import android.widget.Toast
import com.github.dhaval2404.imagepicker.ImagePickerActivity

Expand Down Expand Up @@ -55,4 +56,19 @@ abstract class BaseProvider(protected val activity: ImagePickerActivity) : Conte
*/
protected open fun onFailure() {
}

/**
* Save all appropriate provider state.
*/
open fun onSaveInstanceState(outState: Bundle) {
}

/**
* Restores the saved state for all Providers.
*
* @param savedInstanceState the Bundle returned by {@link #onSaveInstanceState()}
* @see #onSaveInstanceState()
*/
open fun onRestoreInstanceState(savedInstanceState: Bundle?) {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import android.Manifest
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.core.app.ActivityCompat.requestPermissions
import com.github.dhaval2404.imagepicker.ImagePickerActivity
import com.github.dhaval2404.imagepicker.R
Expand All @@ -23,6 +24,10 @@ import java.io.File
class CameraProvider(activity: ImagePickerActivity) : BaseProvider(activity) {

companion object {
/**
* Key to Save/Retrieve Camera File state
*/
private const val STATE_CAMERA_FILE = "state.camera_file"

/**
* Permission Require for Image Capture using Camera
Expand Down Expand Up @@ -54,6 +59,29 @@ class CameraProvider(activity: ImagePickerActivity) : BaseProvider(activity) {
private val mAskCameraPermission = PermissionUtil
.isPermissionInManifest(this, Manifest.permission.CAMERA)

/**
* Save CameraProvider state
* mCameraFile will lose its state when activity is recreated on
* Orientation change or for Low memory device.
*
* Here, We Will save its state for later use
*
* Note: To produce this scenario, enable "Don't keep activities" from developer options
**/
override fun onSaveInstanceState(outState: Bundle) {
// Save Camera File
outState.putSerializable(STATE_CAMERA_FILE, mCameraFile)
}

/**
* Retrieve CameraProvider state
*/
override fun onRestoreInstanceState(savedInstanceState: Bundle?) {
// Restore Camera File
mCameraFile = savedInstanceState?.getSerializable(STATE_CAMERA_FILE) as File?
}

/**
* Start Camera Capture Intent
*/
Expand Down Expand Up @@ -83,11 +111,12 @@ class CameraProvider(activity: ImagePickerActivity) : BaseProvider(activity) {
*/
private fun startCameraIntent() {
// Create and get empty file to store capture image content
mCameraFile = FileUtil.getImageFile()
val file = FileUtil.getImageFile()
mCameraFile = file

// Check if file exists
if (mCameraFile != null && mCameraFile!!.exists()) {
val cameraIntent = IntentUtils.getCameraIntent(this, mCameraFile!!)
if (file != null && file.exists()) {
val cameraIntent = IntentUtils.getCameraIntent(this, file)
activity.startActivityForResult(cameraIntent, CAMERA_INTENT_REQ_CODE)
} else {
setError(R.string.error_failed_to_create_camera_image_file)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import android.app.Activity
import android.content.ActivityNotFoundException
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.util.Log
import com.github.dhaval2404.imagepicker.ImagePicker
import com.github.dhaval2404.imagepicker.ImagePickerActivity
Expand All @@ -24,6 +25,11 @@ class CropProvider(activity: ImagePickerActivity) : BaseProvider(activity) {

companion object {
private val TAG = CropProvider::class.java.simpleName

/**
* Key to Save/Retrieve Crop File state
*/
private const val STATE_CROP_FILE = "state.crop_file"
}

private val mMaxWidth: Int
Expand All @@ -47,6 +53,29 @@ class CropProvider(activity: ImagePickerActivity) : BaseProvider(activity) {
mCropAspectY = bundle.getFloat(ImagePicker.EXTRA_CROP_Y, 0f)
}

/**
* Save CameraProvider state
*
* mCropImageFile will lose its state when activity is recreated on
* Orientation change or for Low memory device.
*
* Here, We Will save its state for later use
*
* Note: To produce this scenario, enable "Don't keep activities" from developer options
*/
override fun onSaveInstanceState(outState: Bundle) {
// Save crop file
outState.putSerializable(STATE_CROP_FILE, mCropImageFile)
}

/**
* Retrieve CropProvider state
*/
override fun onRestoreInstanceState(savedInstanceState: Bundle?) {
// Restore crop file
mCropImageFile = savedInstanceState?.getSerializable(STATE_CROP_FILE) as File?
}

/**
* Check if crop should be enabled or not
*
Expand Down

0 comments on commit 7695b2d

Please sign in to comment.