4

ndk と cocos2dx を使用して、iPhone アプリを Android に移植しました。これは魔法のように機能し、cocos2dx はとてもクールだと思います!

ここで、Java 環境のメインの opengl ビューにいくつかの Java ビューを追加したいと思います。そして、これは私にとってはうまくいきません。Java 環境でのビュー、アクティビティ、インテントなどの機能に関する基本的な知識が必要だと思います。

具体的にはTextView、実行時にopenglビューに(Java)を追加する必要があります。次のことを試しましたが、関数 void を呼び出すとクラッシュしますtestSetText()

public class myTest extends Cocos2dxActivity{
    private static final String TAG = "MY_TEST";

    private FrameLayout mainFrame; 
    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);

        Log.e(TAG, "onCreate");

        String packageName = getApplication().getPackageName();
        super.setPackageName(packageName);

        mainFrame = new FrameLayout(this);

        mGLView = new Cocos2dxGLSurfaceView(this);

        mainFrame.addView(mGLView);

        RelativeLayout base = new RelativeLayout(this);
        base.addView(mainFrame);
        setContentView(base);

    }

    private GLSurfaceView mGLView;

    static {
        System.loadLibrary("cocos2d");
        System.loadLibrary("cocosdenshion");
        System.loadLibrary("game");
    }

     @Override
     protected void onPause() {         
         super.onPause();
         Log.i("TAG"," onPause");         
         mGLView.onPause();

     }

     @Override
     protected void onResume() {         
         super.onResume();
         Log.i("TAG"," onResume");         
         mGLView.onResume();
     }

    @Override
    protected void onStart() {
        // TODO Auto-generated method stub                
        super.onStart();
        Log.e(TAG, "onStart");

    }

    @Override
    protected void onStop() {
        // TODO Auto-generated method stub        
        super.onStop();        
        Log.e(TAG, "onStop");
    }

    public void testSetText(){
        Log.e(TAG, "testSetText");    

        TextView textView = new TextView(this);         
        textView.setText("Hello, Android");

        LinearLayout testLayout = new LinearLayout(this);

        RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);        
        lp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
        testLayout.addView(textView ,lp);
        mainFrame.addView(testLayout);

    }
}

代わりに別のアクティビティを実行しようとしたり、ゲームを呼び出したりsetContentView(R.layout.test_screen)するとfunction public void testSetText()、ゲームもクラッシュします。

ここで誰か良いアドバイスをくれませんか?

更新:
Macarse に感謝します。スタック トレースは次のとおりです。

08-16 15:19:52.121: INFO/TAG(8352):  canITalktoPIT 
08-16 15:19:52.121: ERROR/MY_APP(8352): test call PIT 2
08-16 15:19:52.203: WARN/dalvikvm(8352): threadid=11: thread exiting with uncaught exception (group=0x40015560)
08-16 15:19:52.214: ERROR/AndroidRuntime(8352): FATAL EXCEPTION: GLThread 10
08-16 15:19:52.214: ERROR/AndroidRuntime(8352): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
08-16 15:19:52.214: ERROR/AndroidRuntime(8352):     at android.view.ViewRoot.checkThread(ViewRoot.java:2932)
08-16 15:19:52.214: ERROR/AndroidRuntime(8352):     at android.view.ViewRoot.requestLayout(ViewRoot.java:629)
08-16 15:19:52.214: ERROR/AndroidRuntime(8352):     at android.view.View.requestLayout(View.java:8267)
08-16 15:19:52.214: ERROR/AndroidRuntime(8352):     at android.view.View.requestLayout(View.java:8267)
08-16 15:19:52.214: ERROR/AndroidRuntime(8352):     at android.view.View.requestLayout(View.java:8267)
08-16 15:19:52.214: ERROR/AndroidRuntime(8352):     at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:257)
08-16 15:19:52.214: ERROR/AndroidRuntime(8352):     at android.view.View.requestLayout(View.java:8267)
08-16 15:19:52.214: ERROR/AndroidRuntime(8352):     at android.view.ViewGroup.addView(ViewGroup.java:1869)
08-16 15:19:52.214: ERROR/AndroidRuntime(8352):     at android.view.ViewGroup.addView(ViewGroup.java:1851)
08-16 15:19:52.214: ERROR/AndroidRuntime(8352):     at dk.comp.testApp.testAppB.calling(testAppB.java:289)
08-16 15:19:52.214: ERROR/AndroidRuntime(8352):     at dk.comp.testApp.SigletonJohn.canITalktoPIT(SigletonJohn.java:43)
08-16 15:19:52.214: ERROR/AndroidRuntime(8352):     at org.cocos2dx.lib.testAppJavaCppComunication.pitTestJNI(testAppJavaCppComunication.java:47)
08-16 15:19:52.214: ERROR/AndroidRuntime(8352):     at org.cocos2dx.lib.Cocos2dxActivity.pitTestJNI(Cocos2dxActivity.java:177)
08-16 15:19:52.214: ERROR/AndroidRuntime(8352):     at org.cocos2dx.lib.Cocos2dxRenderer.nativeTouchesEnd(Native Method)
08-16 15:19:52.214: ERROR/AndroidRuntime(8352):     at org.cocos2dx.lib.Cocos2dxRenderer.handleActionUp(Cocos2dxRenderer.java:49)
08-16 15:19:52.214: ERROR/AndroidRuntime(8352):     at org.cocos2dx.lib.Cocos2dxGLSurfaceView$9.run(Cocos2dxGLSurfaceView.java:288)
08-16 15:19:52.214: ERROR/AndroidRuntime(8352):     at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1326)
08-16 15:19:52.214: ERROR/AndroidRuntime(8352):     at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1118)
08-16 15:19:52.238: WARN/ActivityManager(116):   Force finishing activity dk.comp.testApp/.testAppB
08-16 15:19:52.242: INFO/SOUND(8352):  PAUSE 
08-16 15:19:52.246: INFO/TAG(8352):  onPause



更新#2:
わかりました、私はまだこの問題に取り組んでおり、修正することはできません:(しかし、興味深いことがわかりました:

私の問題を要約すると、私のAndroidアプリには、完全に機能するcocos2dxシーンが実行されています。次に、ユーザーがボタンを押すと:

myBut = CCMenuItemImage::itemFromNormalImage("some.png", "some.png.png", this, menu_selector(Cocos2dMenuScene::butPushed));

JNI を介して Java 環境を呼び出し、ある種のビュー ( aTextViewなど) の追加を要求します (「 」を参照testSetText())。この時点で、私のアプリはクラッシュします - クラッシュログで:

WARN/dalvikvm(8352): threadid=11: キャッチされない例外で終了するスレッド (group=0x40015560) 08-16 15:19:52.214: ERROR/AndroidRuntime(8352): FATAL EXCEPTION: GLThread 10 08-16 15:19:52.214 : エラー/AndroidRuntime(8352):

現在、Java エンドに統合されている Admob も使用しています。Admob がデリゲート (例: onReceiveAd ) を介してメイン クラス (上記の myTest を参照) を呼び出すと、この時点で呼び出しtestSetText()て追加しようとしましたがTextView、すべて正常に動作します!

したがって、スレッド化と関係があると思います-しかし、私はこの分野の専門家ではないため、少し助けが必要になる可能性があります.

助言がありますか?

4

3 に答える 3

0

私は同じ問題を抱えていますが、修正して、android と cocos2d-x に何が起こったのかを理解しました。

基本的にAndroidシステムでは、UI自体を更新できるのはUIを作成するメインスレッドのみです。

そのため、ハンドラーとメッセージを使用して、メイン スレッドに UI を更新するように通知する必要があります。

さらに、JNI を介して c/c++ 関数で Java メソッドを呼び出す場合。

静的メソッドが最良の選択である可能性があり、最初に JavaVM を取得し、この JavaVM と env によって staticmethodid を取得できます。

これがあなたに役立つことを願っています。

于 2011-11-02T03:50:33.530 に答える
0

これは遅すぎるかもしれません。私は NDK に詳しくありませんが、スタック トレースから、問題が OpenGL スレッドからビューを追加しようとしていることがわかります (ログに記載されているように、これはスレッド 11 です)。次のように、UI スレッドでこのメソッドを実行する必要があります。

public void testSetText(){
    runOnUiThread(new Runnable() {

        @Override
        public void run() {
           Log.e(TAG, "testSetText");    

           TextView textView = new TextView(this);         
           textView.setText("Hello, Android");

           LinearLayout testLayout = new LinearLayout(this);

           RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);        
           lp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
           testLayout.addView(textView ,lp);
           mainFrame.addView(testLayout);
        }
    });
}
于 2013-12-18T13:26:39.010 に答える
0

私はこれを見つけました。ここに来る人は、プロセスの詳細を示す簡単で完全な回答を探している可能性が高いため、他の人にとって少し簡単にしたかったのです。実装例を次に示します。

import android.os.Handler;
import android.os.Message;
import android.os.Bundle;

このコードは、メイン スレッドによって実行されます。

// In main thread
Handler handler = new Handler(new Handler.Callback() {
    public boolean handleMessage(Message message) {
        Bundle bundle = message.getData();
        switch (bundle.getInt("type")) {
             case 0:
                String txt = bundle.getString("text");
                my_text_view.setText(txt);
                break;
        }
        return true;
    }
});

このコードは、メイン スレッドとの通信を希望する別のスレッドによって実行されます。

// In other thread.
Message msg = handler_variable_passed_to_thread.obtainMessage();
Bundle bundle = new Bundle();
bundle.putInt("type", 0);
bundle.putString("text", "hello world!");

システムはメッセージを配信し、Handlerコールバック用に作成したスレッドでコールバックを呼び出します。これにより、そのスレッドのリソースにアクセスできるようになります。これは他の多くのことにも使用でき、メッセージを渡すための非常に高速な方法です。UI スレッドの対話に限定されません。

于 2015-05-06T18:49:56.170 に答える