Skip to content

Commit

Permalink
Merge pull request #43 from lovoo/develop
Browse files Browse the repository at this point in the history
Fix unsent events from CaptureResultWorker
  • Loading branch information
sherzodnosirov authored Jul 10, 2024
2 parents 2d1c2ed + 7b5804f commit db7c8ff
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 34 deletions.
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ buildscript {
ext.espresso_version = "3.4.0"
ext.uiautomator_version = "2.2.0"
ext.orchestrator_version = "1.2.0"
ext.androidX_test_version = "1.2.0"
ext.androidX_test_version = "1.4.0"

ext.target_version = 33
ext.target_version = 34
ext.min_version = 18

def version = System.getenv("VERSION")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,8 @@
package com.lovoo.android.pickcam.view

import android.app.Activity
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
Expand All @@ -30,6 +28,8 @@ import android.view.ViewGroup
import androidx.core.content.ContextCompat
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.FragmentManager
import androidx.work.WorkInfo
import androidx.work.WorkManager
import com.lovoo.android.pickcam.R
import com.lovoo.android.pickcam.worker.CaptureResultWorker
import com.lovoo.android.pickcore.contract.CameraDestination
Expand All @@ -39,7 +39,6 @@ import com.lovoo.android.pickcore.destination.PublicDirectory
import com.lovoo.android.pickcore.loader.CameraLoader
import com.lovoo.android.pickcore.permission.Permission
import com.lovoo.android.pickcore.util.isMinimumR
import com.lovoo.android.pickcore.util.registerReceiverSafely

/**
* Ready to use solution to handle Android Camera capture.
Expand All @@ -57,13 +56,6 @@ class PickPicCaptureFragment : DialogFragment() {
private var captureDestination: CameraDestination? = null
private var captureCallback: CaptureCallback? = null

private val onWorkerDoneReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
captureCallback?.onCapture(CaptureResultWorker.getUri(intent))
dismissAllowingStateLoss()
}
}

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.pickpic_capture_fragment, container, false)
}
Expand All @@ -81,10 +73,6 @@ class PickPicCaptureFragment : DialogFragment() {
throw (IllegalArgumentException("You have to implement CaptureCallback"))
}
}
context.registerReceiverSafely(
receiver = onWorkerDoneReceiver,
filter = IntentFilter().apply { addAction(CaptureResultWorker.INTENT_ACTION_ON_RESULT) },
)
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
Expand All @@ -110,18 +98,18 @@ class PickPicCaptureFragment : DialogFragment() {

val destination = captureDestination
if (resultCode == Activity.RESULT_OK && destination != null) {
CaptureResultWorker.start(requireContext().applicationContext, destination, WORKER_NAME)
val workUuid = CaptureResultWorker.start(requireContext().applicationContext, destination, WORKER_NAME)

WorkManager.getInstance(this.requireContext())
.getWorkInfoByIdLiveData(workUuid).observe(viewLifecycleOwner) { workInfo ->
handleWorkInfo(workInfo)
}
} else {
captureCallback?.onCapture(null)
dismissAllowingStateLoss()
}
}

override fun onDetach() {
context?.unregisterReceiver(onWorkerDoneReceiver)
super.onDetach()
}

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == PERMISSION_REQUEST_CODE) {
Expand Down Expand Up @@ -177,6 +165,19 @@ class PickPicCaptureFragment : DialogFragment() {
}
}

private fun handleWorkInfo(workInfo: WorkInfo?) {
if (workInfo == null) {
return
}

if (workInfo.state == WorkInfo.State.SUCCEEDED) {
captureCallback?.onCapture(CaptureResultWorker.getUri(workInfo.outputData))
}
if (workInfo.state.isFinished) {
dismissAllowingStateLoss()
}
}

companion object {
private const val CAMERA_REQUEST_CODE = 2734
private const val PERMISSION_REQUEST_CODE = 2735
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,10 @@
*/
package com.lovoo.android.pickcam.worker

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.media.MediaScannerConnection
import android.net.Uri
import androidx.work.Data
import androidx.work.ExistingWorkPolicy
import androidx.work.OneTimeWorkRequest
import androidx.work.RxWorker
Expand All @@ -33,6 +32,7 @@ import com.lovoo.android.pickcore.loader.CameraLoader
import com.lovoo.android.pickcore.util.isMinimumQ
import io.reactivex.Single
import java.io.File
import java.util.UUID

/**
* Worker that handles all the tasks to finalize the captured image from the camera.
Expand All @@ -55,11 +55,10 @@ class CaptureResultWorker(
private var isPublic: Boolean = params.inputData.getBoolean(INPUT_IS_PUBLIC, true)

override fun createWork(): Single<Result> {
return Single.create<Result> { emitter ->
return Single.create { emitter ->
val file = if (isPublic || isMinimumQ()) inputFile else inputFile.moveToPublicDirectory().file

if (file == null) {
context.sendBroadcast(Intent(INTENT_ACTION_ON_RESULT))
emitter.onError(RuntimeException("Captured file is null"))
return@create
}
Expand All @@ -70,33 +69,36 @@ class CaptureResultWorker(
MediaScannerConnection.OnScanCompletedListener { _, uri ->
if (uri == null) return@OnScanCompletedListener
// LiveData holds to long the old result so we have to forward the result as broadcast
context.sendBroadcast(Intent(INTENT_ACTION_ON_RESULT).putExtra(OUTPUT_URI, uri))
emitter.onSuccess(Result.success())
emitter.onSuccess(Result.success(Data.Builder().putString(OUTPUT_URI, uri.toString()).build()))
},
)
}
}

companion object {
const val OUTPUT_URI = "pickcam_output_uri"
private const val INPUT_FILE = "pickcam_input_file"
private const val INPUT_IS_PUBLIC = "pickcam_input_is_public"
private const val OUTPUT_URI = "pickcam_output_uri"
const val INTENT_ACTION_ON_RESULT = "pickcam_result_done"

/**
* Receive the [Uri] from the [Intent] provided by the [BroadcastReceiver]
* @param intent the result [Intent] provided by the [BroadcastReceiver] or null
* Receive the [Uri] from the [Data] provided by the [Worker]
* @param data the output data [Data] provided by the [CaptureResultWorker] or null. If equal
* to [Data.EMPTY] the null will be returned by this function.
* @return the [Uri] to the "normalized" captured image or null
*/
fun getUri(intent: Intent?): Uri? = intent?.getParcelableExtra(OUTPUT_URI)
fun getUri(data: Data?): Uri? = data?.takeUnless { it == Data.EMPTY }
?.getString(OUTPUT_URI)
?.let { Uri.parse(it) }

/**
* Enqueue the unique [Worker] with REPLACE policy.
*
* @param destination the [CameraDestination] that was used to capture the picture
* @param name optional unique name for the [Worker] (default: CaptureResultWorker)
*
* @return the uuid of the created WorkRequest
*/
fun start(context: Context, destination: CameraDestination, name: String = "CaptureResultWorker") {
fun start(context: Context, destination: CameraDestination, name: String = "CaptureResultWorker"): UUID {
val data = workDataOf(
INPUT_IS_PUBLIC to (destination !is PrivateDirectory),
INPUT_FILE to (destination.file?.path ?: ""),
Expand All @@ -107,6 +109,7 @@ class CaptureResultWorker(
.build()

WorkManager.getInstance(context).enqueueUniqueWork(name, ExistingWorkPolicy.REPLACE, request)
return request.id
}
}
}

0 comments on commit db7c8ff

Please sign in to comment.