android jni开发中c++ 调用java 方法

    最近几天搞fbreader 电子书的二次开发,其中需要 c++ 调用 java方法解密电子书,所以l老虎吃天,硬着头皮看c++代码。

 具体的思路如下,其实也就这几步:

     1. jni 中用到 java反射的方法 找到java类,  找类的对象  ,找到方法。,

     2. 如果 是静态的方法都不用找对象, 直接找到类, 找静态方法。

     是你一定感觉很简单,我也这么觉的,可是具体做的时候就会遇到些不可描述的弱智问题,呵呵!!

直接上代码:

1.1


     if (stream.isNull() || !stream->open()) {
         return false;
     }

     std::size_t length;
     int allLength = 0;
     do {
         length = stream->read(myParserBuffer, BUFFER_SIZE);
         allLength += length;
     } while ((length == BUFFER_SIZE) && !myInterrupted);//每次读取一个xhtml

     char *all = (char *) malloc(allLength);
     stream->seek(0, true);
     stream->read(all, allLength);

     std::string result = decode(all, allLength);

   c++ 的语法,不懂的还得熟悉 一下, stream->read()   代表指针 调用read方法 (*stream).read(),malloc 代表分配内存地址,std:: string  就是固定的命名空间的一些写法,基本语言都相似,知识细节不同,我是目标导向, 看懂基本的意思就行啦,其它的以后有机会再看。

问题就在这:std::string result = decode(all, allLength); 自己定义一个调用java解密的方法decode , 可是怎么也不知怎么配置.h 文件和 方法实现,后来网上偶然看到 使用 alt+enter 键,自动在.h 生成定义的头文件 ,在.cpp 生成方法的实现,IDE还真是先进啊,如下所示:.h 文件中
private:
	bool myInterrupted;
	ZLXMLReaderInternal *myInternalReader;
	char *myParserBuffer;
	std::vector<shared_ptr<nsMap> > myNamespaces;
	std::string myErrorMessage;

friend class ZLXMLReaderInternal;
friend class ZLXMLReaderHandler;
	
std::string  decode(const char *all, int length); .h 中就是这句

  .cpp 中是这样子的: 方法的的实现 ,具体调用java方法的过程就得您老自己写。

std::string ZLXMLReader::decode(const char *all, int length) {
   
    return string();
}

1.2  开始调用java方法了 ,进入高潮了。

    首先定义一个java方法,要不调个毛啊: 

package org.geometerplus.zlibrary.core.xml;

public class DecodeXml {

    public String decode(String html) {
        Log.i("dddd", "decode:java1方法 ");
        return  "<defghijk>";
    }

    public static String decodeXml() {
        Log.i("dddd", "decode:java2静态方法");
        return  "<defghijk>";
    }
}

其次就是前面说的反射的大招 :

std::string ZLXMLReader::decode(const char *all, int length) {
    //1.调用java方法;获得env指针,类似与java中上下文
    JNIEnv *env = AndroidUtil::getEnv();
    if (env == NULL) {
        return 0;
    }
     // 2. 找到类 ,后面是包名
    jclass cls = env->FindClass("org/geometerplus/zlibrary/core/xml/DecodeXml");
    if (cls == 0) {
        return 0;
    }
    // 3.找到方法id, 括号里面官名叫方法签名,其实就是传参类型和 返回类型,我这个是字符串
    jmethodID mid;
    mid = env->GetMethodID(cls, "decode", "(Ljava/lang/String;)Ljava/lang/String;");
    // 4.到方法肯定要对象调, 下面就是默认构造方法的对象,也可以自己重载构造方法; 静态方法当然不要对象
    jobject j_object = env->AllocObject(cls);
    const char *str = "fkdfdk";
    if (mid == 0) {
        return 0;
    }
    const char *name = "World";
    jstring arg = env->NewStringUTF(name);
    // 5. 这句就是直捣黄龙的黄龙,调一般方法
    jstring result = (jstring) env->CallObjectMethod(j_object, mid, arg);
//    __android_log_print(ANDROID_LOG_INFO, "dddd", "2GetTime Begin", result);
    str = env->GetStringUTFChars(result, 0);
//    env->ReleaseStringUTFChars(result, 0);
    return str;
}

   经过以上这几步,既可以在java 中看到打印的日志了。看起来简单啊,但是当你对c陌生的时候, 每走一步你就骂,这是什么鬼啊,要当贼就不要怕挨打,呵呵哒!!

猜你喜欢

转载自blog.csdn.net/shidalang/article/details/83866074