0

I'm trying to rewrite my old code in Jetpack Compose, but I have trouble with ContentResolver.addStatusChangeListener which is not firing sync events. I'm using the same business logic (viewmodel, repository) for both - classic UI and compose, but in compose it's not working.

Here is the classic UI code:

private var syncStatusHandle: Any? = null

override fun onResume() {
    super.onResume()
    syncStatusHandle = ContentResolver.addStatusChangeListener(
        ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE or ContentResolver.SYNC_OBSERVER_TYPE_PENDING
    )
    {
        Timber.d("sync event fired")
    }
}

override fun onPause() {
    super.onPause()
    if (syncStatusHandle != null) {
        ContentResolver.removeStatusChangeListener(syncStatusHandle)
    }
}

And here is how it looks like in Compose (It's pretty much the same approach as mentioned in the docs: Interoperability APIs):

@Composable
fun SyncStatusManager(
    onSyncEvent: (count: Int) -> Unit
) {
    val context = LocalContext.current
    val currentOnSyncEvent by rememberUpdatedState(onSyncEvent)
    DisposableEffect(context) {
        val syncStatusHandle = ContentResolver.addStatusChangeListener(
            ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE or ContentResolver.SYNC_OBSERVER_TYPE_PENDING
        )
        {
            currentOnSyncEvent(it)
        }

        onDispose {
            ContentResolver.removeStatusChangeListener(syncStatusHandle)
        }
    }
}

and it's used in different composable like this:

  SyncStatusManager {
        Timber.d("sync event should be fired, but it's not")
    }

I tried to use LaunchEffect, or not Effects at all, but no success. When I trigger sync, the callback should fire immediately but it doesn't. am I missing something ? I'm new to Jetpack Compose. Thank you (Necessary permissions are granted in both cases)

2 Answers 2

1

Example:

private fun myLifecycleObserver(onResume:()->Unit,onPause:()->Unit): LifecycleEventObserver =
    LifecycleEventObserver { _, event ->
        when (event) {
            Lifecycle.Event.ON_RESUME -> onResume()
            Lifecycle.Event.ON_PAUSE -> onPause()
            else -> { /* ignore */ }
        }
    }



@Composable
fun SyncStatusManager(
    onSyncEvent: (count: Int) -> Unit
) {
    val context = LocalContext.current
    val lifecycle = LocalLifecycleOwner.current.lifecycle
    val currentOnSyncEvent by rememberUpdatedState(onSyncEvent)
    var syncStatusHandleState by remember { mutableStateOf<Any?>(null) }

    DisposableEffect(context, lifecycle) {
        val lifecycleObserver =myLifecycleObserver(onResume = {
            syncStatusHandleState = ContentResolver.addStatusChangeListener(
                ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE or ContentResolver.SYNC_OBSERVER_TYPE_PENDING
            )
            {
                currentOnSyncEvent(it)
            }
        }, onPause = {
            syncStatusHandleState?.apply {
                ContentResolver.removeStatusChangeListener(this)
            }
        })

        lifecycle.addObserver(lifecycleObserver)
        onDispose {
            lifecycle.removeObserver(lifecycleObserver)
        }
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

thank you for the response, but it's not working for me either. onResume and onPause callbacks are working correctly, but sync listener doesn't. I'm starting to think problem is somewhere 'under the hood'... I'll need to investigate it deeper... thanks for the response anyway
1

Maybe you didn't add permission

<uses-permission android:name="android.permission.READ_SYNC_STATS" />

1 Comment

Thank you for your response, but that's not the issue. I used that permission and it didn't work.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.