@@ -61,3 +61,154 @@ def unbind(**kwargs):
6161 _activity .unregisterNewIntentListener (listener )
6262 elif event == 'on_activity_result' :
6363 _activity .unregisterActivityResultListener (listener )
64+
65+
66+ # Keep a reference to all the registered classes so that python doesn't
67+ # garbage collect them.
68+ _lifecycle_callbacks = set ()
69+
70+
71+ class ActivityLifecycleCallbacks (PythonJavaClass ):
72+ """Callback class for handling PythonActivity lifecycle transitions"""
73+
74+ __javainterfaces__ = ['android/app/Application$ActivityLifecycleCallbacks' ]
75+
76+ def __init__ (self , callbacks ):
77+ super ().__init__ ()
78+
79+ # It would be nice to use keyword arguments, but PythonJavaClass
80+ # doesn't allow that in its __cinit__ method.
81+ if not isinstance (callbacks , dict ):
82+ raise ValueError ('callbacks must be a dict instance' )
83+ self .callbacks = callbacks
84+
85+ def _callback (self , name , * args ):
86+ func = self .callbacks .get (name )
87+ if func :
88+ return func (* args )
89+
90+ @java_method ('(Landroid/app/Activity;Landroid/os/Bundle;)V' )
91+ def onActivityCreated (self , activity , savedInstanceState ):
92+ self ._callback ('onActivityCreated' , activity , savedInstanceState )
93+
94+ @java_method ('(Landroid/app/Activity;)V' )
95+ def onActivityDestroyed (self , activity ):
96+ self ._callback ('onActivityDestroyed' , activity )
97+
98+ @java_method ('(Landroid/app/Activity;)V' )
99+ def onActivityPaused (self , activity ):
100+ self ._callback ('onActivityPaused' , activity )
101+
102+ @java_method ('(Landroid/app/Activity;Landroid/os/Bundle;)V' )
103+ def onActivityPostCreated (self , activity , savedInstanceState ):
104+ self ._callback ('onActivityPostCreated' , activity , savedInstanceState )
105+
106+ @java_method ('(Landroid/app/Activity;)V' )
107+ def onActivityPostDestroyed (self , activity ):
108+ self ._callback ('onActivityPostDestroyed' , activity )
109+
110+ @java_method ('(Landroid/app/Activity;)V' )
111+ def onActivityPostPaused (self , activity ):
112+ self ._callback ('onActivityPostPaused' , activity )
113+
114+ @java_method ('(Landroid/app/Activity;)V' )
115+ def onActivityPostResumed (self , activity ):
116+ self ._callback ('onActivityPostResumed' , activity )
117+
118+ @java_method ('(Landroid/app/Activity;Landroid/os/Bundle;)V' )
119+ def onActivityPostSaveInstanceState (self , activity , outState ):
120+ self ._callback ('onActivityPostSaveInstanceState' , activity , outState )
121+
122+ @java_method ('(Landroid/app/Activity;)V' )
123+ def onActivityPostStarted (self , activity ):
124+ self ._callback ('onActivityPostStarted' , activity )
125+
126+ @java_method ('(Landroid/app/Activity;)V' )
127+ def onActivityPostStopped (self , activity ):
128+ self ._callback ('onActivityPostStopped' , activity )
129+
130+ @java_method ('(Landroid/app/Activity;Landroid/os/Bundle;)V' )
131+ def onActivityPreCreated (self , activity , savedInstanceState ):
132+ self ._callback ('onActivityPreCreated' , activity , savedInstanceState )
133+
134+ @java_method ('(Landroid/app/Activity;)V' )
135+ def onActivityPreDestroyed (self , activity ):
136+ self ._callback ('onActivityPreDestroyed' , activity )
137+
138+ @java_method ('(Landroid/app/Activity;)V' )
139+ def onActivityPrePaused (self , activity ):
140+ self ._callback ('onActivityPrePaused' , activity )
141+
142+ @java_method ('(Landroid/app/Activity;)V' )
143+ def onActivityPreResumed (self , activity ):
144+ self ._callback ('onActivityPreResumed' , activity )
145+
146+ @java_method ('(Landroid/app/Activity;Landroid/os/Bundle;)V' )
147+ def onActivityPreSaveInstanceState (self , activity , outState ):
148+ self ._callback ('onActivityPreSaveInstanceState' , activity , outState )
149+
150+ @java_method ('(Landroid/app/Activity;)V' )
151+ def onActivityPreStarted (self , activity ):
152+ self ._callback ('onActivityPreStarted' , activity )
153+
154+ @java_method ('(Landroid/app/Activity;)V' )
155+ def onActivityPreStopped (self , activity ):
156+ self ._callback ('onActivityPreStopped' , activity )
157+
158+ @java_method ('(Landroid/app/Activity;)V' )
159+ def onActivityResumed (self , activity ):
160+ self ._callback ('onActivityResumed' , activity )
161+
162+ @java_method ('(Landroid/app/Activity;Landroid/os/Bundle;)V' )
163+ def onActivitySaveInstanceState (self , activity , outState ):
164+ self ._callback ('onActivitySaveInstanceState' , activity , outState )
165+
166+ @java_method ('(Landroid/app/Activity;)V' )
167+ def onActivityStarted (self , activity ):
168+ self ._callback ('onActivityStarted' , activity )
169+
170+ @java_method ('(Landroid/app/Activity;)V' )
171+ def onActivityStopped (self , activity ):
172+ self ._callback ('onActivityStopped' , activity )
173+
174+
175+ def register_activity_lifecycle_callbacks (** callbacks ):
176+ """Register ActivityLifecycleCallbacks instance
177+
178+ The callbacks are supplied as keyword arguments corresponding to the
179+ Application.ActivityLifecycleCallbacks methods such as
180+ onActivityStarted. See the ActivityLifecycleCallbacks documentation
181+ for the signature of each method.
182+
183+ The ActivityLifecycleCallbacks instance is returned so it can be
184+ supplied to unregister_activity_lifecycle_callbacks if needed.
185+ """
186+ instance = ActivityLifecycleCallbacks (callbacks )
187+ _lifecycle_callbacks .add (instance )
188+
189+ # Use the registerActivityLifecycleCallbacks method from the
190+ # Activity class if it's available (API 29) since it guarantees the
191+ # callbacks will only be run for that activity. Otherwise, fallback
192+ # to the method on the Application class (API 14). In practice there
193+ # should be no difference since p4a applications only have a single
194+ # activity.
195+ if hasattr (_activity , 'registerActivityLifecycleCallbacks' ):
196+ _activity .registerActivityLifecycleCallbacks (instance )
197+ else :
198+ app = _activity .getApplication ()
199+ app .registerActivityLifecycleCallbacks (instance )
200+ return instance
201+
202+
203+ def unregister_activity_lifecycle_callbacks (instance ):
204+ """Unregister ActivityLifecycleCallbacks instance"""
205+ if hasattr (_activity , 'unregisterActivityLifecycleCallbacks' ):
206+ _activity .unregisterActivityLifecycleCallbacks (instance )
207+ else :
208+ app = _activity .getApplication ()
209+ app .unregisterActivityLifecycleCallbacks (instance )
210+
211+ try :
212+ _lifecycle_callbacks .remove (instance )
213+ except KeyError :
214+ pass
0 commit comments