Android Project Cheat Sheet

Thought I would compile some info for people since I can’t seem to add anything to the Wiki atm. Hoping this can be used temporarily as a place to add Advice/How To’s until it can be moved to the Wiki: If you have questions, create another topic please :wink: Just refer to the particular problem you encounter there.

Changing the Name of Your APK/Application:

  1. Open your project’s properties and navigate to Application
  2. Update the title

This has no real effect, however it keeps continuity throughout your app. Actually, this likely renamed the window created to display your app. So, now go change the actual name of your APK:

  1. Select File View in the left pane of the SDK
  2. Navigate to the mobile/res/values directory and open the strings.xml file
  3. There should be a string tag with the following key pair: name=“app_name”
  4. Replace MyGame with your app’s name and save the file.
  5. In File view, navigate to nbproject and open the project.properties file
  6. Edit the value of application.title to reflect your game’s name (unless step 1/2 above altered this for you)

Changing the APK Icon:

  1. Under the File view of your project navigate to mobile/res and add a “drawable” folder if one does not exist.
  2. Add you icon file (png)
  3. Open the Android Manifest file and add the following to your application tag: android:icon="@drawable/<ICON FILE NAME WITHOUT EXTENSION>"
  4. If you would like multiple size icons, add the following folders:
    ** drawable-hdpi (should contain the icon named the same at 72x72 pixels)
    ** drawable-ldpi (should contain the icon named the same at 36x36 pixels)
    ** drawable-mdpi (should contain the icon named the same at 48x48 pixels)
    ** drawable-xhdpi (should contain the icon named the same at 96x96 pixels)

Adding a Splash Screen to your app:

  1. Open Android Main Activity, ether through the Important Files list in Project view or in the File view under mobile/src/<package name>/ directory
  2. Add the following line to the MainActivity method:

splashPicID = R.drawable.<IMAGE NAME WITHOUT EXTENSION>;

  1. Add the image the the mobile/res/drawable directory

Compiling Google Play Services and Adding it to Your Project:

First get the api:

  1. Download the google play services add-on through the SDK Manager under Extras (named Google Play services)
  2. Copy the directory from where you downloaded it to another location (like JME Projects Folder)

Compile the jar file for use with your project:

  1. In the directory you copied, there is an android project file.
  2. In JME’s IDE, open this project
  3. In the General section of the project properties, there is a list of potential Android target platforms. Select the one you are using for your project by clicking on the list (this is not intuitive at all, as the list looks like nothing more than info… not selectable items)
  4. Under the Library section, click the checkbox that is labeled: Is Library
  5. Click Ok and then Clean & Build this project.

This will compile the play services all proper like so you can add it to your project. Now, for that step:

  1. Open your project’s properties.
  2. In the Libraries section, click the “Add JAR/folder” button.
  3. Find and add the jar you compiled above (This can be found in: <COPIED DIR>\libproject\google-play-services_lib\libs\google-play-services.jar
  4. Modify your Android Manifest by adding the following tags under application:
    <meta-data android:name=“com.google.android.gms.games.APP_ID”
    android:value="@string/app_id" />
    <meta-data android:name=“com.google.android.gms.version”
    android:value="@integer/google_play_services_version"/>
  5. Add the following tag to your mobile/res/values/integers.xml file (create it if it doesn’t exist):
    <integer name=“google_play_services_version”>4323000</integer>
  6. Clean & Build your project

Adding Play Games Services to Your Project:

  1. Download the project from: https://github.com/playgameservices/android-samples
  2. In the following directory, you find java files you will need to add to your project:
    ** <DOWNLOAD DIR>\android-samples-master\BasicSamples\libraries\BaseGameUtils\src\main\java\com\google\example\games\basegameutils
    ** Grab GameHelper.java and GameHelperUtil.java and add them to the directory you projects Main Activity is in
  3. In the following directoriy, you find a resource file you will need to add to your project:
    ** <DOWNLOAD DIR>\android-samples-master\BasicSamples\libraries\BaseGameUtils\src\main\res\values
    ** Grab the gamehelper_strings.xml into your mobile/res/values folder
  4. Add the following jar from the Adroid SDK folder to your project as a library:
    ** <ANDROID SDK INSTALL DIR>\adt-bundle-windows-x86_64-20131030\sdk\extras\android\support\v4\android-support-v4.jar

And this is the basics for setting this up.

Adding AdMob Support to Your Project:

  1. Open your Android Manifest and add the following tag update the application tag:
    <activity android:name=“com.google.android.gms.ads.AdActivity” android:configChanges=“keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize”/>
  2. After the application tag, add the following tags:
    <uses-permission android:name=“android.permission.INTERNET”/>
    <uses-permission android:name=“android.permission.ACCESS_NETWORK_STATE”/>
  3. In the onCreate method of your Main Activity, add the following snippet (configure however you like):

[java]
adView = new AdView(this);
adView.setAdSize(AdSize.FULL_BANNER);
adView.setAdUnitId("<WHATEVER AD UNIT ID YOU ARE ASSIGNED THROUGH THE GOOGLE DEV CONSOLE>");
adView.buildLayer();

	LinearLayout ll = new LinearLayout(this);
	ll.setGravity(Gravity.BOTTOM);
	ll.addView(adView);
	addContentView(ll, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));

[/java]

Ok, that’s all I have for now. Will add things as I find them.

8 Likes

Heh… almost forgot about this one. Thanks to @iwgeric for this one.

Communication Between your Application & Main Activity:

  1. Create an interface named something along the lines of JmeToHarness.java
  2. Open your Android Main Activity and implement this interface.
  3. In Main.java of your Application, add the following:

[java]
JmeToHarness harness;

public JmeToHarness getHarness() {
return this.harness;
}

public void setHarnessListener(JmeToHarness harness) {
this.harness = harness;
}
[/java]

  1. Add the following snippet to the onCreate method of your Android Main Activity:

[java]
if (app != null)
((Main)app).setHarnessListener(this);
[/java]

  1. Add error handling if you want it.

This bit is ultra useful for calling AdMob changes and Play Games methods (like updating achievements, leader boards, etc, etc)

EDIT: Keep this as generic as you possibly can as it should plug & play with iOS & Applets if you keep that in mind. Google Play Services/Play Games Services works for all of the above… soooo… anyways.

4 Likes

Changing the Package Name After Project Creation:

  1. Open the project properties of your Application
  2. Navigate to Application > Android and edit the package name.

This does absolutely nothing, but help with consistency.

So, to actually change the package name, you will want to:

  1. Open the Android Manifest
  2. Edit the manifest tag key pair: package="<THE NEW PACKAGE NAME>"
  3. In File view, navigate to nbproject and open the project.properties file
  4. Edit the value of mobile.android.package

Take a moment or 4 to navigate through the directory structure in file view and remove any artifacts left from the previous package name build. Alternately, you can run Clean on the project prior to updating the package name.

2 Likes

Day four I finally got that library to be referenced from my MainActivity!

A question… Will the advertisement appear in the debug version of the app, or only when downloaded through google play?

1 Like
@BigBob said: Day four I finally got that library to be referenced from my MainActivity!

A question… Will the advertisement appear in the debug version of the app, or only when downloaded through google play?

If you take a look at the other thread about um… AdMod and JME, you’ll see the following method: (or just grab it from here)

[java]
public void displayBannerAd() {
runOnUiThread(new Runnable() {
public void run() {
AdRequest adRequest = new AdRequest.Builder()
.addTestDevice(“<DEVICE ID HASH DUMPED IN LOGCAT>”)
.build();
adView.loadAd(adRequest);
adView.bringToFront();
adView.requestFocus();
}
});
}
[/java]

Once harness is set in your App, call:

[java]
harness.displayBannerAd();
[/java]

This will display test ads until you publish your App.

EDIT: You’ll need to add the displayBannerAd() method to the JmeToHarness interface of course.
EDIT 2: I’ve noticed it takes a good 30+ seconds for the test ads to start displaying.
EDIT 3: How about I answer your question now? lol Yes… they will display in an unsigned debug enabled app.

2 Likes

Where do I create the JmeToHarness interface?

This is an interface that I am creating myself , then implementing in the MainActivity?

Because as of now, my application crashes when I run the onCreate() method, even if it’s empty.

I’m definitely further than I was this morning though!

Hopefully this interface is going to be the last piece of the puzzle.

I’ve also never created an interface before :stuck_out_tongue:

And my total knowledge of them is that they are implemented…

My knowledge is obviously vast.

@BigBob said: Where do I create the JmeToHarness interface?

This is an interface that I am creating myself , then implementing in the MainActivity?

Because as of now, my application crashes when I have the onCreate() method with the stuff you suggest.

Hopefully this interface is going to be the last piece of the puzzle.

I’ve also never created an interface before :stuck_out_tongue:

And my total knowledge of them is that they are implemented…

My knowledge is obviously vast.

The interface can reside in your default project package. To create it, right click the package and select New > Java Interface

Here is a for instance:

[java]
public interface JmeToHarness {
public void displayInterstitialAd();
public void displayBannerAd();
public void initiateLogin(String UID, String PWD);
public void unlockAchievement(String uid);
public void submitScore(String uid, long score);
public void submitTime(String uid, long time);
}
[/java]

The update your main activity (it will looks something like):

[java]
public class MainActivity extends AndroidHarness implements JmeToHarness, GameHelper.GameHelperListener {

}
[/java]

Click on MainActivity shown above and ALT+ENTER then select implement all methods (or some such thing)

Now, instead of reference your MainActivity as MainActivity, you reference it as class type JmeToHarness and all declared methods in the interface will be visible.

Interfaces are super useful… worth exploring more after this for sure.

EDIT: A for instance for using an interface as apposed to a class…

You have a mesh class that contains a bunch of quads.
The mesh and the quads all need to be able to move independently of each other or as a whole.
Since the mesh as a whole will have a translation, rotation and scale and so will the individual quads, you would likely implement an interface called Transformable, containing methods for manipulating these common transforms.
The Object is a Mesh
The Quads are just data… not a mesh… just info about a small portion of the parent mesh.
All of your Action classes (used to manipulate translation, rotation and scale) would reference the object being manipulated as a Transformable (the interface) so the Action class doesn’t care if it is talking to a real Mesh or a small piece of the mesh being stored as data.

Interface is a serious butt saver and opens up a whole new world when you start looking at what they are capable of doing for you.

Note, that the file might show errors until you run Clean & Build

@t0neg0d

EDIT: FInally!

It is now working! I have ads displaying!

I didn’t need to create the interface after all, and it was easier than I was making it… The late appearing advertisements kinda psyched me out, but I have it!

An advertisement!

1 Like

Thank you t0neg0d

This forum topic is really very helpful and we must seriously try and get it onto the wiki.

You are the best.
:google:

1 Like

Adding tips for maximizing performance in JME for a mobile platform and such: These are ideas, not have to’s.

Separating Your Logical Update from Your Render Update Loop

I’ve noticed the more complex your scene is, the less accurate your game logic is due to being blocked by the speed of the graphical update (well… accurate, just not as finite as you may want it). So, a potential solution for this is to run you game logic on a separate thread that creates it’s own NanoTimer. and then enqueue the updates back to the main render loop.

For this, you will likely not need to bother with a executor… just a simple Thread will do. Your run method (loop) should start by calling update on the timer and then use getTimePerFrame() when calling associated logic-separated classes’ update methods.

It’s a little more to manage as you have your visual component completely separate from your logic, can’t use Controls and HAVE to enqueue all updates to the scene-graph… however you can easily mimic Controls using the above method and it seems to have a fairly significant impact on both updates to your game’s logic as well as speeding up rendering by stripping this out of the render loop.

One other added benefit is, you can pause your logical game timer while the other is still running. This can help avoid unwanted large TPF updates for both this scenario and render lag.

I’d likely never consider this approach on a desktop game, but every little bit helps with mobile dev, so thought I would throw the idea out there.

1 Like

Wow, this is a very interesting idea and could definitely help.
What would be great is if this approach really do make a difference that the team might consider incorporating it into the engine.

I’ve made a wiki page of this…and almost lost my sanity trying to find out how to create a page on this wiki (@erlend_sh at some point we had a menu and this was pretty straight forward…)
anyway here is the link https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:advanced:android

Find out that to edit a wikipage (or create one) you have to add ?do=edit at the end of the url of the page.

@t0neg0d hopefully you’ll be able to edit the page

Hello,

I need to create a popup window in my app for android, and i’m using Nifty but the problem now is the execution time the popup window. How can i create a popup window for android? or how can i do to decrease the execution time using Nyfty?.

Thanks.

@nehon said: I've made a wiki page of this...and almost lost my sanity trying to find out how to create a page on this wiki (@erlend_sh at some point we had a menu and this was pretty straight forward....) anyway here is the link https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:advanced:android

Find out that to edit a wikipage (or create one) you have to add ?do=edit at the end of the url of the page.

t0neg0d hopefully you’ll be able to edit the page

I changed the dokuwiki template to have the original dokuwiki buttons at the top and bottom until somebody fixes the admin bar.

1 Like

Looks as if I can edit it (at least I could see the edit buttons) Thanks for this, guys! It’s much easier writting this stuff down than trying to remember it. I’ll likely post any updates here first to let other review them and decide whether they should be added to the Wiki.

Here is another really useful bit:

Saving & Loading Game Data:

First, it’s important to know where you can save data to. Each APK has default read/write access to a directory created specifically for your games data. The directory is protected, keeping the user from browsing/changing files in this directory unless the device has been rooted.

The directory you will use is as follows:

data/data/<YOUR PACKAGE NAME>/

An example of this would be:

data/data/com.mycompany.mygame/

And here is an example of using JME’s BinaryExporter to save game data as user data of a Node:

[java]
public void saveGame(String name, Node node) {
BinaryExporter exporter = BinaryExporter.getInstance();
// No slash at the begin of the path
File file = new File(“data/data/<YOUR PACKAGE NAME>/” + name + “.j3o”);
try {
exporter.save(node, file);
} catch (IOException ex) {
Logger.getLogger(getClass().getName()).log(Level.SEVERE, “Error: Failed to save game.”, ex);
}
}

public Node loadGame(String name) {
// Added slash to the beginning of the path
// Also note that this only needs to be registered once, so do this some place else :wink:
main.getAssetManager().registerLocator("/data/data/<YOUR PAKAGE NAME>/", FileLocator.class);
Node node = (Node)main.getAssetManager().loadModel(name + “.j3o”);
return node;
}
[/java]

I would also suggest nesting nodes to help organize you save data. For example:

[java]
Node profiles = new Node(“Profiles”);

Node p1 = new Node(“Profile1”);
p1.setUserData(“profileName”, “Profile 1”);
p1.setUserData(“someKey”, someData);
p1.setUserData(“anotherKey”, moreData);

Node p2 = new Node(“Profile2”);
p2.setUserData(“profileName”, “Profile 2”);
p2.setUserData(“someKey”, someData);
p2.setUserData(“anotherKey”, moreData);

profiles.attachChild(p1);
profiles.attachChild(p2);
profiles.setUserData(“defaultProfile”, “Profile 1”);

saveGame(“profiles”, profiles);
[/java]

Then, when reading back in profiles, you can loop through the children Nodes to retrieve the available profiles:

[java]
Node profiles = loadGame(“profiles”);
String defaultProfileName = profiles.getUserData(“defaultProfile”);
for (Spatial s : profiles.getChildren()) {
if ((String)((Node)s).getUserData(“profileName”)).equals(defaultProfileName)) {
// etc, etc…
}
}
[/java]

2 Likes

One more… this is a little on the General side, but very useful static methods for multi-platform dev, especilly considering the save game tip above…

Determining the OS Your App is Running On:

(Would really appreciate an addition to this for iOS :wink:

[java]
public static boolean isWindows() {
String OS = System.getProperty(“os.name”).toLowerCase();
return (OS.indexOf(“win”) >= 0);
}
public static boolean isMac() {
String OS = System.getProperty(“os.name”).toLowerCase();
return (OS.indexOf(“mac”) >= 0);
}
public static boolean isUnix() {
String OS = System.getProperty(“os.name”).toLowerCase();
return (OS.indexOf(“nix”) >= 0 || OS.indexOf(“nux”) >= 0 || OS.indexOf(“aix”) >= 0 );
}
public static boolean isSolaris() {
String OS = System.getProperty(“os.name”).toLowerCase();
return (OS.indexOf(“sunos”) >= 0);
}
public static boolean isAndroid() {
String OS = System.getProperty(“java.vendor”).toLowerCase();
return (OS.indexOf(“android”) >= 0);
}
[/java]

1 Like

I don’t currently own a smartphone, but I’m sure one day I will… and zomg, then, I’ll be reading this in loop.
Brilliant, thx!

1 Like

@t0neg0d for saving the game, we have a SaveGame class that deals with this kind of things

It saves a Savable so basically it can save a Node as you did, but you can also have your own class that implements savable.

The major advantage over your way is that it seamlessly work on desktop and on android.