手把手教你使用jni双向调用

36 篇文章 2 订阅

一、需求:

       项目为cocos2d-X开发的游戏,需要为android版本添加微信分享, 具体是在游戏界面中添加一个分享按钮,点击该按钮即可分享。

       最终考虑通过jni,在C/C++层通过jni调用微信AnroidSDK。

       在分享成功后,在java层调用C++层使角色复活.

二、本地(native)调用java代码:

分享按钮应该是在游戏中,也就是C/C++的本地层,android分享SDK则是在java层,所以这里用本地函数调用java方法。
       先贴native代码:MyJni.h和MyJni.cpp

#ifndef __SkiSim__MyJni__
#define __SkiSim__MyJni__

#include <string.h>
#include <jni.h>

void openUmengShareJni(int score);

       

#include "MyJni.h"
#include "platform/android/jni/JniHelper.h"
#include "cocos2d.h"
#include "MainLayer.h"
using namespace cocos2d;

extern JNIEnv* jniEnv;


jclass TestProvider;
jmethodID openUmengShare;


void openUmengShareJni(int score) {
	JniMethodInfo methodInfo;

	if (TestProvider == NULL || openUmengShare == NULL) {
		return;
	} else {
		jniEnv->CallStaticObjectMethod(TestProvider, openUmengShare, score);
	}
}
int InitProvider() {

	__android_log_print(ANDROID_LOG_INFO, "JNIMsg", "InitProvider Begin  1");

	if (jniEnv == NULL) {
		return 0;
	}

	if (TestProvider == NULL) {
		TestProvider = jniEnv->FindClass(
				"com/andrew/game/Flappy");
		if (TestProvider == NULL) {
			return -1;
		}

	}

	if (openUmengShare == NULL) {
		openUmengShare = jniEnv->GetStaticMethodID(TestProvider,
				"openShareBoard", "(I)V");
		if (openUmengShare == NULL) {
			jniEnv->DeleteLocalRef(TestProvider);
			return -2;
		}

	}
}

注意extern JNIEnv* jniEnv;这个变量,由于在cocos2dx项目中,都会有一个main.cpp源文件,打开即可看到

void Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit函数,我们在这个函数中初始化jniEnv变量:

先声明jniEnv:

JNIEnv* jniEnv;
Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit函数中:

void Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit(JNIEnv* env,
		jobject thiz, jint w, jint h) {
	if(jniEnv == NULL){
		jniEnv = env;
	}
	if (!CCDirector::sharedDirector()->getOpenGLView()) {
		CCEGLView *view = CCEGLView::sharedOpenGLView();
		view->setFrameSize(w, h);

		AppDelegate *pAppDelegate = new AppDelegate();
		CCApplication::sharedApplication()->run();
	}
}

       可以看到,我们定义了void openUmengShareJni(int score) 这个函数,最关键的代码在于:

    创建TestProvider这个jclass对象

TestProvider = jniEnv->FindClass("com/andrew/game/Flappy");
    以及函数openUmengShare这个jmethodId对象

openUmengShare = jniEnv->GetStaticMethodID(TestProvider,"openShareBoard", "(I)V");

       调用java方法:

jniEnv->CallStaticObjectMethod(TestProvider, openUmengShare, score);

       然后上java代码:

com.andrew.game.Flappy:

static void openShareBoard(int score){
	//分享代码
}


最后,在任何需要调用分享代码的地方,include "MyJni.h"并调用openUmengShareJni(int score)即可实现分享功能。
    有几个容易出错的地方,第一是java函数的签名不要弄错,在创建TestProvider时的参数:"com/andrew/game/Flappy"即java包名和类名:com.andrew.game.Flappy,
     jniEnv->GetStaticMethodID(TestProvider,"openShareBoard", "(I)V");表示方法名为openShareBoard,参数"(I)V"即返回值为void,参数为int,
     jniEnv->GetStaticMethodID表示该方法有static修饰。大家可以对比java代码即可发现。


三、java调用本地代码:
    显然,角色复活是游戏中的事件,而分享成功后的回调仍在java层,所以这里要用java调用本地函数。
    先上java代码:
     com.andrew.game.Flappy:

public native static int revival();


   本地代码:
         在MyJni.h中添加jni接口:

extern "C"{
	JNIEXPORT jint Java_com_andrew_game_Flappy_revival(JNIEnv* env,jobject thiz);
}


在MyJni.cpp中添加实现:
extern "C" {
JNIEXPORT jint Java_
com_andrew_game_Flappy
_revival(JNIEnv* env,jobject thiz) {/**CCDirector *director = CCDirector::sharedDirector();if (director->getOpenGLView()) {
		
		CCScene *scene = director->getRunningScene();
		MainLayer *layer = (MainLayer*) scene->getChildByTag(2222);
		layer->revival();
	}
	*/
}


  被注释的代码是该游戏中的角色复活代码。可以在此添加任何你需要实现的任务.需要注意的地方仍是包名、类名和方法名.
JNIEXPORT jint Java_com_andrew_game_Flappy_revival(JNIEnv* env,jobject thiz)


//返回值是int,对应包名cn.andrew.game,类名Flappy,方法为static static int revival();

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值