[ cocos2d-x ] -JNIによるJava連携3-

前回前々回の記事により、C++からJavaへアクセスしてカメラをインテント起動することが出来ました。

本記事からはカメラで撮影した画像でスプライトを生成し、レイヤーに張り付けることを目的とした、
JavaからC++の関数を呼ぶ方法をご紹介します。

上記に必要なことは、単純に撮影した画像のファイルパスをcocos2dxで受け取ることです。

ファイルパスを受け取る方法はいくつかありますが
今回は、インテント起動時に撮影した画像のファイルパスを指定して
撮影に成功した場合、指定したファイルパスをそのまま返却するという方法で
実装を進めていきたいと思います。

まずは前回までで作成したJNItest.javaを拡張します。

JNItest.java

public class JNItest extends Cocos2dxActivity{
	
	private static JNItest myActivity;
	private static String filePath;
	
    protected void onCreate(Bundle savedInstanceState){
		super.onCreate(savedInstanceState);

		myActivity = this;
	}

    public Cocos2dxGLSurfaceView onCreateView() {
    	Cocos2dxGLSurfaceView glSurfaceView = new Cocos2dxGLSurfaceView(this);
    	// test should create stencil buffer
    	glSurfaceView.setEGLConfigChooser(5, 6, 5, 0, 16, 8);
    	Log.d("DEBUG","cocos2dsurfaceview");		
    	
    	return glSurfaceView;
    }

    static {
    	System.loadLibrary("cocos2dcpp");
    }     
    
    // 呼び出すネイティブ関数(C++の関数)
    public native void Java2CEvent(String filePath);
    
    public static void C2JavaEvent(){

    	//修正前
    	//Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    	//myActivity.startActivity(intent);
        
    	//修正後
	    //保存パスを指定する
        final SimpleDateFormat data = new SimpleDateFormat("'Picture'_yyyyMMdd_HHmmss");
        final String filename = data.format( new Date(System.currentTimeMillis()) ) + ".jpg";
        filePath = Environment.getExternalStorageDirectory().toString() + "/DCIM/Camera/" +  filename;
        Uri uri = Uri.fromFile(new File(filePath));

        //startActivityForResultでカメラをインテント起動する
        final Intent intent = new Intent();
    	intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
    	intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
    	int requestCode = 1;
	    
    	myActivity.startActivityForResult(intent, requestCode);    	
    }
    
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);      
      
        //インテント起動時に設定したrequestCodeで判定して処理を分岐する
        switch (requestCode) {
        	case 1:
                //撮影に成功した場合
      	    	if (resultCode == RESULT_OK) {
                    //インテント起動時に指定したファイルパスを引数に
                    //C++の関数を呼ぶ
          			Java2CEvent(filePath);
          		}
          		break;
   
          	default:
          		break;
        }
    }
}

ファイルパスを格納する変数をメンバ変数として宣言します。
onActivityResult内では撮影に成功したときのみC++の関数を呼んでいます。

if文内にある、Java2CEventがC++で実装する関数で
Javaでnativeメソッドとして定義します。

// 呼び出すネイティブ関数(C++の関数)
public native void Java2CEvent(String filePath);

JNItest.javaの修正は以上です。

次に、C++側にJavaから呼ばれる関数を実装したクラスを作成します。

以下の2つのファイルを用意します。

Link2Cpp.h

#ifndef __LINK_2_CPP__
#define __LINK_2_CPP__

#include <iostream>
#include "cocos2d.h"

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)

class Link2Cpp
{
public:
    static void Java2CEvent(char *filePath);
};

#endif

#endif

Link2Cpp.c

#include "cocos2d.h"
#include "HelloWorldScene.h"

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)

#include "Link2Cpp.h"
#include <jni.h>

void Link2Cpp::Java2CEvent(char *filePath)
{
    //引数に受け取ったfilePathを指定しHelloWorldクラスの関数を呼ぶ
	HelloWorld::addImageSprite(filePath);
}

#endif

これで、必要なクラスはすべて揃いました。
残る作業は、main.cppとHelloWorld.cppに一部処理を追加しますが
これらについては、次回お話したいと思います。

以上で、本記事は終了となります。

<次回以降の更新について>
次回は、Javaとc++を繋ぐために必要な処理の実装についてご紹介します。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*