前回、前々回の記事により、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++を繋ぐために必要な処理の実装についてご紹介します。