Google Play Services (Suggested updates to Android Main Activity for plugin)

Soooo… I’m trying to get this all set up, but I’m hitting an issue or 5 and could really use a bit of guidance from someone who has done this successfully.

Thus far, I have at least been able to integrate Google Play Services (and when I say integrate, I simply mean that the app will compile and run… however I am not doing anything with the API).

I’d really like to get AdMob set up and working,

So… I guess a few starting questions would be in order:

  1. Should I be using Google Play Services? Or the legacy AdMob stuff?
  2. What android API is Google Play Services using? There examples do not seem to match what JME’s android harness is referencing.
  3. Any other information, examples, code samples, um… anything… would be really helpful :wink:

Feeling a bit lost here…

Thanks in advance.

Hi!

I’m trying to do the same. Specifically, to add an interstitial ad (AdMob) to the BasicGame project generated by the jMonkeyEngine 3.0 wizard. But it’s a nightmare…

I followed the latest Google instructions at https://developers.google.com/mobile-ads-sdk/docs/?hl=en_US, so, after adding the ‘google-play-services_lib/libs/google-play-services.jar’ library to the project (Properties -> Libraires -> Compile tab) I modified the Android manifest file in jMonkeyEngine as per Google instructions:

[java]
<?xml version=“1.0” encoding=“UTF-8”?>
<manifest xmlns:android=“http://schemas.android.com/apk/res/android” android:versionCode=“1” android:versionName=“1.0” package=“com.mycompany.admobtest”>
<application android:label="@string/app_name">
<meta-data android:name=“com.google.android.gms.version” android:value="@integer/google_play_services_version"/>
<activity android:label="@string/app_name" android:launchMode=“singleTask” android:name=“MainActivity”>
<intent-filter>
<action android:name=“android.intent.action.MAIN”/>
<category android:name=“android.intent.category.LAUNCHER”/>
</intent-filter>
</activity>

    &lt;activity android:name="com.google.android.gms.ads.AdActivity" android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"/&gt;

&lt;/application&gt;
&lt;uses-sdk android:minSdkVersion="9"/&gt;
&lt;supports-screens android:anyDensity="true" android:largeScreens="true" android:normalScreens="true" android:smallScreens="true"/&gt;

<uses-permission android:name=“android.permission.INTERNET”/>
<uses-permission android:name=“android.permission.ACCESS_NETWORK_STATE”/>

</manifest>
[/java]

Then I (roughly!) ported to MainActivity.java in jMonkeyEngine the example project provided by Google for the interstitial ads (found at https://github.com/googleads/googleads-mobile-android-examples/tree/master/admob/interstitial), as follows:

[java]
package com.mycompany.admobtest;

import android.content.pm.ActivityInfo;
import com.jme3.app.AndroidHarness;
import com.jme3.system.android.AndroidConfigChooser.ConfigType;
import java.util.logging.Level;
import java.util.logging.LogManager;
import com.google.android.gms.ads.*;
import android.app.Activity;
import android.os.Bundle;
import android.widget.LinearLayout;
import android.R;
import android.widget.FrameLayout;
import android.view.ViewGroup.LayoutParams;
import android.view.Gravity;
import android.widget.ImageView;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.NinePatchDrawable;
import android.view.View;

public class MainActivity extends AndroidHarness
{

/*

  • Note that you can ignore the errors displayed in this file,
  • the android project will build regardless.
  • Install the ‘Android’ plugin under Tools->Plugins->Available Plugins
  • to get error checks and code completion for the Android project files.
    */

public MainActivity()
{
// Set the application class to run
appClass = “mygame.Main”;
// Try ConfigType.FASTEST; or ConfigType.LEGACY if you have problems
eglConfigType = ConfigType.BEST;
// Exit Dialog title & message
exitDialogTitle = “Exit?”;
exitDialogMessage = “Press Yes”;
// Enable verbose logging
eglConfigVerboseLogging = false;
// Choose screen orientation
screenOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
// Enable MouseEvents being generated from TouchEvents (default = true)
mouseEventsEnabled = true;
// Set the default logging level (default=Level.INFO, Level.ALL=All Debug Info)
LogManager.getLogManager().getLogger("").setLevel(Level.INFO);
}

private InterstitialAd interstitialAd;

@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main); //<== COMPILAITION ERROR

  // Create the interstitial.
  interstitialAd = new InterstitialAd(this);
  interstitialAd.setAdUnitId("my-ad-unit-id-here");

  // Set the AdListener.
  interstitialAd.setAdListener(new AdListener()
  {
     @Override
     public void onAdLoaded()
     {
        logger.log(Level.INFO, "ADTEST - Ad loaded successfully");
     }

     @Override
     public void onAdFailedToLoad(int errorCode)
     {
        logger.log(Level.INFO, "ADTEST - Ad failed to load: " + getErrorReason(errorCode));
     }
  });

  logger.log(Level.INFO, "ADTEST - InitAdView done");
  // Create ad request.
  AdRequest adRequest = new AdRequest.Builder().build();

  // Begin loading your interstitial.
  interstitialAd.loadAd(adRequest); //&lt;== APP CRASHES HERE

}

// Invoke displayInterstitial() when you are ready to display an interstitial.
public void displayInterstitial()
{
if (interstitialAd.isLoaded())
{
interstitialAd.show();
}
}

/** Gets a string error reason from an error code. */
private String getErrorReason(int errorCode)
{
String errorReason = “”;
switch(errorCode)
{
case AdRequest.ERROR_CODE_INTERNAL_ERROR:
errorReason = “Internal error”;
break;
case AdRequest.ERROR_CODE_INVALID_REQUEST:
errorReason = “Invalid request”;
break;
case AdRequest.ERROR_CODE_NETWORK_ERROR:
errorReason = “Network Error”;
break;
case AdRequest.ERROR_CODE_NO_FILL:
errorReason = “No fill”;
break;
}
return errorReason;
}
}

[/java]

However all I get at the moment is the following compilation error: No resource found that matches the given name (at ‘value’ with value ‘@integer/google_play_services_version’).

If I place a ‘hard-coded’ version number in the manifest (replacing ‘@integer/google_play_services_version’ with ‘4030500’ for example), the next compilation error is at the ‘setContentView(R.layout.main);’ line in the MainActivity code above.

Finally, if I comment out the offending line, the project compiles and deploys to the real device (Nexus 7 tablet), but crashes as soon as it tries to load the ad (‘interstitialAd.loadAd(adRequest);’ line in the code above).

Pretty depressing… :frowning:

@Dave-Dave-Dave

You’ll need to add Integers.xml to res > values directory. This file should contain something along the lines of:

[java]
<?xml version=“1.0” encoding=“UTF-8”?>
<resources>
<integer name=“google_play_services_version”>4</integer>
</resources>
[/java]

This will allow it to compile anyways. Please do let me know how it goes for you, as I am still struggling with this as well.

If you guys ever do get this solved I’d like to know how you did it

@t0neg0d

Thanx, but by hard coding the google play service version in our app, rather than having the app figure it out itself from the library installed on the user device I fear we are breaking our apps as soon as a new version of the library is released. Not sure though as I don’t really fully understand android development yet.

Still the trick can help us at least make this test compile.

To try making the ported example compile at the ‘setContentView(R.layout.main);’ line, I replaced it with

setContentView(new FrameLayout(this));

The result is now that the app just shows a black screen, if I don’t try to load the ad. It still crashes if I try to load the ad…

Update: I will now try to implement this with the legacy AdMob libraries (based on http://hub.jmonkeyengine.org/forum/topic/jme3-admob/). Will post results here.

Please note that Google will no longer accept any new or updated app integrating the legacy AdMob after next August so I still hope a solution for Google Play Services can be found!

@Dave-Dave-Dave said: @t0neg0d

Thanx, but by hard coding the google play service version in our app, rather than having the app figure it out itself from the library installed on the user device I fear we are breaking our apps as soon as a new version of the library is released. Not sure though as I don’t really fully understand android development yet.

Still the trick can help us at least make this test compile.

To try making the ported example compile at the ‘setContentView(R.layout.main);’ line, I replaced it with

setContentView(new FrameLayout(this));

The result is now that the app just shows a black screen, if I don’t try to load the ad. It still crashes if I try to load the ad…

Update: I will now try to implement this with the legacy AdMob libraries (based on http://hub.jmonkeyengine.org/forum/topic/jme3-admob/). Will post results here.

Please note that Google will no longer accept any new or updated app integrating the legacy AdMob after next August so I still hope a solution for Google Play Services can be found!

This line:

[java]
<meta-data android:name=”com.google.android.gms.version” android:value=”@integer/google_play_services_version”/>
[/java]

… means that the build expects to pull the value from a resource file… specifically Integers.xml

It is the proper way to set this value, the same as pulling the name from Strings.xml

My next guess on how to proceed with this is to modify the Layout defined in res > layout > Main.xml

But, I’m betting this will require some modification to the input handling of JME.

Hopefully someone who has been through this will see the thread and post something soon :wink:

EDIT: This should allow for banner ads to be displayed, however… I’m not really sure how to handle Interstitials

Ok, thanx for the clarification t0neg0d!

Interstitials are supposed to be a bit easier than regular banners, without the need of a new View (assuming I understand this correctly of course :slight_smile: ).

By using the legacy interface I could actually run the following code

[java] @Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//setContentView(android.R.layout.main); //<== still no idea on what to use in place of ‘android.R.layout.main’

Application app = getJmeApplication();

interstitial = new InterstitialAd(this, "your-ad-unit-id-here");

AdRequest adRequest = new AdRequest();

interstitial.loadAd(adRequest);

//interstitial.setAdListener(this); //&lt;== no idea on how to port this...

}
[/java]

and according to logcat, an ad was successfully received.

However my problem now is calling from the main SimpleApplication code (Main.java) a ‘showAd’ function I define in the android MainActivity code.

I have found this (http://hub.jmonkeyengine.org/forum/topic/how-to-startactivity-from-simpleapplication/) but it’s an old post, with a broken link and a description of the technique that I can’t for the life of me translate into some working code.

My next guess on how to proceed with this is to modify the Layout defined in res > layout > Main.xml

But, I’m betting this will require some modification to the input handling of JME.

Hopefully a developer will see this and drop a line… or two.

@Dave-Dave-Dave said: Ok, thanx for the clarification t0neg0d!

Interstitials are supposed to be a bit easier than regular banners, without the need of a new View (assuming I understand this correctly of course :slight_smile: ).

By using the legacy interface I could actually run the following code

[java] @Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//setContentView(android.R.layout.main); //<== still no idea on what to use in place of ‘android.R.layout.main’

Application app = getJmeApplication();

interstitial = new InterstitialAd(this, "your-ad-unit-id-here");

AdRequest adRequest = new AdRequest();

interstitial.loadAd(adRequest);

//interstitial.setAdListener(this); //&lt;== no idea on how to port this...

}
[/java]

and according to logcat, an ad was successfully received.

However my problem now is calling from the main SimpleApplication code (Main.java) a ‘showAd’ function I define in the android MainActivity code.

I have found this (http://hub.jmonkeyengine.org/forum/topic/how-to-startactivity-from-simpleapplication/) but it’s an old post, with a broken link and a description of the technique that I can’t for the life of me translate into some working code.

Hopefully a developer will see this and drop a line… or two.

Well… at least things are progressing in the right direction! Hopefully, we’ll figure out a way to get Google Play Services to cooperate though. Your post above about support for the legacy AdMod library is troubling =( I really hope that this becomes a priority to someone as it is fairly critical to making Android development worth while at all using JME.

EDIT: From what I have read in various articles, direct support for Google Play Services (AdMob specifically) is provided in every other library aside from JME. Perhaps this will be the motivation needed to push this forward?

EDIT 2: Heh… while I am at it, I’d also love to see support for developing vertical layouts via the desktop. As it stands right now, you are stuck with horizontal… I do know that you can change the orientation via the Android Main Activity, however, the resolution for desktop development is still limited to supported fullscreen modes of the video card, whether or not you are using fullscreen. It would be nice to be able to select windowed vertical layouts for android dev.

One more thing, while it is on my mind.

If a resolution does come of this, I’m hoping that an addition to the Wiki can be made with a step-by-step tutorial that explains and show exactly how to integrate Google Play Services into your Android app. Hopefully, this will include as many of the standard uses as possible.

I’d also love to see this happen for Facebook integration as well. But, I’m not touching that one until I can get some resolution to this :wink:

EDIT: As it stands, it took me a little while just to track down how/where the application name was being stored and how to add a custom icon. None of this was editable through the SDK interface, though it appears that at least the name was changable (this was definitely not the case)

Hmmm…

I found this thread. It’s old, but seems to talk about integrating admob (not the current Google Play Services… but still). Maybe someone from this thread will chime in soon?

http://hub.jmonkeyengine.org/forum/topic/supporting-device-configuration-changes/

Also:

@galvez6000 from this thread:

http://hub.jmonkeyengine.org/forum/topic/tictactoe-revolution/

seems to have successfully integrated admob, though this may not be the latest version? Maybe they have some words of wisdom for us?

Is there anyone specifically I should be referencing with questions about this? Or is this a hopeless cause?

I’ve hit another stumbling block… Apparently you can not reference android.jar in your project without receiving the following error when trying to compile:

[java]
Pre-Dexing D:\jMonkeyProjects\Orbit\mobile\libs\android.jar -> android-7e3581d85f638a3512ddb62c26b5a27c.jar

trouble processing “java/sql/Savepoint.class”:

Ill-advised or mistaken usage of a core class (java.* or javax.*)
when not building a core library.

This is often due to inadvertently including a core library file
in your application’s project, when using an IDE (such as
Eclipse). If you are sure you’re not intentionally defining a
core class, then this is the most likely explanation of what’s
going on.

However, you might actually be trying to define a class in a core
namespace, the source of which you may have taken, for example,
from a non-Android virtual machine project. This will most
assuredly not work. At a minimum, it jeopardizes the
compatibility of your app with future versions of the platform.
It is also often of questionable legality.

If you really intend to build a core library – which is only
appropriate as part of creating a full virtual machine
distribution, as opposed to compiling an application – then use
the “–core-library” option to suppress this error message.

If you go ahead and use “–core-library” but are in fact
building an application, then be forewarned that your application
will still fail to build or run, at some point. Please be
prepared for angry customers who find, for example, that your
application ceases to function once they upgrade their operating
system. You will be to blame for this problem.

If you are legitimately using some code that happens to be in a
core package, then the easiest safe alternative you have is to
repackage that code. That is, move the classes in question into
your own package namespace. This means that they will never be in
conflict with core system classes. JarJar is a tool that may help
you in this endeavor. If you find that you cannot do this, then
that is an indication that the path you are on will ultimately
lead to pain, suffering, grief, and lamentation.

1 error; aborting
D:\jMonkeyProjects\Orbit\nbproject\mobile-impl.xml:10: The following error occurred while executing this line:
D:\Java 3rd Party Libraries\adt-bundle-windows-x86_64-20131030\sdk\tools\ant\build.xml:892: The following error occurred while executing this line:
D:\Java 3rd Party Libraries\adt-bundle-windows-x86_64-20131030\sdk\tools\ant\build.xml:894: The following error occurred while executing this line:
D:\Java 3rd Party Libraries\adt-bundle-windows-x86_64-20131030\sdk\tools\ant\build.xml:906: The following error occurred while executing this line:
D:\Java 3rd Party Libraries\adt-bundle-windows-x86_64-20131030\sdk\tools\ant\build.xml:284: null returned: 1
BUILD FAILED (total time: 4 seconds)
[/java]

How is one supposed to extend Activity without referencing this library?
Without doing this, there is no way to display AdMob ads…

Really could use a bit of help here from… anyone…??

Thus far, I have been able to:

Getting the app to compile referencing Google Play Services… np
Modify the layout with the addition of AdView(s) … np

Doing anything to make use of this… lots of problems =(

Hi to all,

I’ve been a bit busy so sorry for the delay in the answer.

First of all, I have the GoogleAdMobAdsSdk-6.4.1 integrated in my game. I’m currently working in other game and this one was my first game/test to see how this things works. What I have is a smart banner in the bottom of the game (you can check that by downloading it ;-P)

How I did it?

I include in the project the GoodleAdMobAdsSdk-6.4.1.jar.

Then you have to modify your MainActivity

[java]
package com.galvezgames.tictactoerevolution;

import android.content.pm.ActivityInfo;
import android.graphics.Color;
import android.os.Bundle;
import android.view.Gravity;
import android.view.ViewGroup.LayoutParams;
import android.widget.LinearLayout;
import com.google.ads.AdRequest;
import com.google.ads.AdSize;
import com.google.ads.AdView;
import com.jme3.app.AndroidHarness;
import com.jme3.system.android.AndroidConfigChooser.ConfigType;
//import com.mycompany.mygame.R;
import java.util.logging.Level;
import java.util.logging.LogManager;

public class MainActivity extends AndroidHarness{

/*
 * Note that you can ignore the errors displayed in this file,
 * the android project will build regardless.
 * Install the 'Android' plugin under Tools-&gt;Plugins-&gt;Available Plugins
 * to get error checks and code completion for the Android project files.
 */

private AdView adView;

public MainActivity(){
    // Set the application class to run
    appClass = "www.galvezgames.com.TicTacToeRevolution";
    // Try ConfigType.FASTEST; or ConfigType.LEGACY if you have problems
    eglConfigType = ConfigType.BEST;
    // Exit Dialog title &amp; message
    exitDialogTitle = "Exit?";
    exitDialogMessage = "Press Yes";
    // Enable verbose logging
    eglConfigVerboseLogging = false;
    // Choose screen orientation
    screenOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
    // Enable MouseEvents being generated from TouchEvents (default = true)
    mouseEventsEnabled = true;
    splashPicID = R.drawable.splash;                  
    
    // Set the default logging level (default=Level.INFO, Level.ALL=All Debug Info)
    LogManager.getLogManager().getLogger("").setLevel(Level.OFF);
    
    
}

@Override
public void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    
    splashImageView.setBackgroundColor(Color.WHITE);
    
    adView = new AdView(this, AdSize.SMART_BANNER, "your Application Ads Id"); // This is for place a smart banner in the botom of the screen
    LinearLayout ll = new LinearLayout(this);
    ll.setGravity(Gravity.BOTTOM);
    ll.addView(adView);
    this.addContentView(ll, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
    AdRequest request = new AdRequest();
    adView.loadAd(request);                
}

}
[/java]

And the android manifest:

[java]
<?xml version=“1.0” encoding=“UTF-8”?>
<manifest xmlns:android=“http://schemas.android.com/apk/res/android” android:versionCode=“8” android:versionName=“1.4” package=“com.galvezgames.tictactoerevolution”>
<application android:icon="@drawable/icon" android:label=“TicTacToe Revolution!”>
<activity android:label="@string/app_name" android:launchMode=“singleTask” android:name=“MainActivity”>
<intent-filter>
<action android:name=“android.intent.action.MAIN”/>
<category android:name=“android.intent.category.LAUNCHER”/>
</intent-filter>
</activity>
<activity android:name=“com.google.ads.AdActivity” android:configChanges=“keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize”/>
</application>
<uses-sdk android:minSdkVersion=“14”/>
<supports-screens android:anyDensity=“true” android:largeScreens=“true” android:normalScreens=“true” android:smallScreens=“true”/>
<uses-permission android:name=“android.permission.INTERNET”/>
<uses-permission android:name=“android.permission.ACCESS_NETWORK_STATE”/>
<uses-permission android:name=“android.permission.WRITE_EXTERNAL_STORAGE”/>
</manifest>
[/java]

I haven’t try to integrate the new google play api or intersticial ads, so no idea how it works, but I hope you can find something usefull from my code.

1 Like

Well… hopefully this is the missing piece for doing this! Why I didn’t consider the idea of modifying MainActivity in this way is making me feel a bit on the silly side :wink: I’ll give this a go and see if I can get the current Google Play Services API integrated. If it works, I’ll post the final walk-through here and maybe a Wiki page can be put together with a step-by-step tutorial for this.

Thanks so much for posting this @galvez6000 !!

Your are welcome t0neg0d!! Your work for the jme comunity is incredible.
When I finally had admob working in my game (after several crazy attemps) I also feel a bit on the silly side. Good luck with the Google Play stuff.

1 Like

Looks like this is at least on the proposed list for GSoC:

Integrate with Google Play game services

Mentors:
@iwgeric @zathras

Either of you have any word on whether this is happening or not? I’d rather not double up on an effort that is already happening/underway/soon-to-be/whatever.

Also, since AdMob is now part of Google Play Services, can this integration be added to the list of proposed features? Having a leaderboard is great… making money with your app is better :wink:

EDIT: Does this mean there will be some access point back to the app’s main activity to facilitate this? I’m still a bit confused on how to fire off ads etc from within a game.

@iwgeric - Could really use your input here.

I’ve finally gotten AdMod working through the latest Google Play Services API, however… the ads only display IF I return to the home screen (i.e. take focus away from the app) and then give focus back to the app.

Is there something I am missing here that would stop the ads from showing up above everything else?

I am calling bringToFront() … so really not sure what to do about this.

I’d love to get this resolved so I can write up a walk-through on this portion of integrating Google Play Services.

EDIT: I also need a way of calling back to the main activity to be able to control how and when ads are displayed. Is this possible?

Just wanted to let you know I saw this. I’m hoping to respond tomorrow sometime.

We call back from the main app to the android project to initiate the play store connection on a button click on the main app uif.

I just need to go back and look at what else we did.

@t0neg0d said: @iwgeric - Could really use your input here.

I’ve finally gotten AdMod working through the latest Google Play Services API, however… the ads only display IF I return to the home screen (i.e. take focus away from the app) and then give focus back to the app.

Sorry for the delay, been pretty busy lately the last few weeks.

Anyway, can you share how you are modifying the layout in MainActivity to include the ad view?

Personally, we’ve added “in-app purchases”, but we haven’t attempted ads yet. Honestly, I’m not sure how effective ads are in mobile games. That’s the main reason we haven’t attempted it yet.

Also, let me know if you are still looking for a way to trigger displaying the ad view from the main app. Calling a method in the android project from the main project is pretty easy. We did this to trigger the in-app purchase by having an interface defined in the main app and then implementing the interface in MainActivity.