Android Native - How to get an updated version of luaState?

Hello,

I am trying to integrate Chartboost in my Android Native Corona App since I am using Enterprise version of Corona.

Making the interstitial banner from Chartboost to appear is not big deal, we only need to initialize it and then show it. My problem is that before showing it I need to check for a global var from the lua state to make my decision, this global var indicates if the game is active or not, this way I can prevent the interstitial ad from appearing in the middle of the game and annoying the players.

I implemented the module chartboost and the lua call is “chartboost.showInterstitial()”. This ends in following java class which implements this function:

public class ChartboostShowInterstitialLuaFunction implements com.naef.jnlua.NamedJavaFunction {
@Override
public String getName() {
return “showInterstitial”;
}

@Override
public int invoke(com.naef.jnlua.LuaState luaState) {
com.ansca.corona.CoronaActivity activity = com.ansca.corona.CoronaEnvironment.getCoronaActivity();
com.chartboost.sdk.ChartBoost cb = com.chartboost.sdk.ChartBoost.getSharedChartBoost(activity);
android.util.Log.d(“Corona”, “SHOW INTERSTITIAL”);
cb.setDelegate(new ChartboostDelegateWithLuaState(luaState));
cb.showInterstitial();
return 0;
}
}

The invoke method do updates the charboost’s context referencing by giving to it the current CoronaActivity, then it sets a Delegate for chartboost from class ChartboostDelegateWithLuaState:

public class ChartboostDelegateWithLuaState extends com.chartboost.sdk.ChartBoostDelegate {
private com.naef.jnlua.LuaState luaState;

public ChartboostDelegateWithLuaState(com.naef.jnlua.LuaState luaState) {
super();
this.luaState = luaState;
}

public boolean shouldDisplayInterstitial(android.view.View interstitialView) {
this.luaState.getGlobal(“gameIsActive”);
boolean gameIsActive = luaState.checkBoolean(-1);
android.util.Log.d(“Corona”, "gameIsActive = " + String.valueOf(gameIsActive));
return !gameIsActive;
}
}

This delegates needs to implement method shouldDisplayInterstitial as the Chartboost’s documentation suggests that gets called before showing the interstitial ad, if I return false in this method the interstitial is not shown. This is where my problem occurs: the global gameIsActive seams to be always false, but the game updates it just after the game starts, which makes me believe the luaState objects needs to be updated in some way to reflect the new value of global var gameIsActive.

Is there a way to perform this update of luaState? Is there any other way of implementing this?

Thanks in advance for any help.

Best regards,
Augusto Souza [import]uid: 133680 topic_id: 32703 reply_id: 332703[/import]

checkBoolean is merely checking if it is a boolean, and not returning the value of the boolean. toBoolean (-1)is the proper function to get the value itself.

Since it’s returning false, it means you have bigger issues (You have the wrong type for that variable). try printing this.luaState.typeName(-1); to verify what type it actually is, and then from there you are going to have to figure out why it’s not a boolean/how to process it using the toType functions to get it’s value.

As far as the original question the luaState is a reference and is valid and up to date for the lifetime of the app from my experience, meaning you can get it once on initialization and keep it. [import]uid: 134101 topic_id: 32703 reply_id: 130014[/import]

I highly recommend that you do NOT hold on to a reference to the luaState object. The luaState object is only active for the lifetime of the Corona activity and NOT the application. Also, the luaState object does not run on the main UI thread, but on a separate thread which is only active while the activity is displayed. This means that you should NEVER access the luaState from the main UI thread like you are doing because you will most definitely run into odd behaviors due to race conditions and crashes.

We provide the following means of accessing the luaState from the Corona runtime on Android:

  1. Via a CoronaRuntimeListener added to the CoronaEnvironment.
  2. Via a JNLua NamedJavaFunction’s invoke method.
  3. Via a CoronaRuntimeTaskDispatcher object.

Have a look at the following sample project for examples on how to do the above. The “AsyncCallLuaFunction.java” file shows you how to post a task from one thread to the Corona runtime’s thread to call a Lua function.
./CoronaEnterprise/Android/SampleProjects/ExtendingLua

To access a global variable in Lua, you would do the following…
[lua]-- Push the following global variable to the top of the Lua stack.
– Note that if it does not exist, then Lua will push nil to the top of the stack.
luaState.getGlobal(“gameIsActive”);

– Fetch the boolean at the top of the stack.
boolean isGameActive = luaState.toBoolean(-1);

– Pop the fetched boolean off of the Lua stack.
– You need to do this even if the global was not found because nil will be pushed in that case.
luaState.pop(1);[/lua]

Just remember that you cannot do the above on the main UI thread. You can only do the above on the Corona runtime’s thread. So, you may have to redesign your app to make this work. I’m thinking that you should keep the “gameIsActive” flag on Java side and not the Lua side and make it accessible on all threads. You can then create Lua functions that get and set the “gameIsActive” state on the Java side. [import]uid: 32256 topic_id: 32703 reply_id: 130023[/import]

checkBoolean is merely checking if it is a boolean, and not returning the value of the boolean. toBoolean (-1)is the proper function to get the value itself.

Since it’s returning false, it means you have bigger issues (You have the wrong type for that variable). try printing this.luaState.typeName(-1); to verify what type it actually is, and then from there you are going to have to figure out why it’s not a boolean/how to process it using the toType functions to get it’s value.

As far as the original question the luaState is a reference and is valid and up to date for the lifetime of the app from my experience, meaning you can get it once on initialization and keep it. [import]uid: 134101 topic_id: 32703 reply_id: 130014[/import]

I highly recommend that you do NOT hold on to a reference to the luaState object. The luaState object is only active for the lifetime of the Corona activity and NOT the application. Also, the luaState object does not run on the main UI thread, but on a separate thread which is only active while the activity is displayed. This means that you should NEVER access the luaState from the main UI thread like you are doing because you will most definitely run into odd behaviors due to race conditions and crashes.

We provide the following means of accessing the luaState from the Corona runtime on Android:

  1. Via a CoronaRuntimeListener added to the CoronaEnvironment.
  2. Via a JNLua NamedJavaFunction’s invoke method.
  3. Via a CoronaRuntimeTaskDispatcher object.

Have a look at the following sample project for examples on how to do the above. The “AsyncCallLuaFunction.java” file shows you how to post a task from one thread to the Corona runtime’s thread to call a Lua function.
./CoronaEnterprise/Android/SampleProjects/ExtendingLua

To access a global variable in Lua, you would do the following…
[lua]-- Push the following global variable to the top of the Lua stack.
– Note that if it does not exist, then Lua will push nil to the top of the stack.
luaState.getGlobal(“gameIsActive”);

– Fetch the boolean at the top of the stack.
boolean isGameActive = luaState.toBoolean(-1);

– Pop the fetched boolean off of the Lua stack.
– You need to do this even if the global was not found because nil will be pushed in that case.
luaState.pop(1);[/lua]

Just remember that you cannot do the above on the main UI thread. You can only do the above on the Corona runtime’s thread. So, you may have to redesign your app to make this work. I’m thinking that you should keep the “gameIsActive” flag on Java side and not the Lua side and make it accessible on all threads. You can then create Lua functions that get and set the “gameIsActive” state on the Java side. [import]uid: 32256 topic_id: 32703 reply_id: 130023[/import]

Thank you very much Joshua, I agree with you this design is better than mine. I changed the logic of flag gameIsActive to be maintained in Java and it worked =) Thanks!

But, I have a doubt with the checkBoolean function. Reading the documentation it seams to check and extract the boolean value:

“public boolean checkBoolean(int index): Checks if the value of the specified function argument is a boolean. If so, the argument value is returned as a boolean. Otherwise, the method throws a Lua runtime exception with a descriptive error message.
Parameters:
index - the argument index
Returns:
the boolean value, or the default value”

Also, from file “PrintBooleanLuaFunction.java” in sample project ExtedingLua I saw the following:
[java]
// Fetch the Lua function’s first argument.
// Will throw an exception if it is not of type boolean.
boolean value = luaState.checkBoolean(1);

// Print the value to the Android logging system.
System.out.println("printBoolean(): value = " + Boolean.toString(value));
[/java]

I really need to call luaState.toBoolean(-1) and luaState.pop(1)? Isn’t checkBoolean enough?

Best regards.
[import]uid: 133680 topic_id: 32703 reply_id: 130058[/import]

Thank you very much Joshua, I agree with you this design is better than mine. I changed the logic of flag gameIsActive to be maintained in Java and it worked =) Thanks!

But, I have a doubt with the checkBoolean function. Reading the documentation it seams to check and extract the boolean value:

“public boolean checkBoolean(int index): Checks if the value of the specified function argument is a boolean. If so, the argument value is returned as a boolean. Otherwise, the method throws a Lua runtime exception with a descriptive error message.
Parameters:
index - the argument index
Returns:
the boolean value, or the default value”

Also, from file “PrintBooleanLuaFunction.java” in sample project ExtedingLua I saw the following:
[java]
// Fetch the Lua function’s first argument.
// Will throw an exception if it is not of type boolean.
boolean value = luaState.checkBoolean(1);

// Print the value to the Android logging system.
System.out.println("printBoolean(): value = " + Boolean.toString(value));
[/java]

I really need to call luaState.toBoolean(-1) and luaState.pop(1)? Isn’t checkBoolean enough?

Best regards.
[import]uid: 133680 topic_id: 32703 reply_id: 130058[/import]

I’m glad you got it working!

Regarding fetching the boolean value from Lua, both [lua]luaState.toBoolean()[/lua] and [lua]luaState.checkBoolean()[/lua] will do this. The difference is that [lua]luaState.checkBoolean()[/lua] will validate the value and if it is not of type boolean then it will throw an exception, just as you have noted.

The [lua]luaState.toBoolean()[/lua] method will return false if the Lua value is not of type boolean. So, it will never throw an exception and assumes that you know what you are doing.

Now, if you want to check if the Lua value is of the correct type without exception handling, then you can do the following…
[lua]com.naef.jnlua.LuaType luaType = luaState.type(-1);
if (luaType == com.naef.jnlua.LuaType.BOOLEAN) {
boolean flag = luaState.toBoolean(-1);
}[/lua]

The above is the safest way of doing it. Especially if you can’t assume the type of the Lua value that you have been given. A good example of this is in our “PrintTableLuaFunction.java” in our “ExtendingLua” sample project. That code loops through all of the entries in a Lua table containing a mix of types.

I hope this helps! [import]uid: 32256 topic_id: 32703 reply_id: 130101[/import]

I’m glad you got it working!

Regarding fetching the boolean value from Lua, both [lua]luaState.toBoolean()[/lua] and [lua]luaState.checkBoolean()[/lua] will do this. The difference is that [lua]luaState.checkBoolean()[/lua] will validate the value and if it is not of type boolean then it will throw an exception, just as you have noted.

The [lua]luaState.toBoolean()[/lua] method will return false if the Lua value is not of type boolean. So, it will never throw an exception and assumes that you know what you are doing.

Now, if you want to check if the Lua value is of the correct type without exception handling, then you can do the following…
[lua]com.naef.jnlua.LuaType luaType = luaState.type(-1);
if (luaType == com.naef.jnlua.LuaType.BOOLEAN) {
boolean flag = luaState.toBoolean(-1);
}[/lua]

The above is the safest way of doing it. Especially if you can’t assume the type of the Lua value that you have been given. A good example of this is in our “PrintTableLuaFunction.java” in our “ExtendingLua” sample project. That code loops through all of the entries in a Lua table containing a mix of types.

I hope this helps! [import]uid: 32256 topic_id: 32703 reply_id: 130101[/import]

Thank you very much, Joshua.

Regarding these problems with corona runtime. I am with another problem now. I am able to avoid chartboost insterstitial ad from being showed using a flag in the java side, as you suggested.

The problem now is that when I call chartboost library asking it to show an ad
[java]
com.chartboost.sdk.ChartBoost cb = com.chartboost.sdk.ChartBoost.getSharedChartBoost(activity);
cb.showInterstitial();
[/java]

This request makes the CoronaApplication to run the onSuspended and after closing the ad to run the onResumed. Since, I pause the game when applicationSuspend runs in the lua side (as a feature for the user so she can go out of the app and return without losing the game state), I can avoid the ad to be showed during the game by using the flag but I am not able right now to avoid it from pausing since the applicationSuspend and applicationResume are both called.

I tried to run cb.showInterstitial() as a task using the dispatcher and in the ui thread too.

Do anyone know how to treat this situation?

Best regards. [import]uid: 133680 topic_id: 32703 reply_id: 130157[/import]

Thank you very much, Joshua.

Regarding these problems with corona runtime. I am with another problem now. I am able to avoid chartboost insterstitial ad from being showed using a flag in the java side, as you suggested.

The problem now is that when I call chartboost library asking it to show an ad
[java]
com.chartboost.sdk.ChartBoost cb = com.chartboost.sdk.ChartBoost.getSharedChartBoost(activity);
cb.showInterstitial();
[/java]

This request makes the CoronaApplication to run the onSuspended and after closing the ad to run the onResumed. Since, I pause the game when applicationSuspend runs in the lua side (as a feature for the user so she can go out of the app and return without losing the game state), I can avoid the ad to be showed during the game by using the flag but I am not able right now to avoid it from pausing since the applicationSuspend and applicationResume are both called.

I tried to run cb.showInterstitial() as a task using the dispatcher and in the ui thread too.

Do anyone know how to treat this situation?

Best regards. [import]uid: 133680 topic_id: 32703 reply_id: 130157[/import]

It sounds like the chartboost interstitial ad is displayed in a separate activity (ie: window). Displaying another activity on Android will pause/stop the previous activity because Android can only display one activity at a time. In this case, it is stopping the CoronaActivity, which will cause it to suspend the Corona runtime because it no longer has a window to render to anymore.

Can chartboost display an ad as a view? As in a view that you can display within the CoronaActivity? That’s the only way to display an ad without suspending Corona. This is typically how ad banners work. [import]uid: 32256 topic_id: 32703 reply_id: 130198[/import]

It sounds like the chartboost interstitial ad is displayed in a separate activity (ie: window). Displaying another activity on Android will pause/stop the previous activity because Android can only display one activity at a time. In this case, it is stopping the CoronaActivity, which will cause it to suspend the Corona runtime because it no longer has a window to render to anymore.

Can chartboost display an ad as a view? As in a view that you can display within the CoronaActivity? That’s the only way to display an ad without suspending Corona. This is typically how ad banners work. [import]uid: 32256 topic_id: 32703 reply_id: 130198[/import]

Hi Vitor & Joshua,

How did this turn out for you? Were you able to integrate Chartboost successfully with the enterprise edition?

We are looking at jumping on enterprise edition just to add Chartboost, so any info would be great. 

Thanks,

Ben

Hi Vitor & Joshua,

How did this turn out for you? Were you able to integrate Chartboost successfully with the enterprise edition?

We are looking at jumping on enterprise edition just to add Chartboost, so any info would be great. 

Thanks,

Ben