cocos2d-x Jni c++ java互调 安全刷新UI控件最简单例子(上)

来源:互联网 发布:淘宝电影票为什么便宜 编辑:程序博客网 时间:2024/05/17 02:56

上篇

Java调用c++,刷新CCLabelTTF


首先我们先以引擎2.2.1为例子来新建一个TestJni的项目

创建方式如下:

python create_project.py -project TestJni -package org.cocos2dx.TestJni -language cpp

如果你对创建项目有什么疑问,可以参考这遍文章:

http://blog.csdn.net/liuyuyefz/article/details/9129525



我们第一个目标是:通过java层来给C++层发送信号,然后来让我们的cocos2d-x的HelloWorld项目中的CCLabelTTF来改变显示的内容。

请相信我这只需要非常简单的几步操作。然后奇迹就会降临。


我们先来看看我们熟悉的cocos2d-x的c++代码需要添加和修改些什么。

首先我们在  HelloWorldScene.cpp  里搜索一下这段代码:

CCLabelTTF * pLabel = CCLabelTTF::create("Hello World","Arial", 24);

这是创建一个Hello World的Label,也就是我们这次的主角。

我们想要在java处通过调用一个函数,来改变这个label的值。所以我们必须把pLabel重新定义为一个全局变量。

你需要把上面那段代码替换成如下代码

pLabel = CCLabelTTF::create("Hello World""Arial", 24);


同时在 HelloWorldScene.h中的

public:

下添加如下代码  

cocos2d::CCLabelTTF * pLabel ;

第二步:我们在  HelloWorldScene.cpp  里的空白部分添加如下代码


这个是用来改变pLabel中的显示内容

std::string HelloWorld::changeStr =" ";//添加一个全局static变量表示状态,来接收java传过来的字符串


void HelloWorld::changeText(float t)//添加一个方法来改变label的显示内容

{

    if (HelloWorld::changeStr.compare(" ") !=0)//当java没有传内容过来的时候HelloWorld::changeStr 为空

    {

        pLabel ->setString(HelloWorld::changeStr.c_str());

        HelloWorld::changeStr =" ";

    }

}

同时在 HelloWorldScene.h中的

public:

下添加如下代码  

static std::string changeStr;

void changeText(float t);


到此处你可以试试看在HelloWorldScene.cpp

bool HelloWorld::init(){

....

}

函数中的最下面添加如下代码,并且运行看看

CCDirector::sharedDirector()->getScheduler()->scheduleSelector(schedule_selector(HelloWorld::changeText),this, 0,false);//添加一个计时器,来动态每一帧检测一下是java有传文本过来。



到此位置运行代码,你可以看到项目跑起来了,但是还是什么都没有改变。

这个是因为我们还没有从java端来传一个字符串来通知cocos2d-x的label改变。代价也许觉得很奇怪为什么我们要开一个scheduler来不停的检测java是否有传文本过来。因为

opengl的限制,ui只能在主线程中刷新。而我们传过来的文本是通过另外一条线程。所以我们必须要在主线程中通过schedule来检测改变UI控件。


第三步:我们在  HelloWorldScene.cpp  里的空白部分添加Jni代码

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)

#include <jni.h>

extern

"C"

{

    void Java_org_cocos2dx_TestJni_TestJni_changeTTFLabel(JNIEnv*  env, jobject thiz,jstring textStr)

    {

        //这里java调用changeTTFLabel("Test MyLabel Change");这里就会被调用。jint

        const char* str;

        str = env->GetStringUTFChars(textStr, false);

        

        std::string tempStr(str);

        

        HelloWorld::changeStr = tempStr;

    }

}

#endif

第一部分:

我们来分布将讲解以上代码

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)

#endif

以上这段代码是限定平台。这段代码之间的代码只有在编译android项目的时候才会被调用到。因为调用ios项目的时候我们不能够调用到这个之间的代码,否则会编译出错通不过。

第二部分:

必须加上extern “C”,声明以c语言的方式进行编译,因为c++和c在编译时生成的函数签名不一样,可以在网上查找相关资料,不然运行的时候会出现链接错误。

第三部分:

void Java_org_cocos2dx_TestJni_TestJni_changeTTFLabel(JNIEnv*  env, jobject thiz,jstring textStr)

这边的格式规律为

Java_签名(org_cocos2dx_TestJni_)_类名(TestJni)_changeTTFLabel(在该类下要调用的函数)

下面这一段的规律

(JNIEnv*  env, jobject thiz,jstring textStr)

前面两个为必写,最后jstring textStr为要传的参数。

参数可以是jstring 或者 jint 他们分别对应了java的String 或者int类型

第四部分:

 const char* str;

        str = env->GetStringUTFChars(textStr, false);

jstring转化为c++的 const char


在此c++部分的代码我们已经全部完成。



第四步:我们在eclipse中打开如下页面


在进入这个步骤之前你要先配置好所有eclipse下编译cocos2dx android环境。

参考这篇文章:http://blog.csdn.net/jackystudio/article/details/12419387




然后在

public class TestJniextends Cocos2dxActivity{

......

}

函数中最下面添加如下代码。

private static native void changeTTFLabel(String textStr);//这个是作为中介接口,提供java调用c++里面的同名JNI函数的。



最后在

 protected void onCreate(Bundle savedInstanceState){

......

}

函数中最下面添加如下代码。调用

changeTTFLabel("Test MyLabel Change!");


第五步:我们需要在真机上编译c++和java代码才可以看到最后的结果。

c++代码的编译

我们先进入

cocos2d-x2.2.0/projects/TestJni/proj.android

文件夹下面,编译

build_native.sh

的shell脚本来编译c++

windows下你需要有cywin来模拟linux环境

mac下面直接

./build_native.sh即可。编译成功大致为如下画面。如果编译结果中有erro,你要注意查看说明来看看c++什么地方出错了。





然后在eclipse里面编译android的java部分


方法是eclipse-》clean



最后连上真机:调试看结果label被从Hello World改变为Test MyLabel Change!



接下篇:http://blog.csdn.net/liuyuyefz/article/details/17758809

1 0