Crash in Android Native while changing to new Acti

2019-02-27 15:57发布

问题:

My application is unable to open OpenFeint dashboard methods. The implementation of the native c++ libraries uses cocos2d-x as a graphic library, but it has a handler and a wrapper to allow the use of OpenFeint functions. OpenFeint initialization and non-activity methods work correctly.

When UI dashboard functions such as openLaderBoards or openAchievements are called either from a Jni call or in the Java onCreate initialization, the application crashes.

EDIT: I have tested and it happens to any Activity change I try, even my own new classes.

EDIT2: I have a +100 bounty in a similar question, anyone who comes up with the answer gets it.

Code

Activity:

public class App extends Cocos2dxActivity{
private Cocos2dxGLSurfaceView mGLView;

OpenFeintX m_kOpenFeintX;

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);

    InternetConnection.setM_kActivity(this);

    m_kOpenFeintX = new OpenFeintX( this);      

    setContentView(R.layout.applayout);
    mGLView = (Cocos2dxGLSurfaceView) findViewById(R.id.game_gl_surfaceview);
    mGLView.setTextField((EditText)findViewById(R.id.textField));                  

// Testspace for new Activities, OpenFeint or self-made
//
// Intent myIntent = new Intent(this, TestActivity.class);
// startActivityForResult(myIntent, 0);
// Dashboard.open();


// Cocos2d-x scene opens after this

}

 static {
     System.loadLibrary("TestProject");
     // Native library loaded for cocos2d-x
 }

Wrapper:

public class OpenFeintX {

private static OpenFeintXHandler ms_kOpenFeintHandler;

public OpenFeintX(Activity kActivity) {
    initializeOpenFeint("TestApp", "derp",
            "hurr", "6546516516541",
            kActivity, ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

    ms_kOpenFeintHandler = new OpenFeintXHandler();

}

public static void openLeaderBoards() {     
    Message msg = new Message();
    msg.what = OpenFeintXHandler.SHOW_LEADERBOARDS;
    ms_kOpenFeintHandler.sendMessage(msg);
}

Handler openDashboard function:

private void openLeaderBoards() {
    System.out.println("Opening Dashboard");
    Dashboard.openLeaderboards();
}

Manifest:

<application
    android:debuggable="true"
    android:label="@string/app_name">
    <activity
        android:configChanges="orientation"
        android:label="@string/app_name"
        android:name=".App"
        android:screenOrientation="portrait"
        android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
        <intent-filter >
            <action android:name="android.intent.action.MAIN" />

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

    <activity android:name="com.openfeint.internal.ui.IntroFlow"
              android:label=".IntroFlow"
              android:configChanges="orientation|keyboardHidden"
              android:theme="@style/OFNestedWindow" />
    <activity android:name="com.openfeint.api.ui.Dashboard"
              android:label=".Dashboard"
              android:configChanges="orientation|keyboardHidden"
              android:theme="@style/OFNestedWindow"/>
    <activity android:name="com.openfeint.internal.ui.Settings"
              android:label=".Settings"
              android:configChanges="orientation|keyboardHidden"
              android:theme="@style/OFNestedWindow"/>
    <activity android:name="com.openfeint.internal.ui.NativeBrowser"
              android:label=".NativeBrowser"
              android:configChanges="orientation|keyboardHidden"
              android:theme="@style/OFNestedWindow"/>
</application>

Stacktrace (won't indent in SO):

http://pastebin.com/jsmSbgw4

回答1:

The answer was easy but complex. When the app changes to a new activity, the nativeOnPause method from cocos2d-x MessageJNI is called. This method is supposed to call a CCApplication::sharedApplication(), but one of my classes had previously called the CCApplication destructor, which cleared the shared singleton to null.

Even though the answer is easy to fix and project specific, I am going to give some advice on what made me find it. Keep in mind that all my tools are windows and cygwin.

First, make Eclipse do the ndk-builds for you on clean.

Rightclick your Project-> Properties -> C/C++ Build. Builder Settings tab, Command

  C:\NVPACK\cygwin\bin\bash.exe -c "cd /cygdrive/path/to/project && ./build_script.sh"

Second, setup your debugger.

Using this tutorial. It may take some time and attempts to get there but it is worth it. My adb-server call script is

export ANDROID_NDK_ROOT=/cygdrive/c/NVPACK/android-ndk-r6b/
cd $ANDROID_NDK_ROOT
./ndk-gdb-eclipse --adb=/cygdrive/c/NVPACK/android-sdk-windows/platform-tools/adb     --project=/cygdrive/c/project/path --force --verbose

Third, set your logcat in verbose.

UPDATE: This last step can now be skipped as latest versions of Logcat output the class and line for the whole stacktrace.

You will get long stacktraces like the one in my question. To check where the stacktrace errors point follow this other tutorial. My script to access the library is

C:\NVPACK\android-ndk-r6b\toolchains\x86-4.4.3\prebuilt\windows\bin\i686-android-linux-addr2line.exe -C -f -e c:\path\to\project\libMyLib.so