Sunday, February 17, 2013

JSON in Android

In this post I will show you how to get JSON data from a HTTP server and parse it in android.
The JSON data that we will parse in this tutorial is the following:

{
  "status" : "ok",
  "score" : 101,
  "friends" : [{"id" : 321, "score" : 100}, {"id" : 320, "score" : 105}]
}

We will assume that you can access this data from the URL: http://server.com/json

The first step is to get the data in you android application. Since we will download it from a server, you will first need to specify the internet permission in you Android Manifest file:

<uses-permission android:name="android.permission.INTERNET" />

Now that we set this permission, we can download the data. Since we can't use the main thread for networking, we will create a new thread to download our data and parse it. Add the following code in your onCreate method, in your Activity class.

new Thread() {
  public void run() {
    helloJson();
  }
}.start();

Next, we will create the helloJson method, containing the following code:

public void helloJson() {
    StringBuilder builder = new StringBuilder();
    
    try {
      HttpClient client = new DefaultHttpClient();
      HttpGet httpGet = new HttpGet("http://server.com/json");
  
      HttpResponse response = client.execute(httpGet);
      int statusCode = response.getStatusLine().getStatusCode();
      
      if (statusCode == 200) {
        HttpEntity entity = response.getEntity();
        InputStream content = entity.getContent();
        InputStreamReader reader = new InputStreamReader(content)
        BufferedReader reader = new BufferedReader(reader);
        String line;
        while ((line = reader.readLine()) != null) {
          builder.append(line);
        }
        JSONObject jobj = new JSONObject(builder.toString());
        builder = new StringBuilder(jobj.get("status").toString());
        JSONArray jar = jobj.optJSONArray("friends");
        builder.append(jar.length());
      }
    }
    catch(Exception e) {
      e.printStackTrace();
      builder.append(e);
    }
    
    final String str = builder.toString();
    runOnUiThread(new Runnable() {
      @Override
      public void run() {
        Toast.makeText(MainActivity.this, str, Toast.LENGTH_LONG).show();
      }
    });
  }

This will display a message using Toast, containing the status string and the length of the friends array.

That's it! :)

Wednesday, February 6, 2013

Admob with Andengine

If you have a game developed with Andengine you probably don't use a XML layout file and your activity simply extends the BaseGameActivity class or the SimpleBaseGameActivity class.
I assume that you know hot to add the Admob jar to your project and to set the required permissions in the AndroidManifest file. If you don't, then check the tutorials on the Admob web site first.

The first thing you need to do is create a new XML layout file, let's call it game_layout.xml
The content of this file should be similar to the following:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:ads="http://schemas.android.com/apk/lib/com.google.ads"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#000000"
    android:orientation="vertical" >

    <org.andengine.opengl.view.RenderSurfaceView
        android:id="@+id/SurfaceViewId"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentTop="true"
        android:gravity="center" />

    <com.google.ads.AdView
        android:id="@+id/adViewId"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        ads:adSize="BANNER"
        ads:adUnitId="YOU_ID_HERE"
        ads:loadAdOnCreate="true" />
    
</RelativeLayout>

In this case, the Layout is RelativeLayout, because we want the ad to be drawn over the game surface. Based on your requirements, you could try to use a other layouts, but i find the relative one to be the best. Inside the layout there are 2 components, the surface view and the ad view, each with it's own id (adViewId and SurfaceViewId). Also, don't forget to define the namespace for the Admob components, in my case "ads:".


Now that we have our layout file, we must include it in the activity. In a normal android application you could do this by calling setContentView(R.layout.game_layout);  in the onCreate method of the activity. In Andengine, we need to use a different approach.
I will assume that you extend the SimpleBaseGameActivity class because the first step you need to do is adapt the class to extend the BaseGameActivity class.
The class hierarchy for the activity classes in Andengine is presented in the following figure:


In order to display ads we must extend the LayoutGameActivity class.
Let's assume that you have the following class that extends the SimpleBaseGameActivity:
public class MainActivity extends SimpleBaseGameActivity {

  public static final int CAMERA_HEIGHT = 720;
  public static final int CAMERA_WIDTH = 480;

  private Camera camera;
  private BitmapTexture blocksTexture;

  @Override
  public EngineOptions onCreateEngineOptions() {
    this.camera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
    EngineOptions engineOptions = new EngineOptions(true,
        ScreenOrientation.PORTRAIT_FIXED,
        new FillResolutionPolicy(), camera);
    return engineOptions;
  }

  @Override
  protected void onCreateResources() {
    try {
      this.blocksTexture = new BitmapTexture(this.getTextureManager(),
            new IInputStreamOpener() {
        @Override
        public InputStream open() throws IOException {
          return getAssets().open("gfx/block.png");
        }
      });
      blocksTexture.load();
      
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  @Override
  protected Scene onCreateScene() {
    GameScene scene = new GameScene(blocksTexture, this);
    this.mEngine.registerUpdateHandler(scene);
    return scene;
  }

}

This is a minimalist class, with all the logic defined in the GameScene class, for the sake of simplicity.
After extending the LayoutGame class, the file will look like this:
public class MainActivity extends LayoutGameActivity {

  public static final int CAMERA_HEIGHT = 720;
  public static final int CAMERA_WIDTH = 480;

  private Camera camera;
  private BitmapTexture blocksTexture;

  @Override
  public EngineOptions onCreateEngineOptions() {
    this.camera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
    EngineOptions engineOptions = new EngineOptions(true,
        ScreenOrientation.PORTRAIT_FIXED,
        new FillResolutionPolicy(), camera);
    return engineOptions;
  }

  @Override
  public void onCreateResources(
      OnCreateResourcesCallback pOnCreateResourcesCallback)
          throws Exception {
    try {
      this.blocksTexture = new BitmapTexture(this.getTextureManager(),
            new IInputStreamOpener() {
        @Override
        public InputStream open() throws IOException {
          return getAssets().open("gfx/block.png");
        }
      });
      blocksTexture.load();

    } catch (IOException e) {
      e.printStackTrace();
    }
    pOnCreateResourcesCallback.onCreateResourcesFinished();
  }

  @Override
  public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback)
      throws Exception {
    GameScene scene = new GameScene(blocksTexture, this);
    this.mEngine.registerUpdateHandler(scene);
    pOnCreateSceneCallback.onCreateSceneFinished(scene);
  }

  @Override
  public void onPopulateScene(Scene pScene,
      OnPopulateSceneCallback pOnPopulateSceneCallback) throws Exception {
    pOnPopulateSceneCallback.onPopulateSceneFinished();
  }

  @Override
  protected int getLayoutID() {
    return R.layout.game_layout;
  }

  @Override
  protected int getRenderSurfaceViewID() {
    return R.id.SurfaceViewId;
  }

}

There are 2 methods related to the layout file. The first method is getLayoutID, that must return the id of the file containing the layout. The other method is getRenderSurfaceViewID, that must return the id of the surface view.
The other methods simply do what the SimpleBaseGameActivity class does for the BasicGameActivity.

This is all you need to do in order to display ads in an Andengine game.

Friday, February 1, 2013

Nvidia Optimus support in Ubuntu


If you have a laptop with nVidia Optimus and you run Linux (in my case Ubuntu) it will drain your battery very fast (in my case 2-3 times faster than on Windows).

In order to counter this, I install Bumblebee on my laptop. This will allow you to use the discrete graphics card when you need it and turn it off when you don't.
Bumblebee 3.0 is supported up to Ubuntu version 12.10.


In order to install Bumblebee enter the following commands in a terminal:
  1. sudo add-apt-repository ppa:bumblebee/stable
  2. sudo apt-get update
  3. sudo apt-get install bumblebee bumblebee-nvidia linux-headers-generic
  4. Reboot
To run a program using the nVidia card run:
optirun firefox
If you have problems please check the references.

References:
https://wiki.ubuntu.com/Bumblebee
http://bumblebee-project.org/
https://github.com/Bumblebee-Project/Bumblebee