My Libgdx game slow when integrated Admob - libgdx

I am a new game developing with libgdx. I have a problem with Admob ads. When I call "adView.loadAd(adRequest);" my game is slowl, when I start game, FPS ~ 60 , when I call adView.loadAd(adRequest) my game is slowly FPS ~ 30.
Here is my
public class MainActivity extends AndroidApplication implements IActivityRequestHandler {
protected AdView adView;
AdRequest adRequest;
private final int SHOW_ADS = 1;
private final int HIDE_ADS = 0;
protected Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case SHOW_ADS: {
System.out.println("SHOW ADVIEW");
adView.setVisibility(View.VISIBLE);
break;
}
case HIDE_ADS: {
adView.setVisibility(View.GONE);
break;
}
}
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Create the layout
RelativeLayout layout = new RelativeLayout(this);
// Do the stuff that initialize() would do for you
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
// Create the libgdx View
View gameView = initializeForView(new MyGdxGame(this), false);
// Create and setup the AdMob view`enter code here`
adView = new AdView(this, AdSize.BANNER, "XXXXXX"); // Put in your
// secret key
// here
adRequest = new AdRequest();
adView.loadAd(adRequest);
// adView.loadAd(new AdRequest());
// Add the libgdx view
layout.addView(gameView);
// Add the AdMob view
RelativeLayout.LayoutParams adParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
adParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
adParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
layout.addView(adView, adParams);
// Hook it all up
setContentView(layout);
}
// This is the callback that posts a message for the handler
#Override
public void showAds(boolean show) {
handler.sendEmptyMessage(show ? SHOW_ADS : HIDE_ADS);
}
}
I read topic Using interstitials from Admob in a Libgdx game for Android, it's slow when dismissing it
but not solution
Please help me if you have a solution.

This is a known issue and at the moment you cant change it.
Post at the libgdx Forum
It has nothing todo with your code. I think

Related

LibGDX - check if compass needs calibration

How to check if compass is calibrated well in LibGDX (on Android). I've found how to do it on native Android:
In Android can I programmatically detect that the compass is not yet calibrated?
But couldn't find if that's implemented in LibGDX.
What you want is described in the wiki article Interfacing with platform specific code. LibGDX doesn't have any functionality for it because it isn't common and it doesn't make any sense for other backends.
In the core module you'll have something like this:
public interface GameListener {
void calibrateCompassIfNeeded()
}
public class Application extends ApplicationAdapter {
private GameListener listener;
public Application(GameListener listener) {
this.listener = listener;
}
#Override
public void create() {
// Call listener.calibrateCompassIfNeeded() whenever needed.
}
public void onCompassChanged(float[] values) {
// Do something...
}
}
And in the android module:
public class AndroidLauncher extends AndroidApplication implements GameListener, SensorEventListener {
private static final int COMPASS_ACCURACY_UNKNOWN = -1;
private Application app;
private int compassAccuracy = COMPASS_ACCURACY_UNKNOWN;
#Override
public void onCreate(Bundle state) {
super.onCreate(state);
SensorManager sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
Sensor compassSensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
sensorManager.registerListener(this, compassSensor, SensorManager.SENSOR_DELAY_GAME)
AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
app = new Application(this);
initialize(app, config);
}
#Override
public void calibrateCompassIfNeeded() {
if (compassAccuracy != COMPASS_ACCURACY_UNKNOWN && compassAccuracy < SENSOR_STATUS_ACCURACY_MEDIUM) {
// Calibrate only if accuracy is below medium.
// Show whatever is needed so user calibrates the compass.
}
}
#Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
app.onCompassChanged(event.values);
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
compassAccuracy = accuracy;
}
}
I haven't tried it and I have never used the compass before but I'm pretty sure this will work fine.

LibGDX Skin additional resource dependencies issue

I was wondering if I am doing something wrong (most likely) or if there is an issue with LibGDX SkinLoader regarding additional resource dependencies.
According to the documentation of SkinLoader.SkinParameter you can pass an additional ObjectMap to define resources that the skin depends on.
I wanted to use that for bitmap fonts because I am creating them at runtime out of a .ttf file to be able to create the correct font sizes for the correct density/size of the target device's display.
Here is an example program that causes the issue:
public class Test extends Game {
private AssetManager assetManager;
private Skin skin;
private Batch batch;
#Override
public void create() {
this.assetManager = new AssetManager();
final FileHandleResolver resolver = new InternalFileHandleResolver();
assetManager.setLoader(FreeTypeFontGenerator.class, new FreeTypeFontGeneratorLoader(resolver));
assetManager.setLoader(BitmapFont.class, ".ttf", new FreetypeFontLoader(resolver));
final ObjectMap<String, Object> resources = new ObjectMap<String, Object>();
final FreetypeFontLoader.FreeTypeFontLoaderParameter fontParam = new FreetypeFontLoader.FreeTypeFontLoaderParameter();
fontParam.fontFileName = "ui/font.ttf";
fontParam.fontParameters.size = (int) (16 * Gdx.graphics.getDensity());
assetManager.load("font16.ttf", BitmapFont.class, fontParam);
assetManager.finishLoading();
resources.put("font_16", assetManager.get("font16.ttf", BitmapFont.class));
assetManager.load("ui/ui.json", Skin.class, new SkinLoader.SkinParameter(resources));
assetManager.finishLoading();
skin = assetManager.get("ui/ui.json", Skin.class);
batch = new SpriteBatch();
}
#Override
public void render() {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
skin.get("font_16", BitmapFont.class).draw(batch, "Test123", 10, 10);
batch.end();
}
#Override
public void dispose() {
super.dispose();
// enabling the next line will get rid of the Pixmap already disposed exception
// skin.remove("font_16", BitmapFont.class);
assetManager.dispose();
batch.dispose();
}
}
Now when disposing the assetManager at the end of the program then I got an exception "Pixmap already disposed" because the bitmap fonts got disposed multiple times (once when the Skin gets disposed and once when the Bitmap font itself gets disposed).
To solve that for now I called skin.remove(fontName, BitMapFont.class) before assetManager.dispose() to release the bitmap fonts only once BUT imo this is not a nice way and I would expect that the dependency handling of the assetManager should take care of that.
I checked the code of the SkinLoader class and to me it seems like those passed resources are not added as a dependency of the Skin and that is why this error occurs.
My question now is:
Did I do something wrong or does anyone have a working code for that to show how the resourcesmap should be used in the correct way?
Found a topic which is related to this but seems like it never got a real answer
I have got the answer that I needed. Actually it is not an issue with the asset manager. It is an issue with the Skin class.
Look at the dispose method:
public void dispose () {
if (atlas != null) atlas.dispose();
for (ObjectMap<String, Object> entry : resources.values()) {
for (Object resource : entry.values())
if (resource instanceof Disposable) ((Disposable)resource).dispose();
}
}
It disposes any resource directly which is then not reflected in the asset manager of course and therefore the asset manager will also dispose the created bitmap fonts.
To solve this issue I wrote my own loader and Skin class. In case anyone is interested here is the code:
public class SkinLoader extends AsynchronousAssetLoader<Skin, SkinLoader.SkinParameter> {
public static class SkinParameter extends AssetLoaderParameters<Skin> {
private final String fontPath;
private final int[] fontSizesToCreate;
public SkinParameter(final String fontPath, final int... fontSizesToCreate) {
if (fontPath == null || fontPath.trim().isEmpty()) {
throw new GdxRuntimeException("fontPath cannot be null or empty");
}
if (fontSizesToCreate.length == 0) {
throw new GdxRuntimeException("fontSizesToCreate has to contain at least one value");
}
this.fontPath = fontPath;
this.fontSizesToCreate = fontSizesToCreate;
}
}
public SkinLoader(final FileHandleResolver resolver) {
super(resolver);
}
#Override
#SuppressWarnings("unchecked")
public Array<AssetDescriptor> getDependencies(final String fileName, final FileHandle file, final SkinParameter parameter) {
if (parameter == null) {
throw new GdxRuntimeException("SkinParameter cannot be null");
}
// texture atlas dependency
final Array<AssetDescriptor> dependencies = new Array<AssetDescriptor>();
dependencies.add(new AssetDescriptor(file.pathWithoutExtension() + ".atlas", TextureAtlas.class));
// bitmap font dependencies
for (int fontSize : parameter.fontSizesToCreate) {
final FreetypeFontLoader.FreeTypeFontLoaderParameter fontParam = new FreetypeFontLoader.FreeTypeFontLoaderParameter();
fontParam.fontFileName = parameter.fontPath;
// enable anti-aliasing
fontParam.fontParameters.minFilter = Texture.TextureFilter.Linear;
fontParam.fontParameters.magFilter = Texture.TextureFilter.Linear;
// create font according to density of target device display
fontParam.fontParameters.size = (int) (fontSize * Gdx.graphics.getDensity());
dependencies.add(new AssetDescriptor("font" + fontSize + ".ttf", BitmapFont.class, fontParam));
}
return dependencies;
}
#Override
public Skin loadSync(final AssetManager manager, final String fileName, final FileHandle file, final SkinParameter parameter) {
// load atlas and create skin
final String textureAtlasPath = file.pathWithoutExtension() + ".atlas";
final TextureAtlas atlas = manager.get(textureAtlasPath, TextureAtlas.class);
final Skin skin = new Skin(atlas);
// add bitmap fonts to skin
for (int fontSize : parameter.fontSizesToCreate) {
skin.add("font_" + fontSize, manager.get("font" + fontSize + ".ttf"));
}
// load skin now because the fonts in the json file are now available
skin.load(file);
return skin;
}
#Override
public void loadAsync(final AssetManager manager, final String fileName, final FileHandle file, final SkinParameter parameter) {
}}
public class Skin extends com.badlogic.gdx.scenes.scene2d.ui.Skin {
Skin(final TextureAtlas atlas) {
super(atlas);
}
#Override
public void dispose() {
for (String bitmapFontKey : this.getAll(BitmapFont.class).keys()) {
remove(bitmapFontKey, BitmapFont.class);
}
super.dispose();
}}

how to do a button click in Xamarin Forms Android custom info window

In my Xamarin Forms Android project I am showing a Map using CustomMapRenderer. I am popping up a Info Window in Map screen and this info window has button name called "Call". I need to do a "OnCLick" button click operation for this button. I have googled it, but unfortunately I didn't come across any solutions. at last I have started to work on converting the Android Native code -Java into Xamarin Forms Android - c#, for this conversion I have been using this answers Google Maps Android API v2 - Interactive InfoWindow (like in original android google maps) . This converted code shows A field initializer cannot reference the non static field, method or property OnInfoWindowElemTouchListener.onClickConfirmed(view, marker) this Error inside Java.Lang.Runnable please help me to resolve the problem.
OnInfoWindowElemTouchListener.cs
using System.Threading.Tasks;
using Android.App;
using Android.Content;
using Android.Gms.Maps.Model;
using Android.Graphics.Drawables;
using Android.OS;
using Android.Views;
using Android.Views.Accessibility;
using Java.Lang;
namespace Hotel.Droid
{
public abstract class OnInfoWindowElemTouchListener : Java.Lang.Object
, View.IOnTouchListener
{
private View view;
private Drawable bgDrawableNormal;
private Drawable bgDrawablePressed;
private Handler handler = new Handler();
private Marker marker;
private static bool endPressStatus = false;
private bool pressed = false;
public OnInfoWindowElemTouchListener(View view, Drawable bgDrawableNormal, Drawable bgDrawablePressed)
{
this.view = this.view;
this.bgDrawableNormal = this.bgDrawableNormal;
this.bgDrawablePressed = this.bgDrawablePressed;
}
public OnInfoWindowElemTouchListener()
{
}
public void setMarker(Marker marker)
{
this.marker = this.marker;
}
public bool OnTouch(View vv, MotionEvent e)
{
if (0 <= e.GetX() && e.GetX() <= vv.Width && 0 <= e.GetY() && e.GetY() <= vv.Height)
{
switch (e.ActionMasked)
{
case MotionEventActions.Down:
startPress();
break;
// We need to delay releasing of the view a little so it shows the
// pressed state on the screen
case MotionEventActions.Up:
//handler.PostDelayed(ConfirmClickRunnable, 150);
Task.Factory.StartNew(() => onClickConfirmed(view, marker));
Task.Delay(150);
break;
case MotionEventActions.Cancel:
endPress();
break;
default:
break;
}
}
else {
// If the touch goes outside of the view's area
// (like when moving finger out of the pressed button)
// just release the press
endPress();
}
return false;
}
private void startPress()
{
if (!pressed)
{
pressed = true;
//handler.RemoveCallbacks(ConfirmClickRunnable);
view.SetBackgroundDrawable(bgDrawablePressed);
if ((marker != null))
{
marker.ShowInfoWindow();
}
}
}
public bool endPress()
{
if (pressed)
{
this.pressed = false;
handler.RemoveCallbacks(ConfirmClickRunnable);
view.SetBackgroundDrawable(bgDrawableNormal);
if ((marker != null))
{
marker.ShowInfoWindow();
}
endPressStatus = true;
return true;
}
else {
endPressStatus = false;
return false;
}
}
private Runnable ConfirmClickRunnable = new Java.Lang.Runnable(() =>
{
if (endPressStatus)
{
onClickConfirmed(view, marker);
}
});
/*private class RunnableAnonymousInnerClassHelper : Java.Lang.Object, Java.Lang.IRunnable
{
private readonly Context outerInstance;
public RunnableAnonymousInnerClassHelper(Context outerInstance)
{
this.outerInstance = outerInstance;
}
public void Run()
{
if (endPressStatus)
{
onClickConfirmed();
}
}
}*/
protected abstract void onClickConfirmed(View v, Marker marker);
}
}
Updated
I have implemented the Task.Factory.StartNew instead of Android Runnableand now I am stucking on the below lines. I am struggling on converting this below Java codes into C#since it is written by Anonymous class concept.
Java
this.infoButtonListener = new OnInfoWindowElemTouchListener(infoButton,
getResources().getDrawable(R.drawable.btn_default_normal_holo_light),
getResources().getDrawable(R.drawable.btn_default_pressed_holo_light))
{
#Override
protected void onClickConfirmed(View v, Marker marker) {
// Here we can perform some action triggered after clicking the button
Toast.makeText(MainActivity.this, marker.getTitle() + "'s button clicked!", Toast.LENGTH_SHORT).show();
}
};
this.infoButton.setOnTouchListener(infoButtonListener);
infoButton in code is Call button
C# - Please help me to resolve the problem by converting/using(How to use) the above java code
The solution is too complicated for this window. Please see chat room for step by step solution.
https://chat.stackoverflow.com/rooms/128847/discussion-between-jamal-and-yuri-s

Elements disappear after pause and resume

Testing my libGDX app in RoboVM, I have encountered a major problem. When I pause my app (by actually going to the Home screen or sending app invites via Facebook) and then return to my app, classes of my games disappear. As if it does not store data properly on the resume() method. First i though it there was a problem of my AssetLoader, but after some debugging I found that the situation is worse. Actual instances of classes and shapes disappear. As if they never existed.
After googling the issue, I found that it might be related to IOSGraphics, but I have not managed to fix the problem.
My IOSLauncher looks something like this, I have erased the Facebook & Google AdMob specific code.
protected IOSApplication createApplication() {
IOSApplicationConfiguration config = new IOSApplicationConfiguration();
config.useAccelerometer = true;
config.useCompass = true;
config.orientationPortrait = true;
config.orientationLandscape = false;
return new IOSApplication(new Game(this), config);
}
#Override
public boolean didFinishLaunching(UIApplication application,
UIApplicationLaunchOptions launchOptions) {
FBSDKApplicationDelegate.getSharedInstance().didFinishLaunching(application, launchOptions);
initialize();
return true;
}
public void initialize() {
//...
}
public static void main(String[] argv) {
NSAutoreleasePool pool = new NSAutoreleasePool();
UIApplication.main(argv, null, IOSLauncher.class);
pool.close();
}
#Override
public void showAds(boolean show) {
//...
}
#Override
public void shareOnFacebook() {
//...
}
#Override
public void inviteFriends() {
//....
}
#Override
public boolean openURL(UIApplication application, NSURL url,
String sourceApplication, NSPropertyList annotation) {
super.openURL(application, url, sourceApplication, annotation);
return FBSDKApplicationDelegate.getSharedInstance().openURL(
application, url, sourceApplication, annotation);
}
#Override
public void didBecomeActive(UIApplication application) {
super.didBecomeActive(application);
FBSDKAppEvents.activateApp();
}
#Override
public void willResignActive(UIApplication application) {
super.willResignActive(application);
}
#Override
public void willTerminate(UIApplication application) {
super.willTerminate(application);
}
}
This sounds similar to a threading bug I once encountered. I fixed it by deferring resize and resume but I'm not sure if it will help in your case. Something like this:
private boolean needResize, needResume;
private void resize (int width, int height){
needResize = true;
}
private void deferredResize ();
if (!needResize) return;
needResize = false;
int width = Gdx.graphics.getWidth();
int height = Gdx.graphics.getHeight();
//move your resize code here
}
private void resume (){
needResume = true;
}
private void deferredResume (){
if (!needResume) return;
needResume = false;
//move your resume code here
}
public void render (){
deferredResize();
deferredResume();
//...
}
I suggest that you start looking for an alternative to RoboVM to avoid more issues in the future, as Robovm was acquired by Microsoft Xamarin (sad but true) and the framework is no longer maintained. License keys (with Libgdx) will continue to work until the 17th of April 2017, there will be no further updates to RoboVM, be it new features or bug fixes.
As far as I know, Libgdx will switch to Multi-OS engine as the default iOS backend for newly created libGDX projects in the next couple of weeks.
After a couple of days filled with headache I found the solution!
LifeCycle methods like pause & resume, hide & show are not always called When they are supposed to be called, therefore data is not stored properly. This issue can completely break your game.
This thing only occurred when testing my game on the iOS platform, mainly when I opened a 3rd party app, Facebook in this case. No such thing found on Android, though.
The only thing I changed on the iOS version was calling the mentioned methods manually to make sure it always pauses and resumes when it has to.

Android google map v2 auto update

Hi i need marker update at time i try do it
ArrayList<LatLng> markerList = new ArrayList<LatLng>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_soc_map);
mMap = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap();
markerList.add(new LatLng(48.8742, 2.3470));
markerList.add(new LatLng(0, 0));
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask(){
GetDataFromWeb GDFW = new GetDataFromWeb();
public void run() {
for (LatLng latLon : markerList) {
mMap.addMarker(new MarkerOptions().position(latLon).title("Another marker"));
}
//GDFW.execute();
}
}, 12000, 12000);
}
so.. i take from database Lat and Lng but i just test with
markerList.add(new LatLng(48.8742, 2.3470));
markerList.add(new LatLng(0, 0));
so.. i need after 12s take Lat and Lag and update map marker
I have not found anywhere answer so maybe you can help me:)
Hey I have just got the same problem and solved it.
public class Livebus extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.googlemaps);
mMap = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap();
mTask = (GetDataFromWeb) new GetDataFromWeb().execute(); //This is an AsyncTaskClass
}
class GetDataFromWeb extends AsyncTask<String, String, String> {
protected String doInBackground(String... param) {
while(true)
{
//HERE You should collect your data from the Web
latitude=...
longitude=...
//You have to update the markers in the Main thread which is also called UI thread.
//AsyncTask classes create theit own thread so you need to run the marker
//update on the UI thread. Which you can see below now.
runOnUiThread(new Runnable() {
public void run() {
mMap.addMarker(new MarkerOptions()
.position(new LatLng(latitude, longitude))
.title("Hello"));
}
});
}
}
}
This is my first answer here I hope it helps you :)
If something doesn't work pls contact me I will get it working.
Details on AsyncTasks: http://developer.android.com/reference/android/os/AsyncTask.html
Details on the threads: http://developer.android.com/guide/components/processes-and-threads.html
Read that I also learnt my lesson today.