I am not very familiar with android activities, and how that all works; Any sort of guidance on the topic would be amazing. I am having issues integrating an advertising sdk with my game. There are a few classes I will present to allow full understanding of my code. Essentially I am trying to determine a good way to integrate the StartApp sdk (an advertising sdk) with my libGDX game. I am getting what seems to be a looper error caused by the startAppAd.show(); and startAppAd.load(); being called.
Here is the stack trace (mentioning a ui thread, and loading the ad on a different thread):
01-05 15:55:27.646: W/webview_proxy(14876): java.lang.Throwable: Warning: A WebView method was called on thread 'GLThread 8584'. All WebView methods must be called on the UI thread. Future versions of WebView may not support use on other threads.
01-05 15:55:27.646: W/webview_proxy(14876): at android.webkit.WebView.checkThread(WebView.java:1895)
01-05 15:55:27.646: W/webview_proxy(14876): at android.webkit.WebView.ensureProviderCreated(WebView.java:1878)
01-05 15:55:27.646: W/webview_proxy(14876): at android.webkit.WebView.setOverScrollMode(WebView.java:1935)
01-05 15:55:27.646: W/webview_proxy(14876): at android.view.View.<init>(View.java:3316)
01-05 15:55:27.646: W/webview_proxy(14876): at android.view.View.<init>(View.java:3383)
01-05 15:55:27.646: W/webview_proxy(14876): at android.view.ViewGroup.<init>(ViewGroup.java:432)
01-05 15:55:27.646: W/webview_proxy(14876): at android.widget.AbsoluteLayout.<init>(AbsoluteLayout.java:52)
01-05 15:55:27.646: W/webview_proxy(14876): at android.webkit.WebView.<init>(WebView.java:505)
01-05 15:55:27.646: W/webview_proxy(14876): at android.webkit.WebView.<init>(WebView.java:482)
01-05 15:55:27.646: W/webview_proxy(14876): at android.webkit.WebView.<init>(WebView.java:468)
01-05 15:55:27.646: W/webview_proxy(14876): at android.webkit.WebView.<init>(WebView.java:457)
01-05 15:55:27.646: W/webview_proxy(14876): at android.webkit.WebView.<init>(WebView.java:447)
01-05 15:55:27.646: W/webview_proxy(14876): at com.startapp.android.publish.Ad.load(Unknown Source)
01-05 15:55:27.646: W/webview_proxy(14876): at com.startapp.android.publish.HtmlAd.load(Unknown Source)
01-05 15:55:27.646: W/webview_proxy(14876): at com.startapp.android.publish.StartAppAd.loadAds(Unknown Source)
01-05 15:55:27.646: W/webview_proxy(14876): at com.startapp.android.publish.StartAppAd.load(Unknown Source)
01-05 15:55:27.646: W/webview_proxy(14876): at com.startapp.android.publish.StartAppAd.loadAd(Unknown Source)
01-05 15:55:27.646: W/webview_proxy(14876): at com.startapp.android.publish.StartAppAd.loadAd(Unknown Source)
01-05 15:55:27.646: W/webview_proxy(14876): at com.startapp.android.publish.StartAppAd.onResume(Unknown Source)
01-05 15:55:27.646: W/webview_proxy(14876): at com.audiack.freetappgame.MainActivity.resume(MainActivity.java:41)
01-05 15:55:27.646: W/webview_proxy(14876): at Screens.GameScreen.resume(GameScreen.java:699)
01-05 15:55:27.646: W/webview_proxy(14876): at com.badlogic.gdx.Game.resume(Game.java:41)
01-05 15:55:27.646: W/webview_proxy(14876): at com.badlogic.gdx.backends.android.AndroidGraphics.onDrawFrame(AndroidGraphics.java:480)
01-05 15:55:27.646: W/webview_proxy(14876): at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1516)
01-05 15:55:27.646: W/webview_proxy(14876): at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)
01-05 15:55:27.656: W/IInputConnectionWrapper(14876): getSelectedText on inactive InputConnection
01-05 15:55:27.656: D/SensorManager(14876): onAccuracyChanged :: accuracy = 3
01-05 15:55:27.656: W/IInputConnectionWrapper(14876): setComposingText on inactive InputConnection
01-05 15:55:27.676: W/webview_proxy(14876): java.lang.Throwable: Warning: A WebView method was called on thread 'GLThread 8584'. All WebView methods must be called on the UI thread. Future versions of WebView may not support use on other threads.
01-05 15:55:27.676: W/webview_proxy(14876): at android.webkit.WebView.checkThread(WebView.java:1895)
01-05 15:55:27.676: W/webview_proxy(14876): at android.webkit.WebView.getFactory(WebView.java:1889)
01-05 15:55:27.676: W/webview_proxy(14876): at android.webkit.WebView.ensureProviderCreated(WebView.java:1882)
01-05 15:55:27.676: W/webview_proxy(14876): at android.webkit.WebView.setOverScrollMode(WebView.java:1935)
01-05 15:55:27.676: W/webview_proxy(14876): at android.view.View.<init>(View.java:3316)
01-05 15:55:27.676: W/webview_proxy(14876): at android.view.View.<init>(View.java:3383)
01-05 15:55:27.676: W/webview_proxy(14876): at android.view.ViewGroup.<init>(ViewGroup.java:432)
01-05 15:55:27.676: W/webview_proxy(14876): at android.widget.AbsoluteLayout.<init>(AbsoluteLayout.java:52)
01-05 15:55:27.676: W/webview_proxy(14876): at android.webkit.WebView.<init>(WebView.java:505)
01-05 15:55:27.676: W/webview_proxy(14876): at android.webkit.WebView.<init>(WebView.java:482)
01-05 15:55:27.676: W/webview_proxy(14876): at android.webkit.WebView.<init>(WebView.java:468)
01-05 15:55:27.676: W/webview_proxy(14876): at android.webkit.WebView.<init>(WebView.java:457)
01-05 15:55:27.676: W/webview_proxy(14876): at android.webkit.WebView.<init>(WebView.java:447)
01-05 15:55:27.676: W/webview_proxy(14876): at com.startapp.android.publish.Ad.load(Unknown Source)
01-05 15:55:27.676: W/webview_proxy(14876): at com.startapp.android.publish.HtmlAd.load(Unknown Source)
01-05 15:55:27.676: W/webview_proxy(14876): at com.startapp.android.publish.StartAppAd.loadAds(Unknown Source)
01-05 15:55:27.676: W/webview_proxy(14876): at com.startapp.android.publish.StartAppAd.load(Unknown Source)
01-05 15:55:27.676: W/webview_proxy(14876): at com.startapp.android.publish.StartAppAd.loadAd(Unknown Source)
01-05 15:55:27.676: W/webview_proxy(14876): at com.startapp.android.publish.StartAppAd.loadAd(Unknown Source)
01-05 15:55:27.676: W/webview_proxy(14876): at com.startapp.android.publish.StartAppAd.onResume(Unknown Source)
01-05 15:55:27.676: W/webview_proxy(14876): at com.audiack.freetappgame.MainActivity.resume(MainActivity.java:41)
01-05 15:55:27.676: W/webview_proxy(14876): at Screens.GameScreen.resume(GameScreen.java:699)
01-05 15:55:27.676: W/webview_proxy(14876): at com.badlogic.gdx.Game.resume(Game.java:41)
01-05 15:55:27.676: W/webview_proxy(14876): at com.badlogic.gdx.backends.android.AndroidGraphics.onDrawFrame(AndroidGraphics.java:480)
01-05 15:55:27.676: W/webview_proxy(14876): at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1516)
01-05 15:55:27.676: W/webview_proxy(14876): at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)
01-05 15:55:27.706: W/dalvikvm(14876): threadid=11: thread exiting with uncaught exception (group=0x4159a438)
01-05 15:55:27.716: E/AndroidRuntime(14876): FATAL EXCEPTION: GLThread 8584
01-05 15:55:27.716: E/AndroidRuntime(14876): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
01-05 15:55:27.716: E/AndroidRuntime(14876): at android.os.Handler.<init>(Handler.java:121)
01-05 15:55:27.716: E/AndroidRuntime(14876): at android.webkit.WebViewClassic$PrivateHandler.<init>(WebViewClassic.java:10636)
01-05 15:55:27.716: E/AndroidRuntime(14876): at android.webkit.WebViewClassic.<init>(WebViewClassic.java:1258)
01-05 15:55:27.716: E/AndroidRuntime(14876): at android.webkit.WebViewClassic$Factory.createWebView(WebViewClassic.java:2031)
01-05 15:55:27.716: E/AndroidRuntime(14876): at android.webkit.WebView.ensureProviderCreated(WebView.java:1882)
01-05 15:55:27.716: E/AndroidRuntime(14876): at android.webkit.WebView.setOverScrollMode(WebView.java:1935)
01-05 15:55:27.716: E/AndroidRuntime(14876): at android.view.View.<init>(View.java:3316)
01-05 15:55:27.716: E/AndroidRuntime(14876): at android.view.View.<init>(View.java:3383)
01-05 15:55:27.716: E/AndroidRuntime(14876): at android.view.ViewGroup.<init>(ViewGroup.java:432)
01-05 15:55:27.716: E/AndroidRuntime(14876): at android.widget.AbsoluteLayout.<init>(AbsoluteLayout.java:52)
01-05 15:55:27.716: E/AndroidRuntime(14876): at android.webkit.WebView.<init>(WebView.java:505)
01-05 15:55:27.716: E/AndroidRuntime(14876): at android.webkit.WebView.<init>(WebView.java:482)
01-05 15:55:27.716: E/AndroidRuntime(14876): at android.webkit.WebView.<init>(WebView.java:468)
01-05 15:55:27.716: E/AndroidRuntime(14876): at android.webkit.WebView.<init>(WebView.java:457)
01-05 15:55:27.716: E/AndroidRuntime(14876): at android.webkit.WebView.<init>(WebView.java:447)
01-05 15:55:27.716: E/AndroidRuntime(14876): at com.startapp.android.publish.Ad.load(Unknown Source)
01-05 15:55:27.716: E/AndroidRuntime(14876): at com.startapp.android.publish.HtmlAd.load(Unknown Source)
01-05 15:55:27.716: E/AndroidRuntime(14876): at com.startapp.android.publish.StartAppAd.loadAds(Unknown Source)
01-05 15:55:27.716: E/AndroidRuntime(14876): at com.startapp.android.publish.StartAppAd.load(Unknown Source)
01-05 15:55:27.716: E/AndroidRuntime(14876): at com.startapp.android.publish.StartAppAd.loadAd(Unknown Source)
01-05 15:55:27.716: E/AndroidRuntime(14876): at com.startapp.android.publish.StartAppAd.loadAd(Unknown Source)
01-05 15:55:27.716: E/AndroidRuntime(14876): at com.startapp.android.publish.StartAppAd.onResume(Unknown Source)
01-05 15:55:27.716: E/AndroidRuntime(14876): at com.audiack.freetappgame.MainActivity.resume(MainActivity.java:41)
01-05 15:55:27.716: E/AndroidRuntime(14876): at Screens.GameScreen.resume(GameScreen.java:699)
01-05 15:55:27.716: E/AndroidRuntime(14876): at com.badlogic.gdx.Game.resume(Game.java:41)
01-05 15:55:27.716: E/AndroidRuntime(14876): at com.badlogic.gdx.backends.android.AndroidGraphics.onDrawFrame(AndroidGraphics.java:480)
01-05 15:55:27.716: E/AndroidRuntime(14876): at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1516)
01-05 15:55:27.716: E/AndroidRuntime(14876): at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)
01-05 15:57:29.236: E/System(14876): Uncaught exception thrown by finalizer
01-05 15:57:29.246: E/System(14876): java.lang.NullPointerException
01-05 15:57:29.246: E/System(14876): at android.webkit.WebViewClassic.destroy(WebViewClassic.java:2954)
01-05 15:57:29.246: E/System(14876): at android.webkit.WebViewClassic.finalize(WebViewClassic.java:5366)
01-05 15:57:29.246: E/System(14876): at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:186)
01-05 15:57:29.246: E/System(14876): at java.lang.Daemons$FinalizerDaemon.run(Daemons.java:169)
01-05 15:57:29.246: E/System(14876): at java.lang.Thread.run(Thread.java:856)
It seems to have something to do with trying to load the ad within the starting activity. Here is my launch activity (and the only activity due to libGDX only running one activity with android):
package com.audiack.freetappgame;
import Screens.FreeTappGame;
import UtilityClasses.StartAppResolver;
import android.os.Bundle;
import android.os.Looper;
import com.badlogic.gdx.backends.android.AndroidApplication;
import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration;
import com.badlogic.gdx.graphics.Texture;
import com.searchboxsdk.android.StartAppSearch;
import com.startapp.android.publish.StartAppAd;
public class MainActivity extends AndroidApplication implements StartAppResolver{
public StartAppAd startAppAd = new StartAppAd(this);
public StartAppSearch startAppSearch= new StartAppSearch();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AndroidApplicationConfiguration cfg = new AndroidApplicationConfiguration();
StartAppAd.init(this, "101164873", "201640058");
StartAppSearch.init(this, "101164873", "201640058");
Texture.setEnforcePotImages(false);
cfg.useGL20 = true;
initialize(new FreeTappGame(this), cfg);
StartAppSearch.showSearchBox(this);
}
@Override
public boolean showAds() {
startAppAd.load();
startAppAd.show();
return true;
}
@Override
public boolean resume() {
startAppAd.onResume();
return true;
}
@Override
public boolean backButton() {
return true;
}
@Override
public boolean pause() {
startAppAd.onPause();
return true;
}
}
As you may see I have this activity implement an interface I created, and then I pass the activity itself to the ApplicationListener, allowing the libGDX methods to interact with the activity. Here is that interface; based off of my hours of research this is the best way to integrate ads within libGDX (but those ways were for similar advertising sdk's not StartApp directly):
package UtilityClasses;
public interface StartAppResolver {
public boolean showAds();
public boolean resume();
public boolean backButton();
public boolean pause();
}
And finally the ApplicationListener (the FreeTappGame class):
package Screens;
import UtilityClasses.Assets;
import UtilityClasses.StartAppResolver;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Game;
import com.badlogic.gdx.Gdx;
public class FreeTappGame extends Game implements ApplicationListener {
static float Width;
static float Height;
public StartAppResolver startAppResolver;
public SplashScreen splash_screen;
public MenuScreen menu_screen;
public GameScreen game_screen;
public HighscoreScreen highscore_screen;
public AboutScreen about_screen;
public FreeTappGame(StartAppResolver startAppResolver) {
this.startAppResolver = startAppResolver;
}
@Override
public void create() {
Width = Gdx.graphics.getWidth();
Height = Gdx.graphics.getHeight();
Assets.load();
splash_screen = new SplashScreen(this);
menu_screen = new MenuScreen(this);
game_screen = new GameScreen(this);
highscore_screen = new HighscoreScreen(this);
about_screen = new AboutScreen(this);
setScreen(splash_screen);
}
}
Thank you so much for your time.
I would delete this thread, because there is a similar issue here: WebView Methods is not called in android but there aren't many startapp solutions on stackoverflow, and I think this question will be beneficial to people who are trying to integrate startapp. I replaced
@Override
public boolean showAds() {
startAppAd.load();
startAppAd.show();
return true;
}
with
@Override
public boolean showAds() {
this.runOnUiThread(new Runnable() {
@Override
public void run() {
startAppAd.show();
}
});
return true;
}
and i put startAppAd.load() after the initialize method:
initialize(new FreeTappGame(this), cfg);
startAppAd.load();
that did the trick for me; I hope this helps someone.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With