ProcessLifecycleOwner not working after updating app compat to 1.4.1
Asked Answered
L

5

17

I'm investigating a weird issue, where we changed the androidx.appcompat:appcompat from 1.3.1 to 1.4.1 and all of a sudden our LifecycleObservers observing process lifecycle stopped emitting any events.

I'm also using "androidx.lifecycle:lifecycle-extensions:2.2.0", I know that this is already deprecated, but it works flawlessly if appcompat is 1.3.1

I have set the correct application name in the Manifest, I have included this provider as required per docs.

        <provider
            android:name="androidx.startup.InitializationProvider"
            android:authorities="${applicationId}.androidx-startup"
            tools:node="remove" />

Example of initialisation, which doesn't work. This object is injected in the Application class and lifecycle observer is getting added, but onStart and onStop are never called.

class AppLifecycle @Inject constructor(
    private val foregroundProxy: AppLifecycleProxy
) : LifecycleObserver {

    init {
        ProcessLifecycleOwner.get().lifecycle.addObserver(this)
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    fun onStart() {
        foregroundProxy.onStarted()
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    fun onStop() {
        foregroundProxy.onStopped()
    }
}

EDIT: As per @EpicPandaForce comment, changing the the provider block in Manifest to:

 <provider
    android:name="androidx.startup.InitializationProvider"
    android:authorities=\"${applicationId}.androidx-startup"
    android:exported="false"
    tools:node=\"merge">
    <!-- If you are using androidx.startup to initialize other components -->
    <meta-data
        android:name="androidx.lifecycle.ProcessLifecycleInitializer"
        android:value="androidx.startup"
        tools:node="remove" />
 </provider>

And replacing the "androidx.lifecycle:lifecycle-extensions:2.2.0" dependency with "androidx.lifecycle:lifecycle-common:2.4.1" has fixed this problem

Limousine answered 16/3, 2022 at 7:13 Comment(2)
Have you tried with app compat 1.6.0-alpha01 version?Scammony
Yes, the problem was in the provider block which disabled AndroidX StartUp processLimousine
B
17

There's a good bet that the reason there has been changes on your side is because ProcessLifecycleOwner's initialization was reworked to use the Jetpack Startup library, which relies on a ContentProvider, therefore only does initialization in a process's main process.

In the actual code for ProcessLifecycleOwner, it says:

/**
 * Initializes {@link ProcessLifecycleOwner} using {@code androidx.startup}.
 */
public final class ProcessLifecycleInitializer implements Initializer<LifecycleOwner> {

    @NonNull
    @Override
    public LifecycleOwner create(@NonNull Context context) {
        AppInitializer appInitializer = AppInitializer.getInstance(context);
        if (!appInitializer.isEagerlyInitialized(getClass())) {
            throw new IllegalStateException(
                    "ProcessLifecycleInitializer cannot be initialized lazily. \n"
                            + "Please ensure that you have: \n"
                            + "<meta-data\n"
                            + "    android:name='androidx.lifecycle.ProcessLifecycleInitializer' \n"
                            + "    android:value='androidx.startup' /> \n"
                            + "under InitializationProvider in your AndroidManifest.xml");
        }
        LifecycleDispatcher.init(context);
        ProcessLifecycleOwner.init(context);
        return ProcessLifecycleOwner.get();
    }

    @NonNull
    @Override
    public List<Class<? extends Initializer<?>>> dependencies() {
        return Collections.emptyList();
    }
}

And the commit that made it use androidx.startup in 2021-03 says this:

"lifecycle-process now uses androidx.startup to initialize process lifecycle owner.

Previously, this was being done by androidx.lifecycle.ProcessLifecycleOwnerInitializer.

If you used tools:node="remove" the ContentProvider being used to initialize process lifecycle in the past, then you need to do the following instead.

<provider
 android:name="androidx.startup.InitializationProvider"
 android:authorities=\"${applicationId}.androidx-startup"
 android:exported="false" tools:node=\"merge"> <!-- If you are using
 androidx.startup to initialize other components --> 
        <meta-data
          android:name="androidx.lifecycle.ProcessLifecycleInitializer"
          android:value="androidx.startup" /> 
</provider>

(or)


     <!-- If you want to disable androidx.startup completely. -->
     <provider android:name="androidx.startup.InitializationProvider"
     android:authorities="${applicationId}.androidx-startup"
     tools:node="remove"> 
    </provider>

"

So the snippet you added specifically disables the AndroidX StartUp process and therefore your ProcessLifecycleOwner won't get initialized.


By the way, Google did NOT provide a way to manually install the ProcessLifecycleOwner if you disable the automatic start-up process, but to achieve it, you just need to mimic what they are doing. For example, if you needed to use ProcessLifecycleOwner in a multi-process app, then you'd need to not use the ContentProvider.

In that case, you can create a Java file in a package called androidx/lifecycle:

public class ProcessLifecycleInitializerAccessor {
    public static LifecycleOwner initialize(Application context) {
        LifecycleDispatcher.init(context);
        ProcessLifecycleOwner.init(context);
        return ProcessLifecycleOwner.get();
    }
}

But in your place, you probably just have to remove the snippet that removes your ContentProvider.

Brenda answered 16/3, 2022 at 9:40 Comment(5)
Updating the provider block has fixed this issue, thanksLimousine
tools:node="remove" should be removed from ProcessLifecycleInitializer meta-data , otherwise app will crash. Please update your answer @EpicPandaForce.Cruciform
@Cruciform correct, updatedBrenda
@Brenda Just wondering how we can access android/lifecycle and add the above class ?Feverfew
@Feverfew you create a packag called android which contains a package called lifecycle, then if you create a Java class, it can access those functions because they are merely package-internal.Brenda
F
8

There was an upgrade were androidx.lifecycle started using androidx.startup to initialize. So, if this code was in your manifest:

<provider
    android:name="androidx.startup.InitializationProvider"
    android:authorities="${applicationId}.androidx-startup"
    tools:node="remove" />

Then you can completely remove that code, or use tools:node="merge" instead of remove.

You need to verify in the Merged Manifest that androidx.lifecycle.ProcessLifecycleInitializer is being initialized.

Fumigate answered 11/4, 2022 at 15:36 Comment(0)
I
8

if you are using lifecyle library, add this

def lifecycle_version = "2.5.1"    
implementation "androidx.lifecycle:lifecycle-process:$lifecycle_version"
Insider answered 26/10, 2022 at 15:43 Comment(0)
B
4

My workaround might not work for everyone. But here's the basic idea. Note, my app is using WorkManager.

Step 1:

Change

def lifecycle_version = '2.2.0'
// ViewModel and LiveData
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"

to

def lifecycle_version = '2.5.1'
// ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
// LiveData
implementation "androidx.lifecycle:lifecycle-livedata:$lifecycle_version"
// optional - ProcessLifecycleOwner provides a lifecycle for the whole application process
implementation "androidx.lifecycle:lifecycle-process:$lifecycle_version"

Step 2:

Change

<!-- https://developer.android.com/topic/libraries/architecture/workmanager/advanced/custom-configuration -->
<!-- If you want to disable android.startup completely. -->
<provider
    android:name="androidx.startup.InitializationProvider"
    android:authorities="${applicationId}.androidx-startup"
    tools:node="remove">
</provider>

to

<!-- https://developer.android.com/topic/libraries/architecture/workmanager/advanced/custom-configuration -->
<provider
    android:name="androidx.startup.InitializationProvider"
    android:authorities="${applicationId}.androidx-startup"
    android:exported="false"
    tools:node="merge">
    <!-- If you are using androidx.startup to initialize other components -->
    <meta-data
        android:name="androidx.work.WorkManagerInitializer"
        android:value="androidx.startup"
        tools:node="remove" />
</provider>
Bags answered 11/1, 2023 at 3:22 Comment(0)
A
1

I got this problem when I disabled databinding.

Adding this solved it

implementation "androidx.lifecycle:lifecycle-process:$lifecycle_version"
Auspice answered 21/9, 2023 at 10:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.