How to dispatch a custom event to corona runtime on android?

Hi,

Kim ended up storing the listener and dispatcher in 2 static variables to be able to asynchronously call back to the lua listener passed in when the plugin is inited. Works fine so far. Any reason not to do it like that? We also thought about creating a singleton for it. [import]uid: 21746 topic_id: 33865 reply_id: 137421[/import]

Haakon,

There is one thing you have to watch out for on Android that behaves differently compared to iOS.

The CoronaRuntime and its LuaState is tied to the CoronaActivity’s lifecycle and not the Application. That is, when you launch a new CoronaActivity, then a new CoronaRuntime and LuaState object gets created. When you tap “back” to exit the CoronaActivity, the CoronaRuntime and its LuaState are disposed of and dereferenced to be garbage collected, but your app’s process, its Application object, and all of its static variables remain alive. So, the next time you tap your app icon to launch a new CoronaActivity (while your app process is still running in the background), a new CoronaRuntime and LuaState object gets created.

The thing you got to watch out for then is that the CoronaRuntimeTaskDispatcher can only send tasks to the CoronaRuntime that you fed into its constructor. Once that CoronaRuntime has been disposed of, which happens when you back out of a CoronaActivity, then the dispatcher will stop working and no-op when you call its send() method from then on, which is by design.
Note: You can determine if the dispatcher’s target is still available (ie: not disposed of) by calling the dispatcher’s isRuntimeAvailable() method.
http://docs.coronalabs.com/native/android/html/com/ansca/corona/CoronaRuntimeTaskDispatcher.html

This means that the next time a CoronaActivity gets launched, you’ll need to replace your dispatcher object with a new one that target’s the CoronaActivity’s new CoronaRuntime object. So, it’s okay to store the dispatcher object to a static variable. Just make sure to update it.

Setting up a global CoronaRuntimeListener like you’re doing is the easiest way to handle runtime events. It’s onLoaded() method will be called every time a new CoronaRuntime object has been created, so that is where you need to create a new dispatcher and replace your old one.

Anyways, I hope this helps!
[import]uid: 32256 topic_id: 33865 reply_id: 137458[/import]

Joshua,

that helps a lot, it confirms the things we had guessed, thank you. [import]uid: 21746 topic_id: 33865 reply_id: 137486[/import]

We’re having some issues with the async stuff on Android…

We used that to create an event dispatcher and it works like a charm on our devices.
So, we went ahead an published a live app with that same dispatcher…

Now, we also have Crittercism implemented for live error logging, and we see that the dispatch event function fails on this call (with a NullPointerException)

// Post a Runnable object on the UI thread that will call the given Lua function.  
com.ansca.corona.CoronaEnvironment.getCoronaActivity().runOnUiThread(new Runnable() {  

We assume that the getCoronaActivity() is returning null.
We have not been able to replicate the issue, but around 10% off all appstarts generate this error( from google play downloaded versions ).

Any insights on this?
Please note that the dispatch isn’t something that is fired on app shutdown or anything like it.
[import]uid: 63706 topic_id: 33865 reply_id: 139325[/import]

The [lua]getCoronaActivity()[/lua] method will return null if you back out of the activity. There is a race condition that you can run into where if the user starts up your app and then immediately backs out of your app, causing this method to return null while your app is still finishing executing your “main.lua” file. (I hope that explanation made sense.)

In which case, you should check the returned result like this…
[java]
CoronaActivity activity = CoronaEnvironment.getCoronaActivity();
if (activity != null) {
activity.runOnUiThread(new Runnable() { /* Your code goes here… */ });
}
[/java]

You’ll want to store the activity to a local variable as shown above in case [lua]getCoronaActivity()[/lua] suddenly returns null after the [lua]if[/lua] check (ie: that’s the race condition that you have to watch out for). In which case, that local activity variable will keep the object alive by holding on to a reference to it until it falls out of scope in that method.
[import]uid: 32256 topic_id: 33865 reply_id: 139362[/import]

Yepp, thanks :slight_smile:

I saw that activity null check in the LuaError sample, so I did the same thing in our dispatcher, also I surrounded the entire call with a try{}catch(), it’s been quiet since then.

We thought that the race condition you mentioned might have been the culprit, it just sounded a bit freaky that 10% of the afternoons Android users would back right out of the app after bootup.

Thanks for confirming though! [import]uid: 63706 topic_id: 33865 reply_id: 139364[/import]

Happy to help!

Yeah, we have to do the same if checks in our own internal code as well. And we try to make multithreaded development with Corona as easy as possible via our [lua]CoronaRuntimeTaskDispatcher[/lua] class well, because it has its own built in safety mechanisms. It’s still a bit of a pain, but unfortunately that’s how it has to work on Android at the moment. [import]uid: 32256 topic_id: 33865 reply_id: 139378[/import]

We’re having some issues with the async stuff on Android…

We used that to create an event dispatcher and it works like a charm on our devices.
So, we went ahead an published a live app with that same dispatcher…

Now, we also have Crittercism implemented for live error logging, and we see that the dispatch event function fails on this call (with a NullPointerException)

// Post a Runnable object on the UI thread that will call the given Lua function.  
com.ansca.corona.CoronaEnvironment.getCoronaActivity().runOnUiThread(new Runnable() {  

We assume that the getCoronaActivity() is returning null.
We have not been able to replicate the issue, but around 10% off all appstarts generate this error( from google play downloaded versions ).

Any insights on this?
Please note that the dispatch isn’t something that is fired on app shutdown or anything like it.
[import]uid: 63706 topic_id: 33865 reply_id: 139325[/import]

The [lua]getCoronaActivity()[/lua] method will return null if you back out of the activity. There is a race condition that you can run into where if the user starts up your app and then immediately backs out of your app, causing this method to return null while your app is still finishing executing your “main.lua” file. (I hope that explanation made sense.)

In which case, you should check the returned result like this…
[java]
CoronaActivity activity = CoronaEnvironment.getCoronaActivity();
if (activity != null) {
activity.runOnUiThread(new Runnable() { /* Your code goes here… */ });
}
[/java]

You’ll want to store the activity to a local variable as shown above in case [lua]getCoronaActivity()[/lua] suddenly returns null after the [lua]if[/lua] check (ie: that’s the race condition that you have to watch out for). In which case, that local activity variable will keep the object alive by holding on to a reference to it until it falls out of scope in that method.
[import]uid: 32256 topic_id: 33865 reply_id: 139362[/import]

Yepp, thanks :slight_smile:

I saw that activity null check in the LuaError sample, so I did the same thing in our dispatcher, also I surrounded the entire call with a try{}catch(), it’s been quiet since then.

We thought that the race condition you mentioned might have been the culprit, it just sounded a bit freaky that 10% of the afternoons Android users would back right out of the app after bootup.

Thanks for confirming though! [import]uid: 63706 topic_id: 33865 reply_id: 139364[/import]

Happy to help!

Yeah, we have to do the same if checks in our own internal code as well. And we try to make multithreaded development with Corona as easy as possible via our [lua]CoronaRuntimeTaskDispatcher[/lua] class well, because it has its own built in safety mechanisms. It’s still a bit of a pain, but unfortunately that’s how it has to work on Android at the moment. [import]uid: 32256 topic_id: 33865 reply_id: 139378[/import]

Any news about this?
Is there anything like the CoronaLuaRuntimeDispatchEvent for the Android version?

I am trying this:

 LuaState L = \_runtime.getLuaState(); String eventTable = Map\_Lua.mapToLuaString(map); --Receives a map and transform it into a lua table L.load("function dispatchMyEvent() Runtime:dispatchEvent(" + eventTable + ") end","=simple"); L.call(0,0); L.getGlobal("dispatchMyEvent"); L.call(0,0);

based on http://forums.coronalabs.com/topic/46402-a-new-dirty-and-amazingly-efficient-way-to-call-a-lua-function-from-your-native-android-code/

On Android, we have a “CoronaLua” Java class which has newEvent() and dispatchEvent() methods which provide similar functionality.  Documentation for this Java API can be found here…

   http://docs.coronalabs.com/native/android/html/com/ansca/corona/CoronaLua.html

Just remember that the Corona runtime does *not* run on the main UI thread.  So, if you’ve received a native event on a different thread, then you should use our “CoronaRuntimeTaskDispatcher” Java class to dispatch a task to be executed on the Corona runtime’s thread, which gives you safe access to the Lua state.

   http://docs.coronalabs.com/native/android/html/com/ansca/corona/CoronaRuntimeTaskDispatcher.html

An example on how to use the CoronaRuntimeTaskDispatcher to handle async operations can be found in Corona Enterprise’s “SimpleLuaExtension” sample project.  Please see its “AsyncCallLuaFunction.java” file.

Any news about this?
Is there anything like the CoronaLuaRuntimeDispatchEvent for the Android version?

I am trying this:

 LuaState L = \_runtime.getLuaState(); String eventTable = Map\_Lua.mapToLuaString(map); --Receives a map and transform it into a lua table L.load("function dispatchMyEvent() Runtime:dispatchEvent(" + eventTable + ") end","=simple"); L.call(0,0); L.getGlobal("dispatchMyEvent"); L.call(0,0);

based on http://forums.coronalabs.com/topic/46402-a-new-dirty-and-amazingly-efficient-way-to-call-a-lua-function-from-your-native-android-code/

On Android, we have a “CoronaLua” Java class which has newEvent() and dispatchEvent() methods which provide similar functionality.  Documentation for this Java API can be found here…

   http://docs.coronalabs.com/native/android/html/com/ansca/corona/CoronaLua.html

Just remember that the Corona runtime does *not* run on the main UI thread.  So, if you’ve received a native event on a different thread, then you should use our “CoronaRuntimeTaskDispatcher” Java class to dispatch a task to be executed on the Corona runtime’s thread, which gives you safe access to the Lua state.

   http://docs.coronalabs.com/native/android/html/com/ansca/corona/CoronaRuntimeTaskDispatcher.html

An example on how to use the CoronaRuntimeTaskDispatcher to handle async operations can be found in Corona Enterprise’s “SimpleLuaExtension” sample project.  Please see its “AsyncCallLuaFunction.java” file.