Skip to content

Commit b527ae8

Browse files
authored
Merge pull request livecode#7339 from livecodemichael/feature-android_lifecycle_events
[[ LifecycleListeners ]] Allow lcb widgets to register and listen for Android lifecycle events
2 parents c040fb3 + 8cd3d53 commit b527ae8

File tree

4 files changed

+181
-8
lines changed

4 files changed

+181
-8
lines changed

engine/src/java/com/runrev/android/Engine.java

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,12 @@
7979

8080
public class Engine extends View implements EngineApi
8181
{
82+
public interface LifecycleListener
83+
{
84+
public abstract void OnResume();
85+
public abstract void OnPause();
86+
}
87+
8288
public static final String TAG = "revandroid.Engine";
8389

8490
// This is true if the engine is not suspended.
@@ -143,6 +149,8 @@ public class Engine extends View implements EngineApi
143149

144150
private int m_night_mode;
145151

152+
private List<LifecycleListener> m_lifecycle_listeners;
153+
146154
////////////////////////////////////////////////////////////////////////////////
147155

148156
public Engine(Context p_context)
@@ -248,6 +256,8 @@ public void onScreenOrientationChanged(int orientation)
248256
m_night_mode =
249257
p_context.getResources().getConfiguration().uiMode &
250258
Configuration.UI_MODE_NIGHT_MASK;
259+
260+
m_lifecycle_listeners = new ArrayList<LifecycleListener>();
251261
}
252262

253263
////////////////////////////////////////////////////////////////////////////////
@@ -3368,6 +3378,14 @@ public void onAppLaunched()
33683378

33693379
public void onPause()
33703380
{
3381+
/* Pause registered listeners in reverse order of registration as
3382+
* then components will be paused before any components they
3383+
* depend on. */
3384+
for (int i = m_lifecycle_listeners.size() - 1; i >= 0; i--)
3385+
{
3386+
m_lifecycle_listeners.get(i).OnPause();
3387+
}
3388+
33713389
if (m_text_editor_visible)
33723390
hideKeyboard();
33733391

@@ -3440,7 +3458,15 @@ public void onResume()
34403458

34413459
// IM-2013-08-16: [[ Bugfix 11103 ]] dispatch any remote notifications received while paused
34423460
dispatchNotifications();
3443-
3461+
3462+
/* Resume registered listeners in order of registration as then
3463+
* components will be resumed before any components which depend
3464+
* on them. */
3465+
for (int i = 0; i < m_lifecycle_listeners.size(); i++)
3466+
{
3467+
m_lifecycle_listeners.get(i).OnResume();
3468+
}
3469+
34443470
if (m_wake_on_event)
34453471
doProcess(false);
34463472
}
@@ -3994,7 +4020,31 @@ public int getSystemAppearance()
39944020
return 0;
39954021
}
39964022
}
3997-
4023+
4024+
////////////////////////////////////////////////////////////////////////////////
4025+
4026+
public boolean registerLifecycleListener(LifecycleListener p_listener)
4027+
{
4028+
return m_lifecycle_listeners.add(p_listener);
4029+
}
4030+
4031+
public boolean unregisterLifecycleListener(LifecycleListener p_listener)
4032+
{
4033+
/* We can't remove the listener directly since LifecycleListener does
4034+
* not implement equals. Instead, search backwards through the array
4035+
* until we find the passed listener. */
4036+
for (int i = m_lifecycle_listeners.size() - 1; i >= 0; i--)
4037+
{
4038+
if (m_lifecycle_listeners.get(i) == p_listener)
4039+
{
4040+
m_lifecycle_listeners.remove(i);
4041+
return true;
4042+
}
4043+
}
4044+
4045+
return false;
4046+
}
4047+
39984048
////////////////////////////////////////////////////////////////////////////////
39994049

40004050
// url launch callback

extensions/modules/android-utils/android-utils.lcb

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,4 +232,109 @@ public handler AndroidHasPermission(in pPermission as String) returns Boolean
232232
return tHasPermission
233233
end handler
234234

235+
public handler type OnPauseHandler() returns nothing
236+
public handler type OnResumeHandler() returns nothing
237+
238+
__safe foreign handler _JNI_Engine_LifecycleListener(in pListener as Array) returns JObject \
239+
binds to "java:com.runrev.android.Engine$LifecycleListener>interface()"
240+
__safe foreign handler _JNI_Engine_RegisterLifecycleListener(in pSelf as JObject, in pListener as JObject) returns JBoolean \
241+
binds to "java:com.runrev.android.Engine>registerLifecycleListener(Lcom/runrev/android/Engine$LifecycleListener;)Z"
242+
__safe foreign handler _JNI_Engine_UnregisterLifecycleListener(in pSelf as JObject, in pListener as JObject) returns JBoolean \
243+
binds to "java:com.runrev.android.Engine>unregisterLifecycleListener(Lcom/runrev/android/Engine$LifecycleListener;)Z"
244+
245+
/**
246+
Summary:
247+
Register handlers to be called when on application lifecycle events.
248+
249+
Parameters:
250+
pPauseHandler: The handler to be called when the application is paused
251+
pResumeHandler: The handler to be called when the application is resumed
252+
253+
Returns:
254+
A listener object that wraps the registered handlers.
255+
256+
Example:
257+
private variable mLifecycleListener as optional JObject
258+
259+
public handler OnOpen() returns nothing
260+
put AndroidRegisterLifecycleListener(OnMyWidgetPaused, OnMyWidgetResumed) into mLifecycleListener
261+
end handler
262+
263+
public handler OnClose() returns nothing
264+
AndroidUnregisterLifecycleListener(mLifecycleListener)
265+
put nothing into mLifecycleListener
266+
end handler
267+
268+
private handler OnMyWidgetPaused() returns nothing
269+
-- Perform pause actions
270+
end handler
271+
272+
private handler OnMyWidgetResumed() returns nothing
273+
-- Perform resume actions
274+
end handler
275+
276+
Description:
277+
Use the <AndroidRegisterLifecycleListener> handler to register handlers to
278+
application lifecycle events. The handler <pPauseHandler> will be called when
279+
the application is paused and enters into the background. The handler
280+
<pResumeHandler> will be called when the application is resumed and returns from
281+
the background.
282+
283+
A listener object will be returned that wraps the registered handlers and can be
284+
used with <AndroidUnregisterLifecycleListener> to cancel the registration.
285+
*/
286+
public handler AndroidRegisterLifecycleListener(in pPauseHandler as OnPauseHandler, in pResumeHandler as OnResumeHandler) returns JObject
287+
variable tEngine as JObject
288+
put _JNI_GetAndroidEngine() into tEngine
289+
290+
variable tLifecycleListenerHandler as Array
291+
put { \
292+
"OnPause": pPauseHandler, \
293+
"OnResume": pResumeHandler \
294+
} into tLifecycleListenerHandler
295+
296+
variable tLifecycleListener as JObject
297+
put _JNI_Engine_LifecycleListener(tLifecycleListenerHandler) \
298+
into tLifecycleListener
299+
300+
_JNI_Engine_RegisterLifecycleListener(tEngine, tLifecycleListener)
301+
return tLifecycleListener
302+
end handler
303+
304+
/**
305+
Summary:
306+
Unregister an object that is listening on application lifecycle events.
307+
308+
Parameters:
309+
pListener: The listener object to be unregistered
310+
311+
Returns:
312+
True if the listener object was previously registered and has been successfully
313+
unregistered.
314+
315+
Example:
316+
private variable mLifecycleListener as optional JObject
317+
318+
public handler OnOpen() returns nothing
319+
put AndroidRegisterLifecycleListener(OnMyWidgetPaused, OnMyWidgetResumed) into mLifecycleListener
320+
end handler
321+
322+
public handler OnClose() returns nothing
323+
AndroidUnregisterLifecycleListener(mLifecycleListener)
324+
put nothing into mLifecycleListener
325+
end handler
326+
327+
Description:
328+
Use the <AndroidUnregisterLifecycleListener> handler to unregister an object
329+
created with <AndroidRegisterLifecycleListener> that is listening to application
330+
lifecycle events. This will have the effect that any handlers that the listener
331+
object is wrapping will no longer be called.
332+
*/
333+
public handler AndroidUnregisterLifecycleListener(in pListener as JObject) returns Boolean
334+
variable tEngine as JObject
335+
put _JNI_GetAndroidEngine() into tEngine
336+
337+
return _JNI_Engine_UnregisterLifecycleListener(tEngine, pListener)
338+
end handler
339+
235340
end module
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Registering for lifecycle SensorEventListener
2+
3+
A new handler `AndroidRegisterLifecycleListener` has been added that allows for
4+
widgets to track application lifecycle events, specifying handlers to be called
5+
when the application is paused or resumed. The first parameter is the handler to
6+
be called when the application is paused. The second parameter is the handler to
7+
be called when the application is resumed.
8+
9+
The listener object returned by `AndroidRegisterLifecycleListener` can be
10+
unregistered by calling `AndroidUnregisterLifecycleListener`, meaning the pause
11+
and resume handlers will no longer be called.

ide-support/revdocsparser.livecodescript

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -520,13 +520,20 @@ on revDocsExtractDocBlocks pText, pSource, @rAPIData, @rLibraryData
520520
break
521521
case "public"
522522
if word 2 of tLine is "handler" then
523-
put "handler" into tEntryData["type"]
524-
# eat the word 'public'
525-
put word 2 to -1 of tLine into tLine
526-
put token 2 of tLine into tEntryData["name"]
523+
if word 3 of tLine is "type" then
524+
put true into tEntryData["private"]
525+
put "type" into tEntryData["type"]
526+
put word 3 to -1 of tLine into tLine
527+
put true into tEntryEnded
528+
else
529+
put "handler" into tEntryData["type"]
530+
# eat the word 'public'
531+
put word 2 to -1 of tLine into tLine
532+
put token 2 of tLine into tEntryData["name"]
527533

528-
# If we have a widget, then public handlers are not in the message path and so don't need docs.
529-
put not tIsWidget into tEntryData["need_docs"]
534+
# If we have a widget, then public handlers are not in the message path and so don't need docs.
535+
put not tIsWidget into tEntryData["need_docs"]
536+
end if
530537
else
531538
put true into tEntryData["private"]
532539
if word 2 of tLine is "foreign" then

0 commit comments

Comments
 (0)