1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package androidx.lifecycle
17 
18 import android.app.Activity
19 import android.app.Application
20 import android.os.Build
21 import android.os.Bundle
22 import androidx.annotation.RequiresApi
23 import androidx.annotation.RestrictTo
24 
25 /** Internal class that dispatches initialization events. */
26 @Suppress("DEPRECATION", "OVERRIDE_DEPRECATION")
27 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
28 public open class ReportFragment() : android.app.Fragment() {
29     private var processListener: ActivityInitializationListener? = null
30 
dispatchCreatenull31     private fun dispatchCreate(listener: ActivityInitializationListener?) {
32         listener?.onCreate()
33     }
34 
dispatchStartnull35     private fun dispatchStart(listener: ActivityInitializationListener?) {
36         listener?.onStart()
37     }
38 
dispatchResumenull39     private fun dispatchResume(listener: ActivityInitializationListener?) {
40         listener?.onResume()
41     }
42 
onActivityCreatednull43     override fun onActivityCreated(savedInstanceState: Bundle?) {
44         super.onActivityCreated(savedInstanceState)
45         dispatchCreate(processListener)
46         dispatch(Lifecycle.Event.ON_CREATE)
47     }
48 
onStartnull49     override fun onStart() {
50         super.onStart()
51         dispatchStart(processListener)
52         dispatch(Lifecycle.Event.ON_START)
53     }
54 
onResumenull55     override fun onResume() {
56         super.onResume()
57         dispatchResume(processListener)
58         dispatch(Lifecycle.Event.ON_RESUME)
59     }
60 
onPausenull61     override fun onPause() {
62         super.onPause()
63         dispatch(Lifecycle.Event.ON_PAUSE)
64     }
65 
onStopnull66     override fun onStop() {
67         super.onStop()
68         dispatch(Lifecycle.Event.ON_STOP)
69     }
70 
onDestroynull71     override fun onDestroy() {
72         super.onDestroy()
73         dispatch(Lifecycle.Event.ON_DESTROY)
74         // just want to be sure that we won't leak reference to an activity
75         processListener = null
76     }
77 
dispatchnull78     private fun dispatch(event: Lifecycle.Event) {
79         if (Build.VERSION.SDK_INT < 29) {
80             // Only dispatch events from ReportFragment on API levels prior
81             // to API 29. On API 29+, this is handled by the ActivityLifecycleCallbacks
82             // added in ReportFragment.injectIfNeededIn
83             dispatch(activity, event)
84         }
85     }
86 
setProcessListenernull87     public fun setProcessListener(processListener: ActivityInitializationListener?) {
88         this.processListener = processListener
89     }
90 
91     public interface ActivityInitializationListener {
onCreatenull92         public fun onCreate()
93 
94         public fun onStart()
95 
96         public fun onResume()
97     }
98 
99     // this class isn't inlined only because we need to add a proguard rule for it (b/142778206)
100     // In addition to that registerIn method allows to avoid class verification failure,
101     // because registerActivityLifecycleCallbacks is available only since api 29.
102     @RequiresApi(29)
103     internal class LifecycleCallbacks : Application.ActivityLifecycleCallbacks {
104         override fun onActivityCreated(activity: Activity, bundle: Bundle?) {}
105 
106         override fun onActivityPostCreated(activity: Activity, savedInstanceState: Bundle?) {
107             dispatch(activity, Lifecycle.Event.ON_CREATE)
108         }
109 
110         override fun onActivityStarted(activity: Activity) {}
111 
112         override fun onActivityPostStarted(activity: Activity) {
113             dispatch(activity, Lifecycle.Event.ON_START)
114         }
115 
116         override fun onActivityResumed(activity: Activity) {}
117 
118         override fun onActivityPostResumed(activity: Activity) {
119             dispatch(activity, Lifecycle.Event.ON_RESUME)
120         }
121 
122         override fun onActivityPrePaused(activity: Activity) {
123             dispatch(activity, Lifecycle.Event.ON_PAUSE)
124         }
125 
126         override fun onActivityPaused(activity: Activity) {}
127 
128         override fun onActivityPreStopped(activity: Activity) {
129             dispatch(activity, Lifecycle.Event.ON_STOP)
130         }
131 
132         override fun onActivityStopped(activity: Activity) {}
133 
134         override fun onActivitySaveInstanceState(activity: Activity, bundle: Bundle) {}
135 
136         override fun onActivityPreDestroyed(activity: Activity) {
137             dispatch(activity, Lifecycle.Event.ON_DESTROY)
138         }
139 
140         override fun onActivityDestroyed(activity: Activity) {}
141 
142         companion object {
143             @JvmStatic
144             fun registerIn(activity: Activity) {
145                 activity.registerActivityLifecycleCallbacks(LifecycleCallbacks())
146             }
147         }
148     }
149 
150     public companion object {
151         private const val REPORT_FRAGMENT_TAG =
152             "androidx.lifecycle.LifecycleDispatcher.report_fragment_tag"
153 
154         @JvmStatic
injectIfNeededInnull155         public fun injectIfNeededIn(activity: Activity) {
156             if (Build.VERSION.SDK_INT >= 29) {
157                 // On API 29+, we can register for the correct Lifecycle callbacks directly
158                 LifecycleCallbacks.registerIn(activity)
159             }
160             // Prior to API 29 and to maintain compatibility with older versions of
161             // ProcessLifecycleOwner (which may not be updated when lifecycle-runtime is updated and
162             // need to support activities that don't extend from FragmentActivity from support lib),
163             // use a framework fragment to get the correct timing of Lifecycle events
164             val manager = activity.fragmentManager
165             if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {
166                 manager.beginTransaction().add(ReportFragment(), REPORT_FRAGMENT_TAG).commit()
167                 // Hopefully, we are the first to make a transaction.
168                 manager.executePendingTransactions()
169             }
170         }
171 
172         @JvmStatic
dispatchnull173         internal fun dispatch(activity: Activity, event: Lifecycle.Event) {
174             if (activity is LifecycleRegistryOwner) {
175                 activity.lifecycle.handleLifecycleEvent(event)
176                 return
177             }
178             if (activity is LifecycleOwner) {
179                 val lifecycle = (activity as LifecycleOwner).lifecycle
180                 if (lifecycle is LifecycleRegistry) {
181                     lifecycle.handleLifecycleEvent(event)
182                 }
183             }
184         }
185 
186         @JvmStatic
187         @get:JvmName("get")
188         public val Activity.reportFragment: ReportFragment
189             get() {
190                 return this.fragmentManager.findFragmentByTag(REPORT_FRAGMENT_TAG) as ReportFragment
191             }
192     }
193 }
194