Hi !
As I wanted to play with Android NDK, JNI, Android.mk files, etc…, this week was the worst of my developer life…thanks Cocos2d-X
1. INTRODUCTION
What i want is to run the “Box2D hello world project” on my Android phone (or emulator). I managed to run the “tests examples” http://www.cocos2d-x.org/projects/cocos2d-x/wiki/How_to_run_test_cases_on_android-ndk (with a lot of difficulties! please update this article declared as “deprecated”) but impossible to find a solution to run the very simple “Box2D hello world project”.
I started by creating the “Box2D hello world project” in XCode thanks to the Box2D cocos2D-X template. I just did “New project” => “Cocos2d-X Box2D project” => “create” and ok no problem I can run it on my iPhone from Xcode.
Then, I created an empty Android project thanks to “create-android-project.sh” and transfered all the required files and directories to my project created with XCode. The method I followed is very close to what is described in this article http://gameit.ro/2012/01/creating-an-iphone-and-android-cocos2d-x-hybrid-project-updated/#comment-649 Neverthless, I did a little bit differently for the android.mk files, etc… to be closer to the “test cases” examples which work on my phone.
2. MY PROBLEM
Here is my problem:
- my cocos2D/Box2D project perfectly compiles when running ./build_native.sh…
- and loads the Box2D, cocos2D, cocosdenshion libraries…
- …but doesn’t load the “game_logic” and “helloworldgame” libraries.
I can’t figure out what is wrong in my Android.mk, Application.mk files (or another problem elsewhere?).
So here are the details about my project:
I use NDK r7 and cocos2d-1.0.1-x-0.11.0. I run Mac OSX Lion.
**Structure of my folders: *
<pre>
- cocos2d-1.0.1-x-0.11.0
*+ Box2D
*+ cocos2dx
*+ CocosDenshion
*+ agjs
**+ agjs
***+ android
****+ assets
****+ bin
****+ gen
****+ jni
*****+ helloworld
****+ libs
****+ obj
****+ res
****+ src
**** classes
***+ ios
***+ libs )
++ Resources
</pre>
**Here are the contents of my files:*
Android.mk in /agjs/agjs:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE :=* game_logic*
LOCAL_SRC_FILES := \
classes/AppDelegate.cpp \
classes/HelloWorldScene.cpp \
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../cocos2dx \
$(LOCAL_PATH)/../../cocos2dx/include \
$(LOCAL_PATH)/../../cocos2dx/platform \
$(LOCAL_PATH)/../../cocos2dx/platform/third_party/android/ \
$(LOCAL_PATH)/../../CocosDenshion/include \
$(LOCAL_PATH)/../.. \
$(LOCAL_PATH)/..
LOCAL_LDLIBS := -L$(call host-path, $(LOCAL_PATH)/android/libs/$(TARGET_ARCH_ABI)) \
-lGLESv1_CM \
-lcocos2d -llog -lcocosdenshion \
-lbox2d \
-L$(call host-path, $(LOCAL_PATH)/../../cocos2dx/platform/third_party/android/libraries/$(TARGET_ARCH_ABI)) -lcurl
include $(BUILD_SHARED_LIBRARY)
Android.mk in /jni:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
subdirs := $(addprefix $(LOCAL_PATH)/../../../../,$(addsuffix /Android.mk, \
Box2D \
cocos2dx \
CocosDenshion/android \
))
subdirs += $(LOCAL_PATH)/../../Android.mk \
$(LOCAL_PATH)/helloworld/Android.mk
include $(subdirs)
Android.mk in /helloworld:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := *helloworldgame*
LOCAL_SRC_FILES := main.cpp \
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../../../../cocos2dx \
$(LOCAL_PATH)/../../../../../cocos2dx/platform \
$(LOCAL_PATH)/../../../../../cocos2dx/include \
$(LOCAL_PATH)/../../../.. \
$(LOCAL_PATH)/../../../ \
$(LOCAL_PATH)/../../../Classes \
LOCAL_LDLIBS := -L$(call host-path, $(LOCAL_PATH)/../../libs/$(TARGET_ARCH_ABI)) \
-lGLESv1_CM \
-lcocos2d -llog -lgame_logic
include $(BUILD_SHARED_LIBRARY)
Application.mk in /jni:
APP_STL := stlport_static
APP_ABI := armeabi
APP_MODULES := cocos2d cocosdenshion box2d game_logic helloworldgame
build_native.sh in /android:
NDK_ROOT=/Applications/Android/android-ndk-r7
COCOS2DX_ROOT=../../../cocos2dx
GAME_ROOT=../
GAME_ANDROID_ROOT=$GAME_ROOT/android
RESOURCE_ROOT=$GAME_ROOT/Resources
# some more code after that...
In agjs.java:
static {
try {
System.loadLibrary("cocos2d"); // OK here => no exception
} catch (UnsatisfiedLinkError use) {
Log.e("MyApp", "WARNING: Could not load cocos2d.so");
}
try {
System.loadLibrary("cocosdenshion"); // OK here => no exception
} catch (UnsatisfiedLinkError use) {
Log.e("MyApp", "WARNING: Could not load cocosdenshion");
}
try {
System.loadLibrary("game_logic"); // NOT OK here => exception !!!
} catch (UnsatisfiedLinkError use) {
Log.e("MyApp", "WARNING: Could not load game_logic");
}
try {
System.loadLibrary("helloworldgame"); // NOT OK here => exception !!!
} catch (UnsatisfiedLinkError use) {
Log.e("MyApp", "WARNING: Could not load game");
}
try {
System.loadLibrary("box2d"); // OK here => no exception
} catch (UnsatisfiedLinkError use) {
Log.e("MyApp", "WARNING: Could not load box2d");
}
}
Nota: I didn’t forget to change “LOCAL_CFLAGS := ~~DUSE_FILE32API" to "LOCAL_CFLAGS :=~~DUSE_FILE32API -DGL_GLEXT_PROTOTYPES=1” in the Android.mk of cocos2d-1.0.1-x-0.11.0/cocos2dx as I use ndk r7.
Here is the error message in the console:
02-10 00:01:20.372: E/MyApp(22177): WARNING: Could not load game_logic // NOTA: due to the System.loadLibrary("game_logic") written in my code
02-10 00:01:20.372: E/MyApp(22177): WARNING: Could not load game // NOTA: due to the System.loadLibrary("game") written in my code
02-10 00:01:20.472: W/dalvikvm(19568): No implementation found for native Lorg/cocos2dx/lib/Cocos2dxRenderer;.nativeInit (II)V
02-10 00:01:20.472: E/AndroidRuntime(22177): FATAL EXCEPTION: GLThread 12
02-10 00:01:20.472: E/AndroidRuntime(22177): java.lang.UnsatisfiedLinkError: nativeInit
02-10 00:01:20.472: E/AndroidRuntime(22177): at org.cocos2dx.lib.Cocos2dxRenderer.nativeInit(Native Method)
02-10 00:01:20.472: E/AndroidRuntime(22177): at org.cocos2dx.lib.Cocos2dxRenderer.onSurfaceCreated(Cocos2dxRenderer.java:40)
02-10 00:01:20.472: E/AndroidRuntime(22177): at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1373)
02-10 00:01:20.472: E/AndroidRuntime(22177): at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1138)
Anybody can tell me how to solve my problem of library loading ?
Thanks !