#include #include #include #include #include "securec.h" #include "discovery_service.h" #include "softbus_bus_center.h" #include "com_jg_softbus_naservice_SubscribeService.h" // 全局变量,用于保存Java虚拟机的引用 JavaVM *jvm; //全局引用变量,用于保存java对象 jobject globalRef; /** * 解析java对象为c的SubscribeInfo结构 */ int ParseSubscribeInfo(JNIEnv *env, jobject subscribeInfo, SubscribeInfo *info) { jclass infoClass = (*env)->GetObjectClass(env, subscribeInfo); //读取subscribeId jmethodID getSubscribeIdMethod = (*env)->GetMethodID(env, infoClass, "getSubscribeId", "()I"); jint subscribeId = (*env)->CallIntMethod(env, subscribeInfo, getSubscribeIdMethod); info->subscribeId = subscribeId; printf("SubscribeInfo->subscribeId:%d\n", subscribeId); //获取mode jmethodID getDiscoverModeMethod = (*env)->GetMethodID(env, infoClass, "getMode", "()Lcom/jg/softbus/discovery/enums/DiscoverMode;"); jobject modeInfo = (*env)->CallObjectMethod(env, subscribeInfo, getDiscoverModeMethod); jclass modeClass = (*env)->GetObjectClass(env, modeInfo); jmethodID getModeMethod = (*env)->GetMethodID(env, modeClass, "valueOf", "()I"); jint mode = (*env)->CallIntMethod(env, modeInfo, getModeMethod); info->mode = mode; (*env)->DeleteLocalRef(env, modeInfo); printf("SubscribeInfo->mode:%d\n", mode); //获取medium jmethodID getMediumMethod = (*env)->GetMethodID(env, infoClass, "getMedium", "()Lcom/jg/softbus/discovery/enums/ExchangeMedium;"); jobject mediumInfo = (*env)->CallObjectMethod(env, subscribeInfo, getMediumMethod); jclass mediumClass = (*env)->GetObjectClass(env, mediumInfo); jmethodID getMediumMethod2 = (*env)->GetMethodID(env, mediumClass, "valueOf", "()I"); jint medium = (*env)->CallIntMethod(env, mediumInfo, getMediumMethod2); info->medium = medium; (*env)->DeleteLocalRef(env, mediumInfo); printf("SubscribeInfo->medium:%d\n", medium); //获取freq频次 jmethodID getFreqMethod = (*env)->GetMethodID(env, infoClass, "getFreq", "()Lcom/jg/softbus/discovery/enums/ExchangeFreq;"); jobject freqInfo = (*env)->CallObjectMethod(env, subscribeInfo, getFreqMethod); jclass freqClass = (*env)->GetObjectClass(env, freqInfo); jmethodID getFreqMethod2 = (*env)->GetMethodID(env, freqClass, "valueOf", "()I"); jint freq = (*env)->CallIntMethod(env, freqInfo, getFreqMethod2); info->freq = freq; (*env)->DeleteLocalRef(env, freqInfo); printf("SubscribeInfo->freq:%d\n", freq); //获取isSameAccount bool类型 jmethodID getIsSameAccountMethod = (*env)->GetMethodID(env, infoClass, "getIsSameAccount", "()Z"); info->isSameAccount = (*env)->CallBooleanMethod(env, subscribeInfo, getIsSameAccountMethod); printf("SubscribeInfo->isSameAccount:%d\n", info->isSameAccount); //获取isWakeRemote bool类型 jmethodID getIsWakeRemoteMethod = (*env)->GetMethodID(env, infoClass, "getIsWakeRemote", "()Z"); info->isWakeRemote = (*env)->CallBooleanMethod(env, subscribeInfo, getIsWakeRemoteMethod); printf("SubscribeInfo->isWakeRemote:%d\n", info->isWakeRemote); //获取capability jmethodID getCapabilityMethod = (*env)->GetMethodID(env, infoClass, "getCapability", "()Ljava/lang/String;"); jstring capability = (*env)->CallObjectMethod(env, subscribeInfo, getCapabilityMethod); if(capability != NULL) { const char *capabilityStr = (*env)->GetStringUTFChars(env, capability, 0); char *temp = (char *)malloc(strlen(capabilityStr) + 1); // 复制字符串到新分配的内存 strcpy(temp, capabilityStr); info->capability = temp; (*env)->ReleaseStringUTFChars(env, capability, capabilityStr); } else { info->capability = "osdCapability"; } printf("SubscribeInfo->capability:%s\n", info->capability); //获取capabilityData jmethodID getCapabilityDataMethod = (*env)->GetMethodID(env, infoClass, "getCapabilityData", "()Ljava/lang/String;"); jstring capabilityData = (*env)->CallObjectMethod(env, subscribeInfo, getCapabilityDataMethod); if(capabilityData != NULL) { const char *capabilityDataStr = (*env)->GetStringUTFChars(env, capabilityData, 0); strcpy(info->capabilityData, capabilityDataStr); if(info->capabilityData == NULL) { info->capabilityData = NULL; } (*env)->ReleaseStringUTFChars(env, capabilityData, capabilityDataStr); printf("SubscribeInfo->capabilityData:%s\n", capabilityDataStr); } //获取数据长度 jmethodID getDataLenMethod = (*env)->GetMethodID(env, infoClass, "getDataLen", "()I"); info->dataLen = (*env)->CallIntMethod(env, subscribeInfo, getDataLenMethod); printf("SubscribeInfo->dataLen:%d\n", info->dataLen); return 0; } /** * 将c的DeviceInfo对象转换为java的object对象 */ jobject DeviceInfoToJavaObject(JNIEnv *env, const DeviceInfo *device) { //创建java的DeviceInfo对象 jclass deviceInfoClass = (*env)->FindClass(env, "com/jg/softbus/device/DeviceInfo"); if (deviceInfoClass == NULL) { // 处理错误 printf("Cannot found the java class:com/jg/softbus/device/DeviceInfo"); return NULL; } jmethodID constructor = (*env)->GetMethodID(env, deviceInfoClass, "", "()V"); if (constructor == NULL) { // 处理错误 printf("Cannot found the default constructor of DeviceInfo."); return NULL; } jobject obj = (*env)->NewObject(env, deviceInfoClass, constructor); if (obj == NULL) { // 处理错误 printf("Cannot create the DeviceInfo object."); return NULL; } //设置devId jmethodID setDevIdMethod = (*env)->GetMethodID(env, deviceInfoClass, "setDevId", "(Ljava/lang/String;)V"); jstring devIdStr = (*env)->NewStringUTF(env, device->devId); (*env)->CallVoidMethod(env, obj, setDevIdMethod, devIdStr); (*env)->DeleteLocalRef(env, devIdStr); //设置devName jmethodID setDevNameMethod = (*env)->GetMethodID(env, deviceInfoClass, "setDevName", "(Ljava/lang/String;)V"); jstring devNameStr = (*env)->NewStringUTF(env, device->devName); (*env)->CallVoidMethod(env, obj, setDevNameMethod, devNameStr); (*env)->DeleteLocalRef(env, devNameStr); //发现DeviceType java类,根据其提供的静态getForValue(int)方法获取DeviceType对象 jclass deviceTypeClass = (*env)->FindClass(env, "com/jg/softbus/device/DeviceType"); if (deviceTypeClass == NULL) { // 处理错误 printf("Cannot found the java class:com/jg/softbus/device/DeviceType"); return NULL; } jmethodID getForValueMethod = (*env)->GetStaticMethodID(env, deviceTypeClass, "getForValue", "(I)Lcom/jg/softbus/device/DeviceType;"); if (getForValueMethod == NULL) { // 处理错误 printf("Cannot found the static method:getForValue(int)"); return NULL; } jobject deviceTypeObj = (*env)->CallStaticObjectMethod(env, deviceTypeClass, getForValueMethod, (int)(device->devType)); if (deviceTypeObj == NULL) { // 处理错误 printf("Cannot found DeviceType. the devType is: %d", device->devType); return NULL; } //设置devType jmethodID setDevTypeMethod = (*env)->GetMethodID(env, deviceInfoClass, "setDevType", "(Lcom/jg/softbus/device/DeviceType;)V"); (*env)->CallVoidMethod(env, obj, setDevTypeMethod, deviceTypeObj); (*env)->DeleteLocalRef(env, deviceTypeObj); //设置在线状态isOnline // jmethodID setIsOnlineMethod = (*env)->GetMethodID(env, deviceInfoClass, "setOnline", "(Z)V"); // (*env)->CallVoidMethod(env, obj, setIsOnlineMethod, device->isOnline); //设置地址数addrNum jmethodID setAddrNumMethod = (*env)->GetMethodID(env, deviceInfoClass, "setAddrNum", "(I)V"); (*env)->CallVoidMethod(env, obj, setAddrNumMethod, device->addrNum); //发现ConnectionAddr的java类 jclass connectionAddrClass = (*env)->FindClass(env, "com/jg/softbus/network/protocol/ConnectionAddr"); if (connectionAddrClass == NULL) { // 处理错误 printf("Cannot found the class:com/jg/softbus/network/protocol/ConnectionAddr"); return NULL; } //构建一个java ConnectionAddr的数组,数组长度为addrNum jobjectArray addrArray = (*env)->NewObjectArray(env, device->addrNum, connectionAddrClass, NULL); //发现com.jg.softbus.network.protocol.ConnectionAddrType java类,根据其提供的静态getForValue(int)方法获取ConnectionAddrType对象 jclass connectionAddrTypeClass = (*env)->FindClass(env, "com/jg/softbus/network/protocol/ConnectionAddrType"); if (connectionAddrTypeClass == NULL) { // 处理错误 printf("Cannot found the class:com/jg/softbus/network/protocol/ConnectionAddrType"); return NULL; } //查找com.jg.softbus.network.protocol.ConnectionAddrInfo jclass connectionAddrInfoClass = (*env)->FindClass(env, "com/jg/softbus/network/protocol/ConnectionAddrInfo"); if (connectionAddrInfoClass == NULL) { // 处理错误 printf("Cannot found the class:com/jg/softbus/network/protocol/ConnectionAddrInfo"); return NULL; } //查找ConnectionAddrInfo的无参构造函数 jmethodID connectionAddrInfoConstructor = (*env)->GetMethodID(env, connectionAddrInfoClass, "", "()V"); if (connectionAddrInfoConstructor == NULL) { // 处理错误 printf("Cannot found the constructor:com/jg/softbus/network/protocol/ConnectionAddrInfo"); return NULL; } //查找com.jg.softbus.network.protocol.IpAddr的java对象 jclass ipAddrClass = (*env)->FindClass(env, "com/jg/softbus/network/protocol/IpAddr"); if(ipAddrClass == NULL){ printf("Cannot found the IpAddr class."); return NULL; } //查找IpAddr带参构造函数,函数结构为:IpAddr(String ip, int port) jmethodID ipAddrConstructor = (*env)->GetMethodID(env, ipAddrClass, "", "(Ljava/lang/String;I)V"); if(ipAddrConstructor == NULL){ printf("Cannot found the constructor of IpAddr."); return NULL; } //查找com.jg.softbus.network.protocol.BrAddr的java对象 jclass brAddrClass = (*env)->FindClass(env, "com/jg/softbus/network/protocol/BrAddr"); if(brAddrClass == NULL){ printf("Cannot found the BrAddr class."); return NULL; } //查找BrAddr带参构造函数,函数结构为:BrAddr(String brMac) jmethodID brAddrConstructor = (*env)->GetMethodID(env, brAddrClass, "", "(Ljava/lang/String)V"); if(brAddrConstructor == NULL){ printf("Cannot found the constructor of BrAddr."); return NULL; } //查找com.jg.softbus.network.protocol.BleAddr的java对象 jclass bleAddrClass = (*env)->FindClass(env, "com/jg/softbus/network/protocol/BleAddr"); if(bleAddrClass == NULL){ printf("Cannot found the BleAddr class."); return NULL; } //查找BleAddr无参构造函数,函数结构为:BleAddr() jmethodID bleAddrConstructor = (*env)->GetMethodID(env, bleAddrClass, "", "()V"); if(bleAddrConstructor == NULL){ printf("Cannot found the constructor of BleAddr."); return NULL; } //查找com.jg.softbus.network.protocol.BleProtocolType的java对象 // jclass bleProtocolTypeClass = (*env)->FindClass(env, "com/jg/softbus/network/protocol/BleProtocolType"); // if(bleProtocolTypeClass == NULL){ // printf("Cannot found the BleProtocolType class."); // return NULL; // } //查找com/jg/softbus/network/protocol/SessionAddr的java对象 // jclass sessionAddrClass = (*env)->FindClass(env, "com/jg/softbus/network/protocol/SessionAddr"); // if(sessionAddrClass == NULL){ // printf("Cannot found the SessionAddr class."); // return NULL; // } //查找SessionAddr无参构造函数,函数结构为:SessionAddr() // jmethodID sessionAddrConstructor = (*env)->GetMethodID(env, sessionAddrClass, "", "()V"); // if(sessionAddrConstructor == NULL){ // printf("Cannot found the constructor of SessionAddr."); // return NULL; // } for (int i = 0; i < device->addrNum; i++) { //基于无参的构造函数创建ConnectionAddr对象 jmethodID connectionAddrConstructor = (*env)->GetMethodID(env, connectionAddrClass, "", "()V"); jobject addrObj = (*env)->NewObject(env, connectionAddrClass, connectionAddrConstructor); //获取ConnectionAddrType对象 jmethodID getForValueMethod = (*env)->GetStaticMethodID(env, connectionAddrTypeClass, "getForValue", "(I)Lcom/jg/softbus/network/protocol/ConnectionAddrType;"); if (getForValueMethod == NULL) { // 处理错误 printf("Cannot found the method:getForValue(int)"); return NULL; } //根据device提供的地址类型获取ConnectionAddrType对象 jobject addrTypeObj = (*env)->CallStaticObjectMethod(env, connectionAddrTypeClass, getForValueMethod, device->addr[i].type); if(addrTypeObj == NULL) { // 处理错误 printf("Cannot found the ConnectionAddrType. type info: %d", device->addr[i].type); return NULL; } //查找ConnectionAddr的setType(ConnectionAddrType type)方法 jmethodID setTypeMethod = (*env)->GetMethodID(env, connectionAddrClass, "setType", "(Lcom/jg/softbus/network/protocol/ConnectionAddrType;)V"); //设置地址类型到地址对象中 (*env)->CallVoidMethod(env, addrObj, setTypeMethod, addrTypeObj); (*env)->DeleteLocalRef(env, addrTypeObj); //无参创建ConnectionAddrInfo的java对象 jobject infoObj = (*env)->NewObject(env, connectionAddrInfoClass, connectionAddrInfoConstructor); //判断device->addr[i].type的类型,可参考下面代码的Switch方式 switch (device->addr[i].type) { case CONNECTION_ADDR_WLAN: { printf("ip=%s,port=%d,", device->addr[i].info.ip.ip, device->addr[i].info.ip.port); } case CONNECTION_ADDR_ETH: { jstring ipstr = (*env)->NewStringUTF(env, device->addr[i].info.ip.ip); //并使用有参构造函数进行初始化 jobject ipAddrObj = (*env)->NewObject(env, ipAddrClass, ipAddrConstructor, ipstr, device->addr[i].info.ip.port); //将地址对象写入ConnectionAddrInfo对象中 jmethodID setIpMethod = (*env)->GetMethodID(env, connectionAddrClass, "setIp", "(Lcom/jg/softbus/network/protocol/IpAddr;)V"); //设置地址类型到地址对象中 (*env)->CallVoidMethod(env, addrObj, setIpMethod, ipAddrObj); (*env)->DeleteLocalRef(env, ipAddrObj); break; } case CONNECTION_ADDR_BR: { jstring brMacStr = (*env)->NewStringUTF(env, device->addr[i].info.br.brMac); //并使用有参构造函数进行初始化 jobject brAddrObj = (*env)->NewObject(env, brAddrClass, brAddrConstructor, brMacStr); //将地址对象写入ConnectionAddrInfo对象中 jmethodID setBrMethod = (*env)->GetMethodID(env, connectionAddrClass, "setBr", "(Lcom/jg/softbus/network/protocol/BrAddr;)V"); //设置地址类型到地址对象中 (*env)->CallVoidMethod(env, addrObj, setBrMethod, brAddrObj); (*env)->DeleteLocalRef(env, brAddrObj); (*env)->DeleteLocalRef(env, brMacStr); break; } case CONNECTION_ADDR_BLE: { //并使用构造函数进行初始化 jobject bleAddrObj = (*env)->NewObject(env, bleAddrClass, bleAddrConstructor); // //获取BleProtocolType对象 // jmethodID getForValueMethod2 = (*env)->GetStaticMethodID(env, bleProtocolTypeClass, "getForValue", "(I)Lcom/jg/softbus/network/protocol/BleProtocolType;"); // if (getForValueMethod2 == NULL) { // // 处理错误 // printf("Cannot found the method:getForValue(int)"); // return NULL; // } // //根据device提供的bleprotocol类型获取BleProtocolType对象 // jobject bleProtocolTypeObj = (*env)->CallStaticObjectMethod(env, bleProtocolTypeClass, getForValueMethod2, device->addr[i].info.ble.protocol); // if(bleProtocolTypeObj == NULL) { // // 处理错误 // printf("Cannot found the BleProtocolType. type info: %d", device->addr[i].info.ble.protocol); // return NULL; // } // //将地址对象写入ConnectionAddrInfo对象中 // jmethodID setProtocolMethod = (*env)->GetMethodID(env, bleAddrClass, "setProtocol", "(Lcom/jg/softbus/network/protocol/BleProtocolType;)V"); // (*env)->CallVoidMethod(env, bleAddrObj, setProtocolMethod, bleProtocolTypeObj); // (*env)->DeleteLocalRef(env, bleProtocolTypeObj); //setbleMac jmethodID setBleMacMethod = (*env)->GetMethodID(env, bleAddrClass, "setBleMac", "(Ljava/lang/String)V"); jstring bleMac = (*env)->NewStringUTF(env, device->addr[i].info.ble.bleMac); (*env)->CallVoidMethod(env, bleAddrObj, setBleMacMethod, bleMac); (*env)->DeleteLocalRef(env, bleMac); //setUdidHash jmethodID setUdidHashMethod = (*env)->GetMethodID(env, bleAddrClass, "setUdidHash", "([B)V"); size_t len = UDID_HASH_LEN / sizeof(uint8_t); jbyteArray byteArray = (*env)->NewByteArray(env, len); (*env)->SetByteArrayRegion(env, byteArray, 0, len, (const jbyte*)device->addr[i].info.ble.udidHash); // 将udidHash转换为整数 // int hash_value = 0; // for (int k = 0; k < UDID_HASH_LEN; k++) { // hash_value = (hash_value << 8) + device->addr[i].info.ble.udidHash[k]; // } (*env)->CallVoidMethod(env, bleAddrObj, setUdidHashMethod, byteArray); (*env)->DeleteLocalRef(env, byteArray); // //setPsm // jmethodID setPsmMethod = (*env)->GetMethodID(env, bleAddrClass, "setPsm", "(I)V"); // (*env)->CallVoidMethod(env, bleAddrObj, setPsmMethod, device->addr[i].info.ble.psm); //将地址对象写入ConnectionAddrInfo对象中 jmethodID setBleMethod = (*env)->GetMethodID(env, connectionAddrClass, "setBle", "(Lcom/jg/softbus/network/protocol/BrAddr;)V"); (*env)->CallVoidMethod(env, addrObj, setBleMethod, bleAddrObj); (*env)->DeleteLocalRef(env, bleAddrObj); printf("bleMac=%s,", device->addr[i].info.ble.bleMac); break; } // case CONNECTION_ADDR_SESSION: // //创建SessionAddr对象 // jobject sessionAddrObj = (*env)->NewObject(env, sessionAddrClass, sessionAddrConstructor); // //获取void setSessionId(Integer sessionId)方法 // jmethodID setSessionIdMethod = (*env)->GetMethodID(env, sessionAddrClass, "setSessionId", "(I)V"); // //将device中的sessionId调用方法设置到sessionAddrObj中 // (*env)->CallVoidMethod(env, sessionAddrObj, setSessionIdMethod, device->addr[i].info.session.sessionId); // //获取void setChannelId(Integer channelId)方法 // jmethodID setChannelIdMethod = (*env)->GetMethodID(env, sessionAddrClass, "setChannelId", "(I)V"); // //将device中的channelId调用方法设置到sessionAddrObj中 // (*env)->CallVoidMethod(env, sessionAddrObj, setChannelIdMethod, device->addr[i].info.session.channelId); // //获取void setType(String type)方法 // jmethodID setTypeMethod = (*env)->GetMethodID(env, sessionAddrClass, "setType", "(Ljava/lang/String;)V"); // //将device中的type调用方法设置到sessionAddrObj中 // jstring sessionTypeStr = (*env)->NewStringUTF(env, device->addr[i].info.session.type); // (*env)->CallVoidMethod(env, sessionAddrObj, setTypeMethod, sessionTypeStr); // jmethodID setSessionMethod = (*env)->GetMethodID(env, connectionAddrClass, "setSession", "(Lcom/jg/softbus/network/protocol/SessionAddr;)V"); // (*env)->CallVoidMethod(env, addrObj, setSessionMethod, sessionAddrObj); // (*env)->DeleteLocalRef(env, sessionTypeStr); // (*env)->DeleteLocalRef(env, sessionAddrObj); // printf("sessionId=%d, channelId=%d, type=%d", device->addr[i].info.session.sessionId, device->addr[i].info.session.channelId,device->addr[i].info.session.type); // break; default: break; } //获取ConnectionAddr中的void setPeerUid(String peerUid)方法,将device中的peerUid放入到addrObj中 jmethodID setPeerUidMethod = (*env)->GetMethodID(env, connectionAddrClass, "setPeerUid", "(Ljava/lang/String;)V"); jstring peerUidStr = (*env)->NewStringUTF(env, device->addr[i].peerUid); (*env)->CallVoidMethod(env, addrObj, setPeerUidMethod, peerUidStr); (*env)->DeleteLocalRef(env, peerUidStr); (*env)->SetObjectArrayElement(env, addrArray, i, addrObj); (*env)->DeleteLocalRef(env, addrObj); } //查找void setAddr(ConnectionAddr[] addr)方法并将addrArray对象设置到obj对象中 jmethodID setAddrMethod = (*env)->GetMethodID(env, deviceInfoClass, "setAddr", "([Lcom/jg/softbus/network/protocol/ConnectionAddr;)V"); (*env)->CallVoidMethod(env, obj, setAddrMethod, addrArray); (*env)->DeleteLocalRef(env, addrArray); //查找void setCapabilityBitmapNum(Integer capabilityBitmapNum)方法 jmethodID setCapabilityBitmapNumMethod = (*env)->GetMethodID(env, deviceInfoClass, "setCapabilityBitmapNum", "(I)V"); (*env)->CallVoidMethod(env, obj, setCapabilityBitmapNumMethod, device->capabilityBitmapNum); //查找void setCapabilityBitmap(String[] capabilityBitmap)方法 jmethodID setCapabilityBitmapMethod = (*env)->GetMethodID(env, deviceInfoClass, "setCapabilityBitmap", "([Ljava/lang/String;)V"); //构建jstring的数组对象,长度为addrNum的数值 jobjectArray sArray = (*env)->NewObjectArray(env, device->addrNum, (*env)->FindClass(env, "java/lang/String"), NULL); for (int i = 0; i < device->addrNum; i++) { char* cbitmap_str; sprintf(cbitmap_str, "0x%x", device->capabilityBitmap[i]); //将cbitmap_str放入到jstringArray中 jstring addrObj = (*env)->NewStringUTF(env, cbitmap_str); (*env)->SetObjectArrayElement(env, sArray, i, addrObj); (*env)->DeleteLocalRef(env, addrObj); printf("\t\tcapabilityBitmap[%d]=0x%x\n", i + 1, device->capabilityBitmap[i]); } (*env)->CallVoidMethod(env, obj, setCapabilityBitmapMethod, sArray); (*env)->DeleteLocalRef(env, sArray); //查找void setCustData(String custData)方法 jmethodID setCustDataMethod = (*env)->GetMethodID(env, deviceInfoClass, "setCustData", "(Ljava/lang/String;)V"); //获取device的custData放入到obj中 jstring custDataObj = (*env)->NewStringUTF(env, device->custData); (*env)->CallVoidMethod(env, obj, setCustDataMethod, custDataObj); (*env)->DeleteLocalRef(env, custDataObj); //获取void setRange(Integer range)方法 // jmethodID setRangeMethod = (*env)->GetMethodID(env, deviceInfoClass, "setRange", "(I)V"); // (*env)->CallVoidMethod(env, obj, setRangeMethod, device->range); } /** * 设备发现回调 */ void DeviceFound(const DeviceInfo *device) { // 获取JNIEnv环境 JNIEnv *env; // 将当前线程附加到Java虚拟机 (*jvm)->AttachCurrentThread(jvm, (void **)&env, NULL); // 获取当前对象的类引用 jclass nativeLibClass = (*env)->GetObjectClass(env, globalRef); // 获取当前对象的publishSuccess方法的ID jmethodID callbackMethod = (*env)->GetMethodID(env, nativeLibClass, "onDeviceFound", "(Lcom/jg/softbus/device/DeviceInfo;)V"); //转换DeviceInfo为java对应的对象 jobject deviceObj = DeviceInfoToJavaObject(env, device); if(deviceObj == NULL) { return; } //调用回调方法执行 (*env)->CallVoidMethod(env, globalRef, callbackMethod, deviceObj); //删除本地对象 (*env)->DeleteLocalRef(env, deviceObj); //将当前线程从java虚拟机中移除 (*jvm)->DetachCurrentThread(jvm); } /** * 发现成功回调 */ void DiscoverySuccess(int subscribeId) { // 获取JNIEnv环境 JNIEnv *env; // 将当前线程附加到Java虚拟机 (*jvm)->AttachCurrentThread(jvm, (void **)&env, NULL); // 获取当前对象的类引用 jclass nativeLibClass = (*env)->GetObjectClass(env, globalRef); // 获取当前对象的publishSuccess方法的ID jmethodID callbackMethod = (*env)->GetMethodID(env, nativeLibClass, "onDiscoverySuccess", "(I)V"); //调用回调方法执行 (*env)->CallVoidMethod(env, globalRef, callbackMethod, subscribeId); //将当前线程从java虚拟机中移除 (*jvm)->DetachCurrentThread(jvm); printf("CB: discover subscribeId=%d\n", subscribeId); } /** * 发现失败回调 */ void DiscoveryFailed(int subscribeId, DiscoveryFailReason reason) { // 获取JNIEnv环境 JNIEnv *env; // 将当前线程附加到Java虚拟机 (*jvm)->AttachCurrentThread(jvm, (void **)&env, NULL); // 获取当前对象的类引用 jclass nativeLibClass = (*env)->GetObjectClass(env, globalRef); // 获取当前对象的publishSuccess方法的ID jmethodID callbackMethod = (*env)->GetMethodID(env, nativeLibClass, "onDiscoverFailed", "(II)V"); // 调用当前对象的非静态方法 (*env)->CallVoidMethod(env, globalRef, callbackMethod, subscribeId, (int)reason); //将当前线程从java虚拟机中移除 (*jvm)->DetachCurrentThread(jvm); printf("CB: discover subscribeId=%d failed, reason=%d\n", subscribeId, (int)reason); } JNIEXPORT jint JNICALL Java_com_jg_softbus_naservice_SubscribeService_discoveryStart (JNIEnv *env, jobject obj, jstring pkgName, jobject subscribeInfo, jobject callback) { // 保存Java虚拟机的引用 (*env)->GetJavaVM(env, &jvm); globalRef = (*env)->NewGlobalRef(env, callback); const char *pkgNameStr = (*env)->GetStringUTFChars(env, pkgName, NULL); SubscribeInfo info; int ret = ParseSubscribeInfo(env, subscribeInfo, &info); if(ret != 0) { // 尝试进行一些可能会抛出异常的操作 jclass exceptionClass = (*env)->FindClass(env, "java/lang/Exception"); // 获取异常类 // 如果找不到异常类,则抛出异常 jmethodID exceptionConstructor = (*env)->GetMethodID(env, exceptionClass, "", "()V"); jthrowable exception = (*env)->NewObject(env,exceptionClass, exceptionConstructor); // 抛出异常 (*env)->ThrowNew(env, exceptionClass, "SubscribeInfo object error."); //解析失败无法继续操作 return -1; } IDiscoveryCallback cb = { .OnDeviceFound = DeviceFound, .OnDiscoverFailed = DiscoveryFailed, .OnDiscoverySuccess = DiscoverySuccess }; ret = StartDiscovery(pkgNameStr, &info, &cb); (*env)->ReleaseStringUTFChars(env, pkgName, pkgNameStr); return ret; } JNIEXPORT jint JNICALL Java_com_jg_softbus_naservice_SubscribeService_stopDiscovery (JNIEnv * env, jobject obj, jstring pkgName, jint subscribeId) { (*env)->GetJavaVM(env, &jvm); const char* pkgName_str = (*env)->GetStringUTFChars(env, pkgName, NULL); int ret = StopDiscovery(pkgName_str, subscribeId); if (ret) { // 尝试进行一些可能会抛出异常的操作 jclass exceptionClass = (*env)->FindClass(env, "java/lang/Exception"); // 获取异常类 // 如果找不到异常类,则抛出异常 jmethodID exceptionConstructor = (*env)->GetMethodID(env, exceptionClass, "", "()V"); jthrowable exception = (*env)->NewObject(env, exceptionClass, exceptionConstructor); // 抛出异常 (*env)->ThrowNew(env, exceptionClass, "stop discovery error."); printf("StopDiscovery fail:%d\n", ret); } printf("stop discover pkgName=%s, subscribeId=%d\n", pkgName_str, subscribeId); (*env)->ReleaseStringUTFChars(env, pkgName, pkgName_str); return ret; } static void discoverResult(int32_t refreshId, RefreshResult reason) { // 获取JNIEnv环境 JNIEnv *env; // 将当前线程附加到Java虚拟机 (*jvm)->AttachCurrentThread(jvm, (void **)&env, NULL); // 获取当前对象的类引用 jclass nativeLibClass = (*env)->GetObjectClass(env, globalRef); // 获取当前对象的publishSuccess方法的ID jmethodID callbackMethod = (*env)->GetMethodID(env, nativeLibClass, "onDiscoverResult", "(II)V"); // 调用当前对象的非静态方法 (*env)->CallVoidMethod(env, globalRef, callbackMethod, refreshId, (int)reason); // 将当前线程从Java虚拟机分离 (*jvm)->DetachCurrentThread(jvm); printf("CB: discover subscribeId=%d failed, reason=%d\n", refreshId, (int)reason); } JNIEXPORT jint JNICALL Java_com_jg_softbus_naservice_SubscribeService_refreshLNN (JNIEnv *env, jobject obj, jstring pkgName, jobject subscribeInfo, jobject callback){ // 保存Java虚拟机的引用 (*env)->GetJavaVM(env, &jvm); globalRef = (*env)->NewGlobalRef(env, callback); const char *pkgNameStr = (*env)->GetStringUTFChars(env, pkgName, NULL); SubscribeInfo info; int ret = ParseSubscribeInfo(env, subscribeInfo, &info); if(ret != 0) { // 尝试进行一些可能会抛出异常的操作 jclass exceptionClass = (*env)->FindClass(env, "java/lang/Exception"); // 获取异常类 // 如果找不到异常类,则抛出异常 jmethodID exceptionConstructor = (*env)->GetMethodID(env, exceptionClass, "", "()V"); jthrowable exception = (*env)->NewObject(env, exceptionClass, exceptionConstructor); // 抛出异常 (*env)->ThrowNew(env, exceptionClass, "SubscribeInfo object error."); //解析失败无法继续操作 return -1; } IRefreshCallback cb = { .OnDeviceFound = DeviceFound, .OnDiscoverResult = discoverResult, }; ret = RefreshLNN(pkgNameStr, &info, &cb); (*env)->ReleaseStringUTFChars(env, pkgName, pkgNameStr); return ret; } JNIEXPORT jint JNICALL Java_com_jg_softbus_naservice_SubscribeService_stopRefreshLNN (JNIEnv * env, jobject obj, jstring pkgName, jint refreshId) { // 保存Java虚拟机的引用 (*env)->GetJavaVM(env, &jvm); const char* pkgNameStr = (*env)->GetStringUTFChars(env, pkgName, NULL); // 停止刷新LNN int ret = StopRefreshLNN(pkgNameStr, refreshId); if (ret) { // 尝试进行一些可能会抛出异常的操作 jclass exceptionClass = (*env)->FindClass(env, "java/lang/Exception"); // 获取异常类 // 如果找不到异常类,则抛出异常 jmethodID exceptionConstructor = (*env)->GetMethodID(env, exceptionClass, "", "()V"); jthrowable exception = (*env)->NewObject(env, exceptionClass, exceptionConstructor); // 抛出异常 (*env)->ThrowNew(env, exceptionClass, "stop refreshLNN error."); printf("stop refreshLNN fail:%d\n", ret); } // 释放pkgNameStr (*env)->ReleaseStringUTFChars(env, pkgName, pkgNameStr); return ret; } JNIEXPORT jobjectArray JNICALL Java_com_jg_softbus_naservice_SubscribeService_findDeviceNodes (JNIEnv *env, jobject obj, jstring pkgName) { // 保存Java虚拟机的引用 (*env)->GetJavaVM(env, &jvm); const char* pkgNameStr = (*env)->GetStringUTFChars(env, pkgName, NULL); NodeBasicInfo **dev = NULL; int ret, num; ret = GetAllNodeDeviceInfo(pkgNameStr, dev, &num); if (ret) { // 尝试进行一些可能会抛出异常的操作 jclass exceptionClass = (*env)->FindClass(env, "java/lang/Exception"); // 获取异常类 // 如果找不到异常类,则抛出异常 jmethodID exceptionConstructor = (*env)->GetMethodID(env, exceptionClass, "", "()V"); jthrowable exception = (*env)->NewObject(env, exceptionClass, exceptionConstructor); // 抛出异常 (*env)->ThrowNew(env, exceptionClass, "get online device error."); printf("GetAllNodeDeviceInfo fail:%d\n", ret); return NULL; } jclass nodeClass = (*env)->FindClass(env, "com/jg/softbus/network/node/NodeBasicInfo"); // 获取构造函数 jmethodID nodeConstructor = (*env)->GetMethodID(env, nodeClass, "", "(Ljava/lang/String;Ljava/lang/String;S)V"); jobjectArray json_nodes = (*env)->NewObjectArray(env, num, nodeClass, NULL); printf("return %d Node\n", num); for (int i = 0; i < num; i++) { jstring networkId = (*env)->NewStringUTF(env, dev[i]->networkId); jstring deviceName = (*env)->NewStringUTF(env, dev[i]->deviceName); //构造node对象 jobject node = (*env)->NewObject(env, nodeClass, nodeConstructor, networkId, deviceName, dev[i]->deviceTypeId); (*env)->SetObjectArrayElement(env, json_nodes, i, node); //释放字符串资源 (*env)->DeleteLocalRef(env, networkId); (*env)->DeleteLocalRef(env, deviceName); (*env)->DeleteLocalRef(env, node); printf("deviceName=%s\n", i + 1, dev[i]->deviceName); printf("\tnetworkId=%s\n", dev[i]->networkId); printf("\tdeviceTypeId=%d\n", dev[i]->deviceTypeId); } // 释放pkgNameStr (*env)->ReleaseStringUTFChars(env, pkgName, pkgNameStr); return json_nodes; } JNIEXPORT void JNICALL Java_com_jg_softbus_naservice_SubscribeService_releaseDeviceNodes (JNIEnv *env, jobject obj, jobjectArray nodes) { // 保存Java虚拟机的引用 (*env)->GetJavaVM(env, &jvm); // 释放创建的节点集合对象 (*env)->DeleteLocalRef(env, nodes); } JNIEXPORT void JNICALL Java_com_jg_softbus_naservice_SubscribeService_destroy (JNIEnv *env, jobject obj) { printf("[subscribe]destory the subscribe data.\r\n"); // 删除全局引用 (*env)->DeleteGlobalRef(env, globalRef); printf("[subscribe]globalRef have been destory.\r\n"); // if(jvm != NULL) { // free(jvm); // printf("[subscribe]jvm have been destory.\r\n"); // } }