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