You are here

Chapter 10: Create the app's four pages

Now it's time to create the four different "pages" I sketched down in Chapter 05:

Let's start with declaring three new activities in the AndroidManifest.xml file. We can put the directly beneath our AdActivity:

    <activity
        android:name=".GameActivity"
        android:label="Game Activity"
        android:screenOrientation="portrait"
        android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"
    />
    <activity
        android:name=".HowtoActivity"
        android:label="Howto Activity"
        android:screenOrientation="portrait"
        android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"
    />
    <activity
        android:name=".CreditsActivity"
        android:label="Credits Activity"
        android:screenOrientation="portrait"
        android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"
    />

While here, we can also remove the title bar from the main ".JustRoidsActivity" (our main menu) by adding a line to that block of code:

        <activity
            android:name=".JustRoidsActivity"
            android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

Next step is to implement the three activities we just declared.

If we expand "src" and the package within it, we will see that only our main activity is there:

Right-click on the package and select "New" -> "Class":

Enter "GameActivity" as name and click "Browse":

Search for "Activity", select "Activity - android.app" and click "OK":

Then click "Finish":

A more or less empty class file is now created for you:

Repeat the same procedure ("New" -> "Class") and create "HowtoActivity" and "CreditsActivity" in the same manner, so that we have four java files in total in our package:

 

Next step is to create three new "layouts".

If we expand "res/layout" we'll see only main.xml there:

Mark "main.xml" and press ctrl-c to copy the file.

Then press ctrl-v and enter "credits.xml" as name. Repeat for "game.xml" and "howto.xml", so that we have four layout files in total:

Very soon we will edit the three new layouts, so that we can see the difference between them when we make our first test, but first this:

In order to make an app easy to adapt to additional languages, you should never have any text strings hard coded in your source, but rather in a separate resource file, that later on can be duplicated and edited for each supported language. We do this by opening up the file "res/values/strings.xml" and add the four lines:

    <string name="justroids">JustRoids</string>
    <string name="credits">Credits</string>
    <string name="play">Play</string>
    <string name="howto">HowTo</string>

Now we have four new text resources that we can refer to in our layouts.

Give "android:text" in credits.xml the value "@string/credits" :

 

Make the corresponding changes in game.xml and howto.xml.

 

Well, now we're finished with three layouts - time to let our three latest activities display them. 

Edit HowtoActivity.java and add an override on onCreate where we specify that the layout "howto" shall be shown:

package com.ajomannen.justroids;

import android.app.Activity;
import android.os.Bundle;

public class HowtoActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.howto);
    }
   
}

Repeat this for CreditsActivity.java (credits) and GameActivity.java (game).

 

These three were the easy ones, as they don't contain any functionality for navigating to other pages. (The handling of "Back" and "Home" is something that Android handle for us automatically.)

 

Our main menu (JustRoidsActivity.java / main.xml) is a bit more complex, though.

To begin with, main.xml should contain our four different text-images; one logo plus three buttons that links to the other pages. Furthermore it shall contain a special ad-view. (I decided to change my the idea of having ads displayed during the gameplay, to have them in the main menu instead. It is quite possible that I also decide to put ads in the Credits and HowTo pages later on.)

Open up main.xml in text mode, remove the existing content and paste the following instead:

<?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:id="@+id/rootLayout"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <ImageView
        android:id="@+id/imgLogo"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:adjustViewBounds="true"
        android:contentDescription="@string/justroids"
        android:src="@drawable/justroids" />

    <ImageView
        android:id="@+id/btnGame"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/imgLogo"
        android:layout_gravity="center_horizontal"
        android:clickable="true"
        android:contentDescription="@string/play"
        android:onClick="onClickGame"
        android:src="@drawable/play" />

    <ImageView
        android:id="@+id/btnHowto"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/btnGame"
        android:layout_gravity="center_horizontal"
        android:clickable="true"
        android:contentDescription="@string/howto"
        android:onClick="onClickHowto"
        android:src="@drawable/howto" />

    <ImageView
        android:id="@+id/btnCredits"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/btnHowto"
        android:layout_gravity="center_horizontal"
        android:clickable="true"
        android:contentDescription="@string/credits"
        android:onClick="onClickCredits"
        android:src="@drawable/credits" />

    <com.google.ads.AdView
        android:id="@+id/adView"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerInParent="false"
        ads:adSize="BANNER"
        ads:adUnitId="XXXXXXXXXXXXXXX"
        android:gravity="bottom"
        ads:loadAdOnCreate="false"
        ads:test="true"
        android:visibility="visible" />

</RelativeLayout>

(The value of "ads.adUnitId" shall be the AdMob Publisher Id you wrote down somewhere safe earlier.)

You can double check that all objects shows up by clicking the "Graphical Layout" tab:

 

What remains now is to make JustRoidsActivity.java look like this:

package com.ajomannen.justroids;

import com.google.ads.AdRequest;
import com.google.ads.AdView;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;

public class JustRoidsActivity extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);

  AdView adView = (AdView) findViewById(R.id.adView);
  AdRequest adRequest = new AdRequest();
  adRequest.addTestDevice(AdRequest.TEST_EMULATOR);
  // adRequest.addTestDevice("E213A781A27DEE785F5CCD8A07BF21BF");
  adView.loadAd(adRequest);
}

public void onClickGame(View v) {
  Toast.makeText(this, "You clicked on Game!", Toast.LENGTH_LONG).show();
  Intent intent = new Intent(this, GameActivity.class);
  startActivity(intent);
}

public void onClickHowto(View v) {
  Toast.makeText(this, "You clicked on Howto!", Toast.LENGTH_LONG).show();
  Intent intent = new Intent(this, HowtoActivity.class);
  startActivity(intent);
}

public void onClickCredits(View v) {
  Toast.makeText(this, "You clicked on Credits!", Toast.LENGTH_LONG) .show();
  Intent intent = new Intent(this, CreditsActivity.class);
  startActivity(intent);
}

}

What we have done here is to find the ad view and load it with an ad (the orange block) at app startup and add three handlers for the differnt onClick-events we created earlier.

Observe that you should run your ad-integration in so called "Test-mode" while developing the app. This is done by 1) Setting "ads:test" to "true" in the ad view in main.xml and 2) Including the device you're testing on in the orange block (addTestDevice). Virtual devices, such as the one we created, should already be covered in the code above, and the out-commented line is an example of how a real physical device is added.

 

At this stage, our app only contains four different pages and the mechanism to navigate between them, but this is a good point to start it up and verify that we've got it right so far.

Press ctrl-F11 to install it on your virtual device and run it.

If everything's in order, you will eventually see the main menu:

Now try pressing "Play":

(I just noticed a bit of inconsistency regarding the use of the words "game" and "play", but that's not a bug. It's by design.)

Now we can verify the the rest of the page navigation works as intended; the back-button on the device should take you back to the main menu, while the home-button should put the app into the background and take you to the Android start screen. If you start the app again, it should display the page that was active when you left it.

 

This means that we are done with the basic framework, and the coming chapters will be a bit more advanced.

 

Requirements implemented in this chapter

✔ 01. The app shall be started through a clickable icon as any other app.

✔ 02. When the app is started, the Main Menu shall be shown, unless the app already was running in the background - in that case the last viewed page shall be shown.

✔ 03. On the Main Menu there shall be three links to the other pages; Play, How-To and Credits.

✔ 07. When pressing "Back" on your Android device, you shall end up "one page up". If your already on "Main Menu", the app shall be closed.

✔ 08. When pressing "Home", the app shall be put in the background and the Android device shall display the standard Android Home Screen.

Comments

Im an IT student and currently working my first android game and
while Im working on this chapter Im having this kind of error
"No resource found that matches the given name (at 'contentDescription' with value '@string/mosquito')."
what can I do to fix this ?? please help me sir .. thank you in advance !

ajo's picture

Hi Cabs,
It looks like you are missing the definition of "mosquito" in res/values/strings.xml.
Do you have a line like: <string name="mosquito">Mosquito</string> in the <resources> section?

BR - Anders

Thank you sir for your help ! :) I gotta go on to finish my project .

Hello Anders,
 
I am learning android from your Chapters and im doing the same step which you have explained.
In Chapter 10: Create your app's four page, I have done the steps explained but I have a issue when i click the button (say Play). I get a error message in my virtual device "Unfortunatly Page has stopped".
Note: My package name is Page (com.example.page))
Below is the LogCat for the issue:
03-22 03:45:40.971: D/dalvikvm(1158): GC_CONCURRENT freed 285K, 15% free 2581K/3012K, paused 37ms+13ms, total 237ms
 

03-22 03:45:40.971: D/dalvikvm(1158): WAIT_FOR_CONCURRENT_GC blocked 101ms

03-22 03:45:41.191: I/Choreographer(1158): Skipped 67 frames!  The application may be doing too much work on its main thread.

03-22 03:45:41.672: I/Choreographer(1158): Skipped 161 frames!  The application may be doing too much work on its main thread.

03-22 03:45:41.861: D/gralloc_goldfish(1158): Emulator without GPU emulation detected.

03-22 03:46:05.892: D/AndroidRuntime(1158): Shutting down VM

03-22 03:46:05.892: W/dalvikvm(1158): threadid=1: thread exiting with uncaught exception (group=0x40a71930)

03-22 03:46:06.051: E/AndroidRuntime(1158): FATAL EXCEPTION: main

03-22 03:46:06.051: E/AndroidRuntime(1158): java.lang.IllegalStateException: Could not execute method of the activity

03-22 03:46:06.051: E/AndroidRuntime(1158): at android.view.View$1.onClick(View.java:3599)

03-22 03:46:06.051: E/AndroidRuntime(1158): at android.view.View.performClick(View.java:4204)

03-22 03:46:06.051: E/AndroidRuntime(1158): at android.view.View$PerformClick.run(View.java:17355)

03-22 03:46:06.051: E/AndroidRuntime(1158): at android.os.Handler.handleCallback(Handler.java:725)

03-22 03:46:06.051: E/AndroidRuntime(1158): at android.os.Handler.dispatchMessage(Handler.java:92)

03-22 03:46:06.051: E/AndroidRuntime(1158): at android.os.Looper.loop(Looper.java:137)

03-22 03:46:06.051: E/AndroidRuntime(1158): at android.app.ActivityThread.main(ActivityThread.java:5041)

03-22 03:46:06.051: E/AndroidRuntime(1158): at java.lang.reflect.Method.invokeNative(Native Method)

03-22 03:46:06.051: E/AndroidRuntime(1158): at java.lang.reflect.Method.invoke(Method.java:511)

03-22 03:46:06.051: E/AndroidRuntime(1158): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)

03-22 03:46:06.051: E/AndroidRuntime(1158): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)

03-22 03:46:06.051: E/AndroidRuntime(1158): at dalvik.system.NativeStart.main(Native Method)

03-22 03:46:06.051: E/AndroidRuntime(1158): Caused by: java.lang.reflect.InvocationTargetException

03-22 03:46:06.051: E/AndroidRuntime(1158): at java.lang.reflect.Method.invokeNative(Native Method)

03-22 03:46:06.051: E/AndroidRuntime(1158): at java.lang.reflect.Method.invoke(Method.java:511)

03-22 03:46:06.051: E/AndroidRuntime(1158): at android.view.View$1.onClick(View.java:3594)

03-22 03:46:06.051: E/AndroidRuntime(1158): ... 11 more

03-22 03:46:06.051: E/AndroidRuntime(1158): Caused by: android.content.ActivityNotFoundException: Unable to find explicit activity class {com.example.page/com.example.page.Page3}; have you declared this activity in your AndroidManifest.xml?

03-22 03:46:06.051: E/AndroidRuntime(1158): at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1618)

03-22 03:46:06.051: E/AndroidRuntime(1158): at android.app.Instrumentation.execStartActivity(Instrumentation.java:1417)

03-22 03:46:06.051: E/AndroidRuntime(1158): at android.app.Activity.startActivityForResult(Activity.java:3370)

03-22 03:46:06.051: E/AndroidRuntime(1158): at android.app.Activity.startActivityForResult(Activity.java:3331)

03-22 03:46:06.051: E/AndroidRuntime(1158): at android.app.Activity.startActivity(Activity.java:3566)

03-22 03:46:06.051: E/AndroidRuntime(1158): at android.app.Activity.startActivity(Activity.java:3534)

03-22 03:46:06.051: E/AndroidRuntime(1158): at com.example.page.PageActivity.onClickPage3(PageActivity.java:32)

03-22 03:46:06.051: E/AndroidRuntime(1158): ... 14 more

03-22 03:51:06.541: I/Process(1158): Sending signal. PID: 1158 SIG: 9

 
Kindly help me solving this issue, it will be very usefull for my android learning.
Thanks in Advance !!
Rajesh
 
 

ajo's picture

Hi Rajesh,
There is one line in the stack trace, that caught my attention:

03-22 03:46:06.051: E/AndroidRuntime(1158): Caused by: android.content.ActivityNotFoundException: Unable to find explicit activity class {com.example.page/com.example.page.Page3}; have you declared this activity in your AndroidManifest.xml
 
Could you double check that your AndroidManifest.xml really inclues a definition of your activity?
BR - Anders

Theme by Danetsoft and Danang Probo Sayekti inspired by Maksimer