Commits

Christian Fischer  committed e74244e

win32 / android project setup

  • Participants
  • Parent commits cbbdfe9

Comments (0)

Files changed (43)

+
+syntax:glob
+
+#ignore thumbnails created by windows
+Thumbs.db
+#Ignore files build by Visual Studio
+*.obj
+*.exe
+*.pdb
+*.aps
+*.vcproj.*.user
+*.vspscc
+*_i.c
+*.i
+*.icf
+*_p.c
+*.ncb
+*.suo
+*.tlb
+*.tlh
+*.bak
+*.cache
+*.ilk
+*.log
+[Bb]in
+[Dd]ebug*/
+*.sbr
+obj/
+[Rr]elease*/
+_ReSharper*/
+[Tt]est[Rr]esult*
+
+# Ignore files build by ndk and eclipse
+android/gen/
+android/libs/
+android/bin/
+android/obj/
+android/assets/
+android/local.properties
+.classpath
+.project
+.cproject
+
+# Ignore files build by linux
+*.o
+
+# Ignore files build by airplay
+build_*_xcode/
+
+# Ignore files build by xcode
+*.mode*v*
+*.pbxuser
+*.xcbkptlist
+*.xcscheme
+*.xcworkspacedata
+*.xcuserstate
+xcschememanagement.plist
+build/
+.DS_Store

File Classes/Android.mk

+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := game_logic_static
+
+LOCAL_MODULE_FILENAME := libgame_logic
+
+LOCAL_SRC_FILES := AppDelegate.cpp \
+                   HelloWorldScene.cpp
+                   
+LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
+
+LOCAL_STATIC_LIBRARIES := png_static_prebuilt
+LOCAL_STATIC_LIBRARIES += xml2_static_prebuilt
+LOCAL_STATIC_LIBRARIES += jpeg_static_prebuilt
+LOCAL_WHOLE_STATIC_LIBRARIES += cocos2dx_static
+                
+LOCAL_SHARED_LIBRARIES := cocosdenshion_shared
+            
+include $(BUILD_STATIC_LIBRARY)
+
+$(call import-module,cocos2dx/platform/third_party/android/modules/libpng)
+$(call import-module,cocos2dx/platform/third_party/android/modules/libxml2)
+$(call import-module,cocos2dx/platform/third_party/android/modules/libjpeg)

File Classes/AppDelegate.cpp

+#include "AppDelegate.h"
+
+#include "cocos2d.h"
+#include "HelloWorldScene.h"
+
+#include "CCEGLView.h"
+
+USING_NS_CC;
+
+AppDelegate::AppDelegate() {
+
+}
+
+AppDelegate::~AppDelegate() {
+}
+
+bool AppDelegate::initInstance() {
+	bool bRet = false;
+	do {
+#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
+
+		// Initialize OpenGLView instance, that release by CCDirector when application terminate.
+		// The HelloWorld is designed as HVGA.
+		CCEGLView * pMainWnd = new CCEGLView();
+		CC_BREAK_IF(! pMainWnd
+				|| ! pMainWnd->Create(TEXT("cocos2d: Hello World"), 480, 320));
+
+#endif  // CC_PLATFORM_WIN32
+#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
+
+		// OpenGLView initialized in testsAppDelegate.mm on ios platform, nothing need to do here.
+
+#endif  // CC_PLATFORM_IOS
+#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
+
+		// OpenGLView initialized in HelloWorld/android/jni/helloworld/main.cpp
+		// the default setting is to create a fullscreen view
+		// if you want to use auto-scale, please enable view->create(320,480) in main.cpp
+		// if the resources under '/sdcard" or other writeable path, set it.
+		// warning: the audio source should in assets/
+		// cocos2d::CCFileUtils::setResourcePath("/sdcard");
+
+#endif  // CC_PLATFORM_ANDROID
+#if (CC_TARGET_PLATFORM == CC_PLATFORM_WOPHONE)
+
+		// Initialize OpenGLView instance, that release by CCDirector when application terminate.
+		// The HelloWorld is designed as HVGA.
+		CCEGLView* pMainWnd = new CCEGLView(this);
+		CC_BREAK_IF(! pMainWnd || ! pMainWnd->Create(320,480, WM_WINDOW_ROTATE_MODE_CW));
+
+#ifndef _TRANZDA_VM_  
+		// on wophone emulator, we copy resources files to Work7/NEWPLUS/TDA_DATA/Data/ folder instead of zip file
+		cocos2d::CCFileUtils::setResource("HelloWorld.zip");
+#endif
+
+#endif  // CC_PLATFORM_WOPHONE
+#if (CC_TARGET_PLATFORM == CC_PLATFORM_MARMALADE)
+		// MaxAksenov said it's NOT a very elegant solution. I agree, haha
+		CCDirector::sharedDirector()->setDeviceOrientation(kCCDeviceOrientationLandscapeLeft);
+#endif
+#if (CC_TARGET_PLATFORM == CC_PLATFORM_LINUX)
+
+		// Initialize OpenGLView instance, that release by CCDirector when application terminate.
+		// The HelloWorld is designed as HVGA.
+		CCEGLView * pMainWnd = new CCEGLView();
+		CC_BREAK_IF(! pMainWnd
+				|| ! pMainWnd->Create("cocos2d: Hello World", 480, 320 ,480, 320));
+
+		CCFileUtils::setResourcePath("../Resources/");
+
+#endif  // CC_PLATFORM_LINUX
+
+#if (CC_TARGET_PLATFORM == CC_PLATFORM_BADA)
+
+		CCEGLView * pMainWnd = new CCEGLView();
+		CC_BREAK_IF(! pMainWnd|| ! pMainWnd->Create(this, 480, 320));
+		pMainWnd->setDeviceOrientation(Osp::Ui::ORIENTATION_LANDSCAPE);
+		CCFileUtils::setResourcePath("/Res/");
+
+#endif  // CC_PLATFORM_BADA
+
+#if (CC_TARGET_PLATFORM == CC_PLATFORM_QNX)
+		CCEGLView * pMainWnd = new CCEGLView();
+		CC_BREAK_IF(! pMainWnd|| ! pMainWnd->Create(1024, 600));
+		CCFileUtils::setResourcePath("app/native/Resources");
+#endif // CC_PLATFORM_QNX
+		bRet = true;
+	} while (0);
+	return bRet;
+}
+
+bool AppDelegate::applicationDidFinishLaunching() {
+	// initialize director
+	CCDirector *pDirector = CCDirector::sharedDirector();
+
+	pDirector->setOpenGLView(&CCEGLView::sharedOpenGLView());
+
+	// enable High Resource Mode(2x, such as iphone4) and maintains low resource on other devices.
+//     pDirector->enableRetinaDisplay(true);
+
+	// turn on display FPS
+	pDirector->setDisplayFPS(true);
+
+	// pDirector->setDeviceOrientation(kCCDeviceOrientationLandscapeLeft);
+
+	// set FPS. the default value is 1.0/60 if you don't call this
+	pDirector->setAnimationInterval(1.0 / 60);
+
+	// create a scene. it's an autorelease object
+	CCScene *pScene = HelloWorld::scene();
+
+	// run
+	pDirector->runWithScene(pScene);
+
+	return true;
+}
+
+// This function will be called when the app is inactive. When comes a phone call,it's be invoked too
+void AppDelegate::applicationDidEnterBackground() {
+	CCDirector::sharedDirector()->pause();
+
+	// if you use SimpleAudioEngine, it must be pause
+	// SimpleAudioEngine::sharedEngine()->pauseBackgroundMusic();
+}
+
+// this function will be called when the app is active again
+void AppDelegate::applicationWillEnterForeground() {
+	CCDirector::sharedDirector()->resume();
+
+	// if you use SimpleAudioEngine, it must resume here
+	// SimpleAudioEngine::sharedEngine()->resumeBackgroundMusic();
+}

File Classes/AppDelegate.h

+#ifndef  _APP_DELEGATE_H_
+#define  _APP_DELEGATE_H_
+
+#include "CCApplication.h"
+
+/**
+@brief	The cocos2d Application.
+
+The reason for implement as private inheritance is to hide some interface call by CCDirector.
+*/
+class  AppDelegate : private cocos2d::CCApplication
+{
+public:
+	AppDelegate();
+	virtual ~AppDelegate();
+
+    /**
+    @brief	Implement for initialize OpenGL instance, set source path, etc...
+    */
+    virtual bool initInstance();
+
+    /**
+    @brief	Implement CCDirector and CCScene init code here.
+    @return true    Initialize success, app continue.
+    @return false   Initialize failed, app terminate.
+    */
+    virtual bool applicationDidFinishLaunching();
+
+    /**
+    @brief  The function be called when the application enter background
+    @param  the pointer of the application
+    */
+    virtual void applicationDidEnterBackground();
+
+    /**
+    @brief  The function be called when the application enter foreground
+    @param  the pointer of the application
+    */
+    virtual void applicationWillEnterForeground();
+};
+
+#endif // _APP_DELEGATE_H_
+

File Classes/HelloWorldScene.cpp

+#include "HelloWorldScene.h"
+
+USING_NS_CC;
+
+CCScene* HelloWorld::scene()
+{
+	// 'scene' is an autorelease object
+	CCScene *scene = CCScene::node();
+	
+	// 'layer' is an autorelease object
+	HelloWorld *layer = HelloWorld::node();
+
+	// add layer as a child to scene
+	scene->addChild(layer);
+
+	// return the scene
+	return scene;
+}
+
+// on "init" you need to initialize your instance
+bool HelloWorld::init()
+{
+	//////////////////////////////
+	// 1. super init first
+	if ( !CCLayer::init() )
+	{
+		return false;
+	}
+
+	/////////////////////////////
+	// 2. add a menu item with "X" image, which is clicked to quit the program
+	//    you may modify it.
+
+	// add a "close" icon to exit the progress. it's an autorelease object
+	CCMenuItemImage *pCloseItem = CCMenuItemImage::itemFromNormalImage(
+										"CloseNormal.png",
+										"CloseSelected.png",
+										this,
+										menu_selector(HelloWorld::menuCloseCallback) );
+	pCloseItem->setPosition( ccp(CCDirector::sharedDirector()->getWinSize().width - 20, 20) );
+
+	// create menu, it's an autorelease object
+	CCMenu* pMenu = CCMenu::menuWithItems(pCloseItem, NULL);
+	pMenu->setPosition( CCPointZero );
+	this->addChild(pMenu, 1);
+
+	/////////////////////////////
+	// 3. add your codes below...
+
+	// add a label shows "Hello World"
+	// create and initialize a label
+    CCLabelTTF* pLabel = CCLabelTTF::labelWithString("Hello World", "Arial", 24);
+	// ask director the window size
+	CCSize size = CCDirector::sharedDirector()->getWinSize();
+
+	// position the label on the center of the screen
+	pLabel->setPosition( ccp(size.width / 2, size.height - 50) );
+
+	// add the label as a child to this layer
+	this->addChild(pLabel, 1);
+
+	// add "HelloWorld" splash screen"
+	CCSprite* pSprite = CCSprite::spriteWithFile("HelloWorld.png");
+
+	// position the sprite on the center of the screen
+	pSprite->setPosition( ccp(size.width/2, size.height/2) );
+
+	// add the sprite as a child to this layer
+	this->addChild(pSprite, 0);
+	
+	return true;
+}
+
+void HelloWorld::menuCloseCallback(CCObject* pSender)
+{
+	CCDirector::sharedDirector()->end();
+
+#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
+	exit(0);
+#endif
+}

File Classes/HelloWorldScene.h

+#ifndef __HELLOWORLD_SCENE_H__
+#define __HELLOWORLD_SCENE_H__
+
+#include "cocos2d.h"
+
+class HelloWorld : public cocos2d::CCLayer
+{
+public:
+	// Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
+	virtual bool init();  
+
+	// there's no 'id' in cpp, so we recommand to return the exactly class pointer
+	static cocos2d::CCScene* scene();
+	
+	// a selector callback
+	virtual void menuCloseCallback(CCObject* pSender);
+
+	// implement the "static node()" method manually
+	LAYER_NODE_FUNC(HelloWorld);
+};
+
+#endif // __HELLOWORLD_SCENE_H__

File Resources/CloseNormal.png

Added
New image

File Resources/CloseSelected.png

Added
New image

File Resources/HelloWorld.png

Added
New image

File Resources/app.config.txt

+[Trace]
+GAME 				<0 or 1>	Game Channel
+
+[Assert]
+GAME 				<0 or 1>	Game Assert Channel

File Resources/fonts/Marker Felt.ttf

Binary file added.

File Resources/fonts/arial.ttf

Binary file added.

File android/AndroidManifest.xml

+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+      package="org.cocos2dx.application"
+      android:versionCode="1"
+      android:versionName="1.0">
+
+    <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="8"/>
+
+    <application android:label="@string/app_name"
+        android:debuggable="true"
+        android:icon="@drawable/icon">
+
+        <activity android:name=".ApplicationDemo"
+                  android:label="@string/app_name"
+                  android:screenOrientation="landscape"
+                  android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
+                  android:configChanges="orientation">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+    <supports-screens android:largeScreens="true"
+                      android:smallScreens="true"
+                      android:anyDensity="true"
+                      android:normalScreens="true"/>
+</manifest> 

File android/build.xml

+<?xml version="1.0" encoding="UTF-8"?>
+<project name="LuftKriegsElefant" default="help">
+
+    <!-- The local.properties file is created and updated by the 'android' tool.
+         It contains the path to the SDK. It should *NOT* be checked into
+         Version Control Systems. -->
+    <property file="local.properties" />
+
+    <!-- The ant.properties file can be created by you. It is only edited by the
+         'android' tool to add properties to it.
+         This is the place to change some Ant specific build properties.
+         Here are some properties you may want to change/update:
+
+         source.dir
+             The name of the source directory. Default is 'src'.
+         out.dir
+             The name of the output directory. Default is 'bin'.
+
+         For other overridable properties, look at the beginning of the rules
+         files in the SDK, at tools/ant/build.xml
+
+         Properties related to the SDK location or the project target should
+         be updated using the 'android' tool with the 'update' action.
+
+         This file is an integral part of the build system for your
+         application and should be checked into Version Control Systems.
+
+         -->
+    <property file="ant.properties" />
+
+    <!-- The project.properties file is created and updated by the 'android'
+         tool, as well as ADT.
+
+         This contains project specific properties such as project target, and library
+         dependencies. Lower level build properties are stored in ant.properties
+         (or in .classpath for Eclipse projects).
+
+         This file is an integral part of the build system for your
+         application and should be checked into Version Control Systems. -->
+    <loadproperties srcFile="project.properties" />
+
+    <!-- quick check on sdk.dir -->
+    <fail
+            message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through an env var"
+            unless="sdk.dir"
+    />
+
+
+<!-- extension targets. Uncomment the ones where you want to do custom work
+     in between standard targets -->
+<!--
+    <target name="-pre-build">
+    </target>
+    <target name="-pre-compile">
+    </target>
+
+    /* This is typically used for code obfuscation.
+       Compiled code location: ${out.classes.absolute.dir}
+       If this is not done in place, override ${out.dex.input.absolute.dir} */
+    <target name="-post-compile">
+    </target>
+-->
+
+	<target name="-pre-build">
+		<!-- copy resource files -->
+		<copy todir="assets/">
+			<fileset dir="../Resources/"/>
+		</copy>
+  
+		<!-- run native build -->
+		<exec 
+			executable="bash"
+			failonerror="true"
+		>
+			<arg line="${ndk.dir}/ndk-build" />
+		</exec>
+	</target>
+
+    <!-- Import the actual build file.
+
+         To customize existing targets, there are two options:
+         - Customize only one target:
+             - copy/paste the target into this file, *before* the
+               <import> task.
+             - customize it to your needs.
+         - Customize the whole content of build.xml
+             - copy/paste the content of the rules files (minus the top node)
+               into this file, replacing the <import> task.
+             - customize to your needs.
+
+         ***********************
+         ****** IMPORTANT ******
+         ***********************
+         In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
+         in order to avoid having your file be overridden by tools such as "android update project"
+    -->
+    <!-- version-tag: 1 -->
+    <import file="${sdk.dir}/tools/ant/build.xml" />
+
+</project>

File android/jni/Android.mk

+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+subdirs := $(addprefix $(LOCAL_PATH)/../../libraries/cocos2d-x/,$(addsuffix /Android.mk, \
+           cocos2dx \
+           CocosDenshion/android \
+	))
+subdirs += $(LOCAL_PATH)/../../Classes/Android.mk $(LOCAL_PATH)/helloworld/Android.mk
+
+include $(subdirs)

File android/jni/Application.mk

+APP_STL := gnustl_static
+APP_CPPFLAGS += -frtti
+
+APP_MODULES := cocos2dx_static cocosdenshion_shared game_logic_static helloworld_shared

File android/jni/helloworld/Android.mk

+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := helloworld_shared
+
+LOCAL_MODULE_FILENAME := libhelloworld
+
+LOCAL_SRC_FILES := main.cpp
+
+LOCAL_STATIC_LIBRARIES := png_static_prebuilt
+LOCAL_STATIC_LIBRARIES += xml2_static_prebuilt
+LOCAL_STATIC_LIBRARIES += jpeg_static_prebuilt
+LOCAL_WHOLE_STATIC_LIBRARIES := game_logic_static
+LOCAL_WHOLE_STATIC_LIBRARIES += cocos2dx_static
+                
+LOCAL_SHARED_LIBRARIES := cocosdenshion_shared
+            
+include $(BUILD_SHARED_LIBRARY)
+
+$(call import-module,cocos2dx/platform/third_party/android/modules/libpng)
+$(call import-module,cocos2dx/platform/third_party/android/modules/libxml2)
+$(call import-module,cocos2dx/platform/third_party/android/modules/libjpeg)

File android/jni/helloworld/main.cpp

+#include "AppDelegate.h"
+#include "cocos2d.h"
+#include "platform/android/jni/JniHelper.h"
+#include <jni.h>
+#include <android/log.h>
+
+#define  LOG_TAG    "main"
+#define  LOGD(...)  __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
+
+using namespace cocos2d;
+
+extern "C"
+{
+
+jint JNI_OnLoad(JavaVM *vm, void *reserved)
+{
+	JniHelper::setJavaVM(vm);
+
+	return JNI_VERSION_1_4;
+}
+
+void Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit(JNIEnv*  env, jobject thiz, jint w, jint h)
+{
+    if (!cocos2d::CCDirector::sharedDirector()->getOpenGLView())
+    {
+	cocos2d::CCEGLView *view = &cocos2d::CCEGLView::sharedOpenGLView();
+        view->setFrameWidthAndHeight(w, h);
+        // if you want to run in WVGA with HVGA resource, set it
+        // view->create(480, 320);  Please change it to (320, 480) if you're in portrait mode.
+        cocos2d::CCDirector::sharedDirector()->setOpenGLView(view);
+
+        AppDelegate *pAppDelegate = new AppDelegate();
+        cocos2d::CCApplication::sharedApplication().run();
+    }
+    else
+    {
+        cocos2d::CCTextureCache::reloadAllTextures();
+        cocos2d::CCDirector::sharedDirector()->setGLDefaultValues();
+    }
+}
+
+}

File android/proguard.cfg

+-optimizationpasses 5
+-dontusemixedcaseclassnames
+-dontskipnonpubliclibraryclasses
+-dontpreverify
+-verbose
+-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
+
+-keep public class * extends android.app.Activity
+-keep public class * extends android.app.Application
+-keep public class * extends android.app.Service
+-keep public class * extends android.content.BroadcastReceiver
+-keep public class * extends android.content.ContentProvider
+-keep public class * extends android.app.backup.BackupAgentHelper
+-keep public class * extends android.preference.Preference
+-keep public class com.android.vending.licensing.ILicensingService
+
+-keepclasseswithmembernames class * {
+    native <methods>;
+}
+
+-keepclasseswithmembers class * {
+    public <init>(android.content.Context, android.util.AttributeSet);
+}
+
+-keepclasseswithmembers class * {
+    public <init>(android.content.Context, android.util.AttributeSet, int);
+}
+
+-keepclassmembers class * extends android.app.Activity {
+   public void *(android.view.View);
+}
+
+-keepclassmembers enum * {
+    public static **[] values();
+    public static ** valueOf(java.lang.String);
+}
+
+-keep class * implements android.os.Parcelable {
+  public static final android.os.Parcelable$Creator *;
+}

File android/project.properties

+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-10

File android/res/drawable-hdpi/icon.png

Added
New image

File android/res/drawable-ldpi/icon.png

Added
New image

File android/res/drawable-mdpi/icon.png

Added
New image

File android/res/layout/helloworld_demo.xml

+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:orientation="vertical">
+
+    <org.cocos2dx.lib.Cocos2dxEditText 
+        android:id="@+id/textField"
+        android:layout_height="wrap_content"
+        android:layout_width="fill_parent"
+        android:background="@null"/>
+
+    <org.cocos2dx.lib.Cocos2dxGLSurfaceView
+        android:id="@+id/helloworld_gl_surfaceview"
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent"/>
+
+</FrameLayout>

File android/res/values/strings.xml

+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="app_name">helloworld</string>
+</resources>

File android/src/org/cocos2dx/application/ApplicationDemo.java

+/****************************************************************************
+Copyright (c) 2010-2012 cocos2d-x.org
+
+http://www.cocos2d-x.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+****************************************************************************/
+package org.cocos2dx.application;
+
+import org.cocos2dx.lib.Cocos2dxActivity;
+import org.cocos2dx.lib.Cocos2dxEditText;
+import org.cocos2dx.lib.Cocos2dxGLSurfaceView;
+
+import android.os.Bundle;
+
+public class ApplicationDemo extends Cocos2dxActivity{
+	private Cocos2dxGLSurfaceView mGLView;
+	
+	protected void onCreate(Bundle savedInstanceState){
+		super.onCreate(savedInstanceState);
+		
+		// get the packageName,it's used to set the resource path
+		String packageName = getApplication().getPackageName();
+		super.setPackageName(packageName);
+		
+		setContentView(R.layout.helloworld_demo);
+        mGLView = (Cocos2dxGLSurfaceView) findViewById(R.id.helloworld_gl_surfaceview);
+        mGLView.setTextField((Cocos2dxEditText)findViewById(R.id.textField));
+	}
+	
+	 @Override
+	 protected void onPause() {
+	     super.onPause();
+	     mGLView.onPause();
+	 }
+
+	 @Override
+	 protected void onResume() {
+	     super.onResume();
+	     mGLView.onResume();
+	 }
+	
+     static {
+    	 System.loadLibrary("cocosdenshion");
+         System.loadLibrary("helloworld");
+     }
+}

File android/src/org/cocos2dx/lib/Cocos2dxAccelerometer.java

+/****************************************************************************
+Copyright (c) 2010-2011 cocos2d-x.org
+
+http://www.cocos2d-x.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+****************************************************************************/
+package org.cocos2dx.lib;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.view.Display;
+import android.view.Surface;
+import android.view.WindowManager;
+
+/**
+ * 
+ * This class is used for controlling the Accelerometer
+ *
+ */
+public class Cocos2dxAccelerometer implements SensorEventListener {
+	
+	private static final String TAG = "Cocos2dxAccelerometer";
+	private Context mContext;
+	private SensorManager mSensorManager;
+	private Sensor mAccelerometer;
+	private int mNaturalOrientation;
+
+	public Cocos2dxAccelerometer(Context context){
+		mContext = context;
+
+		//Get an instance of the SensorManager
+	    mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
+	    mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
+	    
+	    Display display = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
+	    mNaturalOrientation = display.getOrientation();
+	}
+
+	public void enable() {
+		mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME);
+	}
+
+	public void disable () {
+		mSensorManager.unregisterListener(this);
+	}
+
+	@Override
+	public void onSensorChanged(SensorEvent event) {
+
+		if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER){
+            return;
+		}
+
+		float x = event.values[0];
+		float y = event.values[1];
+		float z = event.values[2];
+		
+		/*
+		 * Because the axes are not swapped when the device's screen orientation changes. 
+		 * So we should swap it here.
+		 * In tablets such as Motorola Xoom, the default orientation is landscape, so should
+		 * consider this.
+		 */
+		int orientation = mContext.getResources().getConfiguration().orientation;
+		if ((orientation == Configuration.ORIENTATION_LANDSCAPE) && (mNaturalOrientation != Surface.ROTATION_0)){
+			float tmp = x;
+			x = -y;
+			y = tmp;
+		}
+		else if ((orientation == Configuration.ORIENTATION_PORTRAIT) && (mNaturalOrientation != Surface.ROTATION_0))
+		{
+			 float tmp = x;
+	         x = y;
+	         y = -tmp;
+		}
+				
+        onSensorChanged(x, y, z, event.timestamp);
+        // Log.d(TAG, "x = " + event.values[0] + " y = " + event.values[1] + " z = " + event.values[2]);
+	}
+
+	@Override
+	public void onAccuracyChanged(Sensor sensor, int accuracy) {
+	}
+
+	private static native void onSensorChanged(float x, float y, float z, long timeStamp);
+}

File android/src/org/cocos2dx/lib/Cocos2dxActivity.java

+/****************************************************************************
+Copyright (c) 2010-2011 cocos2d-x.org
+
+http://www.cocos2d-x.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+****************************************************************************/
+
+package org.cocos2dx.lib;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.util.DisplayMetrics;
+import android.util.Log;
+
+public class Cocos2dxActivity extends Activity{
+    private static Cocos2dxMusic backgroundMusicPlayer;
+    private static Cocos2dxSound soundPlayer;
+    private static Cocos2dxAccelerometer accelerometer;
+    private static boolean accelerometerEnabled = false;
+    private static Handler handler;
+    private final static int HANDLER_SHOW_DIALOG = 1;
+    private static String packageName;
+
+    private static native void nativeSetPaths(String apkPath);
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        
+        // get frame size
+        DisplayMetrics dm = new DisplayMetrics();
+        getWindowManager().getDefaultDisplay().getMetrics(dm);
+        accelerometer = new Cocos2dxAccelerometer(this);
+
+        // init media player and sound player
+        backgroundMusicPlayer = new Cocos2dxMusic(this);
+        soundPlayer = new Cocos2dxSound(this);
+        
+        // init bitmap context
+        Cocos2dxBitmap.setContext(this);
+        
+        handler = new Handler(){
+        	public void handleMessage(Message msg){
+        		switch(msg.what){
+        		case HANDLER_SHOW_DIALOG:
+        			showDialog(((DialogMessage)msg.obj).title, ((DialogMessage)msg.obj).message);
+        			break;
+        		}
+        	}
+        };
+    }
+    
+    public static String getCurrentLanguage() {
+    	String languageName = java.util.Locale.getDefault().getLanguage();
+    	return languageName;
+    }
+    
+    public static void showMessageBox(String title, String message){
+    	Message msg = new Message();
+    	msg.what = HANDLER_SHOW_DIALOG;
+    	msg.obj = new DialogMessage(title, message);
+    	
+    	handler.sendMessage(msg);
+    } 
+
+    public static void enableAccelerometer() {
+        accelerometerEnabled = true;
+        accelerometer.enable();
+    }
+
+    public static void disableAccelerometer() {
+        accelerometerEnabled = false;
+        accelerometer.disable();
+    }
+
+    public static void preloadBackgroundMusic(String path){
+    	backgroundMusicPlayer.preloadBackgroundMusic(path);
+    }
+    
+    public static void playBackgroundMusic(String path, boolean isLoop){
+    	backgroundMusicPlayer.playBackgroundMusic(path, isLoop);
+    }
+    
+    public static void stopBackgroundMusic(){
+    	backgroundMusicPlayer.stopBackgroundMusic();
+    }
+    
+    public static void pauseBackgroundMusic(){
+    	backgroundMusicPlayer.pauseBackgroundMusic();
+    }
+    
+    public static void resumeBackgroundMusic(){
+    	backgroundMusicPlayer.resumeBackgroundMusic();
+    }
+    
+    public static void rewindBackgroundMusic(){
+    	backgroundMusicPlayer.rewindBackgroundMusic();
+    }
+    
+    public static boolean isBackgroundMusicPlaying(){
+    	return backgroundMusicPlayer.isBackgroundMusicPlaying();
+    }
+    
+    public static float getBackgroundMusicVolume(){
+    	return backgroundMusicPlayer.getBackgroundVolume();
+    }
+    
+    public static void setBackgroundMusicVolume(float volume){
+    	backgroundMusicPlayer.setBackgroundVolume(volume);
+    }
+    
+    public static int playEffect(String path, boolean isLoop){
+    	return soundPlayer.playEffect(path, isLoop);
+    }
+    
+    public static void stopEffect(int soundId){
+    	soundPlayer.stopEffect(soundId);
+    }
+    
+    public static void pauseEffect(int soundId){
+    	soundPlayer.pauseEffect(soundId);
+    }
+    
+    public static void resumeEffect(int soundId){
+    	soundPlayer.resumeEffect(soundId);
+    }
+    
+    public static float getEffectsVolume(){
+    	return soundPlayer.getEffectsVolume();
+    }
+    
+    public static void setEffectsVolume(float volume){
+    	soundPlayer.setEffectsVolume(volume);
+    }
+    
+    public static void preloadEffect(String path){
+    	soundPlayer.preloadEffect(path);
+    }
+    
+    public static void unloadEffect(String path){
+    	soundPlayer.unloadEffect(path);
+    }
+    
+    public static void stopAllEffects(){
+    	soundPlayer.stopAllEffects();
+    }
+    
+    public static void pauseAllEffects(){
+    	soundPlayer.pauseAllEffects();
+    }
+    
+    public static void resumeAllEffects(){
+    	soundPlayer.resumeAllEffects();
+    }
+    
+    public static void end(){
+    	backgroundMusicPlayer.end();
+    	soundPlayer.end();
+    }
+    
+    public static String getCocos2dxPackageName(){
+    	return packageName;
+    }
+    
+    public static void terminateProcess(){
+    	android.os.Process.killProcess(android.os.Process.myPid());
+    }
+
+    @Override
+    protected void onResume() {
+    	super.onResume();
+    	if (accelerometerEnabled) {
+    	    accelerometer.enable();
+    	}
+    }
+
+    @Override
+    protected void onPause() {
+    	super.onPause();
+    	if (accelerometerEnabled) {
+    	    accelerometer.disable();
+    	}
+    }
+
+    protected void setPackageName(String packageName) {
+    	Cocos2dxActivity.packageName = packageName;
+    	
+    	String apkFilePath = "";
+        ApplicationInfo appInfo = null;
+        PackageManager packMgmr = getApplication().getPackageManager();
+        try {
+            appInfo = packMgmr.getApplicationInfo(packageName, 0);
+        } catch (NameNotFoundException e) {
+            e.printStackTrace();
+            throw new RuntimeException("Unable to locate assets, aborting...");
+        }
+        apkFilePath = appInfo.sourceDir;
+        Log.w("apk path", apkFilePath);
+
+        // add this link at the renderer class
+        nativeSetPaths(apkFilePath);
+    }
+    
+    private void showDialog(String title, String message){
+    	Dialog dialog = new AlertDialog.Builder(this)
+	    .setTitle(title)
+	    .setMessage(message)
+	    .setPositiveButton("Ok",
+	    new DialogInterface.OnClickListener()
+	    {
+	    	public void onClick(DialogInterface dialog, int whichButton){
+	    		
+	    	}
+	    }).create();
+
+	    dialog.show();
+    }
+}
+
+class DialogMessage {
+	public String title;
+	public String message;
+	
+	public DialogMessage(String title, String message){
+		this.message = message;
+		this.title = title;
+	}
+}

File android/src/org/cocos2dx/lib/Cocos2dxBitmap.java

+/****************************************************************************
+Copyright (c) 2010-2011 cocos2d-x.org
+
+http://www.cocos2d-x.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+****************************************************************************/
+package org.cocos2dx.lib;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.LinkedList;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Typeface;
+import android.graphics.Paint.Align;
+import android.graphics.Paint.FontMetricsInt;
+import android.util.Log;
+
+public class Cocos2dxBitmap{
+	/*
+	 * The values are the same as cocos2dx/platform/CCImage.h.
+	 * I think three alignments are OK.
+	 */
+	private static final int ALIGNCENTER = 0x33;
+	private static final int ALIGNLEFT	 = 0x31;
+	private static final int ALIGNRIGHT	 = 0x32;
+	
+	private static Context context;
+	
+	public static void setContext(Context context){
+		Cocos2dxBitmap.context = context;
+	}
+	
+	/*
+	 * @width: the width to draw, it can be 0
+	 * @height: the height to draw, it can be 0
+	 */
+    public static void createTextBitmap(String content, String fontName, 
+    		int fontSize, int alignment, int width, int height){
+    	
+    	content = refactorString(content);   	
+    	Paint paint = newPaint(fontName, fontSize, alignment);
+    	
+    	TextProperty textProperty = computeTextProperty(content, paint, width, height);      	
+
+        int bitmapTotalHeight = (height == 0 ? textProperty.totalHeight:height);
+
+        // Draw text to bitmap
+        Bitmap bitmap = Bitmap.createBitmap(textProperty.maxWidth, 
+        		bitmapTotalHeight, Bitmap.Config.ARGB_8888);
+        Canvas canvas = new Canvas(bitmap);
+        
+        // Draw string
+        FontMetricsInt fm = paint.getFontMetricsInt();
+        int x = 0;
+        int y = height == 0 ?(-fm.top):
+			(-fm.top + (height - textProperty.totalHeight)/2);
+        String[] lines = textProperty.lines;
+        for (String line : lines){
+        	x = computeX(paint, line, textProperty.maxWidth, alignment);
+        	canvas.drawText(line, x, y, paint);
+        	y += textProperty.heightPerLine;
+        }
+        
+        initNativeObject(bitmap);
+    }
+    
+    private static int computeX(Paint paint, String content, int w, int alignment){
+    	int ret = 0;
+    	
+    	switch (alignment){
+    	case ALIGNCENTER:
+    		ret = w / 2;
+    		break;
+    	
+        // ret = 0
+    	case ALIGNLEFT:   		
+    		break;
+    		
+    	case ALIGNRIGHT:
+    		ret = w;
+    		break;
+    	
+    	/*
+    	 * Default is align left.
+    	 * Should be same as newPaint().
+    	 */
+    	default:
+    		break;
+    	}
+    	
+    	return ret;
+    }
+    
+    private static class TextProperty{
+    	// The max width of lines
+    	int maxWidth;
+    	// The height of all lines
+    	int totalHeight;
+    	int heightPerLine;
+    	String[] lines;
+
+    	TextProperty(int w, int h, String[] lines){
+    		this.maxWidth = w;
+    		this.heightPerLine = h;
+    		this.totalHeight = h * lines.length;   		
+    		this.lines = lines;
+    	}
+    }
+    
+    private static TextProperty computeTextProperty(String content, Paint paint,
+    		int maxWidth, int maxHeight){              
+        FontMetricsInt fm = paint.getFontMetricsInt();
+        int h = (int)Math.ceil(fm.bottom - fm.top);
+        int maxContentWidth = 0;
+        
+        String[] lines = splitString(content, maxHeight, maxWidth, paint);
+        
+        if (maxWidth != 0){
+        	maxContentWidth = maxWidth;
+        }
+        else {
+        	/*
+             * Compute the max width
+             */
+            int temp = 0;
+            for (String line : lines){
+            	temp = (int)Math.ceil(paint.measureText(line, 0, line.length()));
+            	if (temp > maxContentWidth){
+            		maxContentWidth = temp;
+            	}
+            }
+        }        
+        
+        return new TextProperty(maxContentWidth, h, lines);
+    }
+    
+    /*
+     * If maxWidth or maxHeight is not 0,
+     * split the string to fix the maxWidth and maxHeight.
+     */
+    private static String[] splitString(String content, int maxHeight, int maxWidth, 
+    		Paint paint){
+    	String[] lines = content.split("\\n");
+    	String[] ret = null;
+    	FontMetricsInt fm = paint.getFontMetricsInt();
+        int heightPerLine = (int)Math.ceil(fm.bottom - fm.top);
+        int maxLines = maxHeight / heightPerLine;
+    	
+    	if (maxWidth != 0){
+    		LinkedList<String> strList = new LinkedList<String>();
+    		for (String line : lines){
+    			/*
+    			 * The width of line is exceed maxWidth, should divide it into
+    			 * two or more lines.
+    			 */
+    			int lineWidth = (int)Math.ceil(paint.measureText(line));
+    			if (lineWidth > maxWidth){    				
+    				strList.addAll(divideStringWithMaxWidth(paint, line, maxWidth));
+    			}
+    			else{
+    				strList.add(line);
+    			}
+    			
+    			/*
+    			 * Should not exceed the max height;
+    			 */
+    			if (maxLines > 0 && strList.size() >= maxLines){
+    				break;
+    			}
+    		}
+    		
+    		/*
+    		 * Remove exceeding lines
+    		 */
+    		if (maxLines > 0 && strList.size() > maxLines){
+    			while (strList.size() > maxLines){
+    				strList.removeLast();
+    			}
+    		}
+    		
+    		ret = new String[strList.size()];
+    		strList.toArray(ret);
+    	} else 
+    	if (maxHeight != 0 && lines.length > maxLines) {
+    		/*
+    		 * Remove exceeding lines
+    		 */
+    		LinkedList<String> strList = new LinkedList<String>();
+    		for (int i = 0; i < maxLines; i++){
+    			strList.add(lines[i]);
+    		}
+    		ret = new String[strList.size()];
+    		strList.toArray(ret);
+    	}
+    	else {
+    		ret = lines;
+    	}
+    	
+    	return ret;
+    }
+    
+    private static LinkedList<String> divideStringWithMaxWidth(Paint paint, String content, 
+    		int width){
+    	int charLength = content.length();
+    	int start = 0;
+    	int tempWidth = 0;
+    	LinkedList<String> strList = new LinkedList<String>();
+    	
+    	/*
+    	 * Break a String into String[] by the width & should wrap the word
+    	 */
+    	for (int i = 1; i <= charLength; ++i){  		
+    		tempWidth = (int)Math.ceil(paint.measureText(content, start, i));
+    		if (tempWidth >= width){
+    			int lastIndexOfSpace = content.substring(0, i).lastIndexOf(" ");
+    			
+    			if (lastIndexOfSpace != -1 && lastIndexOfSpace > start){
+    				/**
+    				 * Should wrap the word
+    				 */
+    				strList.add(content.substring(start, lastIndexOfSpace));
+    				i = lastIndexOfSpace;
+    			}
+    			else {
+    				/*
+        			 * Should not exceed the width
+        			 */
+        			if (tempWidth > width){
+        				strList.add(content.substring(start, i - 1));
+        				/*
+        				 * compute from previous char
+        				 */
+        				--i;
+        			}
+        			else {
+        				strList.add(content.substring(start, i));   				
+        			}
+    			}
+    			   			
+    			start = i;
+    		}
+    	}
+    	
+    	/*
+    	 * Add the last chars
+    	 */
+    	if (start < charLength){
+    		strList.add(content.substring(start));
+    	}
+    	
+    	return strList;
+    }
+    
+    private static Paint newPaint(String fontName, int fontSize, int alignment){
+    	Paint paint = new Paint();
+    	paint.setColor(Color.WHITE);
+        paint.setTextSize(fontSize);      
+        paint.setAntiAlias(true);    
+        
+        /*
+         * Set type face for paint, now it support .ttf file.
+         */
+        if (fontName.endsWith(".ttf")){
+        	 try {
+        		//Typeface typeFace = Typeface.createFromAsset(context.getAssets(), fontName);
+        		 Typeface typeFace = Cocos2dxTypefaces.get(context, fontName);
+              	paint.setTypeface(typeFace);
+             } catch (Exception e){
+             	Log.e("Cocos2dxBitmap", 
+             		"error to create ttf type face: " + fontName);
+             	
+             	/*
+             	 * The file may not find, use system font
+             	 */
+             	paint.setTypeface(Typeface.create(fontName, Typeface.NORMAL));
+             }
+        }
+        else {
+        	paint.setTypeface(Typeface.create(fontName, Typeface.NORMAL));
+        }
+        
+        switch (alignment){
+    	case ALIGNCENTER:
+    		paint.setTextAlign(Align.CENTER);
+    		break;
+    	
+    	case ALIGNLEFT:  
+    		paint.setTextAlign(Align.LEFT);
+    		break;
+    		
+    	case ALIGNRIGHT:
+    		paint.setTextAlign(Align.RIGHT);
+    		break;
+    	
+    	default:
+    		paint.setTextAlign(Align.LEFT);
+    		break;
+    	}
+        
+        return paint;
+    }
+    
+    private static String refactorString(String str){
+    	// Avoid error when content is ""
+		if (str.compareTo("") == 0){
+			return " ";
+		}
+		
+		/*
+		 * If the font of "\n" is "" or "\n", insert " " in front of it.
+		 * 
+		 * For example:
+		 * "\nabc"     -> " \nabc"
+		 * "\nabc\n\n" -> " \nabc\n \n"
+		 */
+		StringBuilder strBuilder = new StringBuilder(str);
+		int start = 0;
+		int index = strBuilder.indexOf("\n");
+		while (index != -1){
+			if (index == 0 || strBuilder.charAt(index -1) == '\n'){
+				strBuilder.insert(start, " ");
+				start = index + 2;
+			} else {
+				start = index + 1;
+			}
+			
+			if (start > strBuilder.length() || index == strBuilder.length()){
+				break;
+			}
+			
+			index = strBuilder.indexOf("\n", start);			
+		}
+		
+		return strBuilder.toString();
+	}
+    
+    private static void initNativeObject(Bitmap bitmap){
+    	byte[] pixels = getPixels(bitmap);
+    	if (pixels == null){
+    		return;
+    	}
+    	
+    	nativeInitBitmapDC(bitmap.getWidth(), bitmap.getHeight(), pixels);
+    }
+    
+    private static byte[] getPixels(Bitmap bitmap){
+    	if (bitmap != null){
+    		byte[] pixels = new byte[bitmap.getWidth() * bitmap.getHeight() * 4];
+    		ByteBuffer buf = ByteBuffer.wrap(pixels);
+    		buf.order(ByteOrder.nativeOrder());
+    		bitmap.copyPixelsToBuffer(buf);
+    		return pixels;
+    	}
+    	
+    	return null;
+    }
+    
+    private static native void nativeInitBitmapDC(int width, int height, byte[] pixels);
+}

File android/src/org/cocos2dx/lib/Cocos2dxEditText.java

+/****************************************************************************
+Copyright (c) 2012 cocos2d-x.org
+
+http://www.cocos2d-x.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+****************************************************************************/
+
+package org.cocos2dx.lib;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.KeyEvent;
+import android.widget.EditText;
+
+public class Cocos2dxEditText extends EditText {
+	
+	private Cocos2dxGLSurfaceView mView;
+
+	public Cocos2dxEditText(Context context) {
+		super(context);
+		// TODO Auto-generated constructor stub
+	}
+	
+	public Cocos2dxEditText(Context context, AttributeSet attrs) {
+		super(context, attrs);
+	}
+	
+	public Cocos2dxEditText(Context context, AttributeSet attrs, int defStyle) {
+		super(context, attrs, defStyle);
+	}
+	
+	public void setMainView(Cocos2dxGLSurfaceView glSurfaceView) {
+		mView = glSurfaceView;
+	}
+	
+	/*
+	 * Let GlSurfaceView get focus if back key is input
+	 */
+	public boolean onKeyDown(int keyCode, KeyEvent event) {
+		super.onKeyDown(keyCode, event);
+		
+		if (keyCode == KeyEvent.KEYCODE_BACK) {
+			mView.requestFocus();
+		}
+		
+		return true;
+	}
+}

File android/src/org/cocos2dx/lib/Cocos2dxGLSurfaceView.java

+/****************************************************************************
+Copyright (c) 2010-2011 cocos2d-x.org
+
+http://www.cocos2d-x.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+****************************************************************************/
+package org.cocos2dx.lib;
+
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.os.Handler;
+import android.os.Message;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.TextView;
+import android.widget.TextView.OnEditorActionListener;
+
+class TextInputWraper implements TextWatcher, OnEditorActionListener {
+	
+	private static final Boolean debug = false;
+	private void LogD(String msg) {
+		if (debug) Log.d("TextInputFilter", msg);
+	}
+	
+	private Cocos2dxGLSurfaceView mMainView;
+	private String mText;
+	private String mOriginText;
+	
+	private Boolean isFullScreenEdit() {
+		InputMethodManager imm = (InputMethodManager)mMainView.getTextField().getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+		return imm.isFullscreenMode();
+	}
+
+	public TextInputWraper(Cocos2dxGLSurfaceView view) {
+		mMainView = view;
+	}
+	
+	public void setOriginText(String text) {
+		mOriginText = text;
+	}
+	
+	@Override
+	public void afterTextChanged(Editable s) {
+		if (isFullScreenEdit()) {
+			return;
+		}
+		
+		LogD("afterTextChanged: " + s);
+		int nModified = s.length() - mText.length();
+		if (nModified > 0) {
+			final String insertText = s.subSequence(mText.length(), s.length()).toString();
+			mMainView.insertText(insertText);
+			LogD("insertText(" + insertText + ")");
+		}
+		else {
+			for (; nModified < 0; ++nModified) {
+				mMainView.deleteBackward();
+				LogD("deleteBackward");
+			}
+		}
+		mText = s.toString();
+	}
+
+	@Override
+	public void beforeTextChanged(CharSequence s, int start, int count,
+			int after) {
+		LogD("beforeTextChanged(" + s + ")start: " + start + ",count: " + count + ",after: " + after);
+		mText = s.toString();
+	}
+
+	@Override
+	public void onTextChanged(CharSequence s, int start, int before, int count) {
+	}
+
+	@Override
+	public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+		if (mMainView.getTextField() == v && isFullScreenEdit()) {
+			// user press the action button, delete all old text and insert new text
+			for (int i = mOriginText.length(); i > 0; --i) {
+				mMainView.deleteBackward();
+				LogD("deleteBackward");
+			}
+			String text = v.getText().toString();
+			
+			/*
+			 * If user input nothing, translate "\n" to engine.
+			 */
+			if (text.compareTo("") == 0){
+				text = "\n";
+			}
+			
+			if ('\n' != text.charAt(text.length() - 1)) {
+				text += '\n';
+			}
+			
+			final String insertText = text;
+			mMainView.insertText(insertText);
+			LogD("insertText(" + insertText + ")");
+		}
+		return false;
+	}
+}
+
+public class Cocos2dxGLSurfaceView extends GLSurfaceView {
+    
+    static private Cocos2dxGLSurfaceView mainView;
+
+    private static final String TAG = Cocos2dxGLSurfaceView.class.getCanonicalName();
+    private Cocos2dxRenderer mRenderer;
+    
+    private static final boolean debug = false;
+	
+    ///////////////////////////////////////////////////////////////////////////
+    // for initialize
+	///////////////////////////////////////////////////////////////////////////
+    public Cocos2dxGLSurfaceView(Context context) {
+        super(context);
+        initView();
+    }
+
+    public Cocos2dxGLSurfaceView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        initView();
+    }
+
+    protected void initView() {
+        mRenderer = new Cocos2dxRenderer();       
+        setFocusableInTouchMode(true);
+        setRenderer(mRenderer);
+        
+        textInputWraper = new TextInputWraper(this);
+
+        handler = new Handler(){
+        	public void handleMessage(Message msg){
+        		switch(msg.what){
+        		case HANDLER_OPEN_IME_KEYBOARD:
+        			if (null != mTextField && mTextField.requestFocus()) {
+        				mTextField.removeTextChangedListener(textInputWraper);
+        				mTextField.setText("");
+        				String text = (String)msg.obj;
+        				mTextField.append(text);
+        				textInputWraper.setOriginText(text);
+        				mTextField.addTextChangedListener(textInputWraper);
+                        InputMethodManager imm = (InputMethodManager)mainView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+                        imm.showSoftInput(mTextField, 0);
+                        Log.d("GLSurfaceView", "showSoftInput");
+        			}
+        			break;
+        			
+        		case HANDLER_CLOSE_IME_KEYBOARD:
+        			if (null != mTextField) {
+        				mTextField.removeTextChangedListener(textInputWraper);
+                        InputMethodManager imm = (InputMethodManager)mainView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+                        imm.hideSoftInputFromWindow(mTextField.getWindowToken(), 0);
+                        Log.d("GLSurfaceView", "HideSoftInput");
+        			}
+        			break;
+        		}
+        	}
+        };
+
+        mainView = this;
+    }
+    
+    public void onPause(){
+    	queueEvent(new Runnable() {
+            @Override
+            public void run() {
+                mRenderer.handleOnPause();
+            }
+        });
+    	
+    	super.onPause();
+    }
+    
+    public void onResume(){
+    	super.onResume();
+    	
+    	queueEvent(new Runnable() {
+            @Override
+            public void run() {
+                mRenderer.handleOnResume();
+            }
+        });
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+    // for text input
+	///////////////////////////////////////////////////////////////////////////
+    private final static int HANDLER_OPEN_IME_KEYBOARD = 2;
+    private final static int HANDLER_CLOSE_IME_KEYBOARD = 3;
+    private static Handler handler;
+    private static TextInputWraper textInputWraper;
+    private Cocos2dxEditText mTextField;
+    
+    public TextView getTextField() {
+    	return mTextField;
+    }
+    
+    public void setTextField(Cocos2dxEditText view) {
+    	mTextField = view;
+    	if (null != mTextField && null != textInputWraper) {
+    		mTextField.setOnEditorActionListener(textInputWraper);
+    		mTextField.setMainView(this);
+    		this.requestFocus();
+    	}
+    }
+    
+    public static void openIMEKeyboard() {
+    	Message msg = new Message();
+    	msg.what = HANDLER_OPEN_IME_KEYBOARD;
+    	msg.obj = mainView.getContentText();
+    	handler.sendMessage(msg);
+    	
+    }
+    
+    private String getContentText() {
+		return mRenderer.getContentText();
+	}
+
+	public static void closeIMEKeyboard() {
+    	Message msg = new Message();
+    	msg.what = HANDLER_CLOSE_IME_KEYBOARD;
+    	handler.sendMessage(msg);
+    }
+    
+    public void insertText(final String text) {
+        queueEvent(new Runnable() {
+            @Override
+            public void run() {
+                mRenderer.handleInsertText(text);
+            }
+        });
+    }
+    
+    public void deleteBackward() {
+        queueEvent(new Runnable() {
+            @Override
+            public void run() {
+                mRenderer.handleDeleteBackward();
+            }
+        });
+    }
+
+	///////////////////////////////////////////////////////////////////////////
+    // for touch event
+    ///////////////////////////////////////////////////////////////////////////
+
+    public boolean onTouchEvent(final MotionEvent event) {
+    	// these data are used in ACTION_MOVE and ACTION_CANCEL
+    	final int pointerNumber = event.getPointerCount();
+    	final int[] ids = new int[pointerNumber];
+    	final float[] xs = new float[pointerNumber];
+    	final float[] ys = new float[pointerNumber];
+
+    	for (int i = 0; i < pointerNumber; i++) {
+            ids[i] = event.getPointerId(i);
+            xs[i] = event.getX(i);
+            ys[i] = event.getY(i);
+        }
+        
+        switch (event.getAction() & MotionEvent.ACTION_MASK) {
+        case MotionEvent.ACTION_POINTER_DOWN:
+        	final int indexPointerDown = event.getAction() >> MotionEvent.ACTION_POINTER_ID_SHIFT;
+        	final int idPointerDown = event.getPointerId(indexPointerDown);
+            final float xPointerDown = event.getX(indexPointerDown);
+            final float yPointerDown = event.getY(indexPointerDown);
+
+            queueEvent(new Runnable() {
+                @Override
+                public void run() {
+                    mRenderer.handleActionDown(idPointerDown, xPointerDown, yPointerDown);
+                }
+            });
+            break;
+            
+        case MotionEvent.ACTION_DOWN:
+        	// there are only one finger on the screen
+        	final int idDown = event.getPointerId(0);
+            final float xDown = xs[0];
+            final float yDown = ys[0];
+            
+            queueEvent(new Runnable() {
+                @Override
+                public void run() {
+                    mRenderer.handleActionDown(idDown, xDown, yDown);
+                }
+            });
+            break;