本文主要说明了在Android应用程序中,怎么使用jni交互.
包括:回调接口,获取对象,不同线程汇总怎么使用JNIEnv *env等实例.
在jni中,用jfieldID和jmethodID来表示Java类的成员变量和成员函数.
比如:我们的jni侧要获取java对象中的某个String. java代码精简如下:
class InstanceFieldAccess {
private String text;
private native void accessField();
public static void main(String args[]) {
InstanceFieldAccess ifa = new InstanceFieldAccess();
ifa.text = "abcdefg";
ifa.accessField();
System.out.println("Java output");
System.out.println(" ifa.text = \"" + ifa.text + "\"");
}
static {
System.loadLibrary("InstanceFieldAccess");
}
}
c++代码精简如下:
JNIEXPORT void JNICALL Java_InstanceFieldAccess_accessField(JNIEnv *env, jobject obj)
{
jfieldID fid; //字段id,在jni中对应着java的类成员变量
jstring jstr; //jstring类型,对应的java中的String
const char *str;
//第一步,我们获取类对象,因为是非静态方法所以是object
jclass cls = (*env)->GetObjectClass(env, obj);
printf("C output:\n");
//第二步,通过jni函数表,获取类对象里面的成员变量.
fid = (*env)->GetFieldID(env, cls, "text", "Ljava/lang/String;");
if (fid == NULL) {
return; //如果是空的,那就是没有找到,返回.
}
//第三步,找到了字段id,那么就开始读取值.因为字符串是个特殊的对象,所以这里使用GetObjectField读取.
jstr = (*env)->GetObjectField(env, obj, fid);
//第四步,读取到了String值因为 Java 默认使用 Unicode 编码,而 C/C++ 默认使用 UTF 编码,所以在本地代码中操作字符串的时候,必
//须使用合适的 JNI 函数把 jstring 转换成 C 风格的字符串
str = (*env)->GetStringUTFChars(env, jstr, NULL);
if (str == NULL) {
return; //调用完 GetStringUTFChars 之后不要忘记安全检查,因为 JVM 需要为新诞生的字符串分配内存空间,当内存
//空间不够分配的时候,会导致调用失败,失败后 GetStringUTFChars 会返回 NULL,并抛出一个OutOfMemoryError 异常
}
printf(" c.s = \"%s\"\n", str);
//在调用 GetStringUTFChars 函数从 JVM 内部获取一个字符串之后,JVM 内部会分配一块新的内存,用于存
//储源字符串的拷贝,以便本地代码访问和修改。即然有内存分配,用完之后就可以马上释放了.
(*env)->ReleaseStringUTFChars(env, jstr, str);
//通过调用 NewStringUTF 函数,会构建一个新的 java.lang.String 字符串对象。这个新创建的字符串会自动转换成Java支持的Unicode编码
jstr = (*env)->NewStringUTF(env, "123");
if (jstr == NULL) {
return; /* out of memory */
}
//通过jni函数表,给java对象的变量赋值
(*env)->SetObjectField(env, obj, fid, jstr);
}
//打印
/**
C output:
c.s = "abc"
Java output:
ifa.text = "123"
*/
public interface IWifiStaServiceService {
// methods
public ActivateOutput activate();
public AddApOutput addAp(WifiConfiguration wifiConfiguration);
public ConnectOutput connect(WifiConfiguration wifiConfiguration);
public DeactivateOutput deactivate();
public DisconnectOutput disconnect();
public ForgetOutput forget(WifiApID wifiApID);
public GetApListOutput getApList();
public GetConfiguredApListOutput getConfiguredApList();
public GetConnectedApOutput getConnectedAp();
public GetConnectionInfoOutput getConnectionInfo();
public GetMacAddressOutput getMacAddress();
public IsActivatedOutput isActivated();
public ScanOutput scan();
public UpdateApOutput updateAp(WifiConfiguration wifiConfiguration);
// fields
}
public class WifiStaServiceServiceStub {
public static final String LOG_TAG = "WifiStaServiceServiceStub";
public static final String INSTANCE_NAME_1 = "WifiStaService_Provider/WifiStaService_ProviderRootSwc/WifiStaService1";
private static final int METHOD_ACTIVATE = 0;
private static final int METHOD_ADDAP = 1;
private static final int METHOD_CONNECT = 2;
private static final int METHOD_DEACTIVATE = 3;
private static final int METHOD_DISCONNECT = 4;
private static final int METHOD_FORGET = 5;
private static final int METHOD_GETAPLIST = 6;
private static final int METHOD_GETCONFIGUREDAPLIST = 7;
private static final int METHOD_GETCONNECTEDAP = 8;
private static final int METHOD_GETCONNECTIONINFO = 9;
private static final int METHOD_GETMACADDRESS = 10;
private static final int METHOD_ISACTIVATED = 11;
private static final int METHOD_SCAN = 12;
private static final int METHOD_UPDATEAP = 13;
private static IWifiStaServiceService mService;
//我们这里定义的都是静态类型的native方法,注意cpp里面对应的头文件
private static native void native_init(String ap_env);
private static native void native_setup(Object object, String instance);
private static native void native_finalize();
private static native void native_sendService();
private static native void native_stopSendService();
private static native void native_notifyRssiChanged(byte[] data);
private static native void native_notifyScanFinished(byte[] data);
private static native void native_notifyStaConnChanged(byte[] data);
private static native void native_notifyStationChanged(byte[] data);
static {
try {
System.loadLibrary("wifistaservice");
Log.d(LOG_TAG, "load wifistaservice");
} catch (Exception ex) {
Log.e(LOG_TAG, "System.loadLibrary Exception " + ex);
} catch (Error err) {
Log.e(LOG_TAG, "System.loadLibrary Error " + err);
}
}
//构造方法里面调用了2个native方法
public WifiStaServiceServiceStub(IWifiStaServiceService service, String instance, String ap_env) {
Log.d(LOG_TAG, "new WifiStaServiceServiceStub");
native_init(ap_env);//参数只传递了一个String
mService = service;
native_setup(new WeakReference<WifiStaServiceServiceStub>(this), instance);//参数传递了一个软引用的对象和一个String
}
protected void finalize() {
native_finalize();
}
public void sendService() {
native_sendService();
}
public void stopSendService() {
native_stopSendService();
}
public void notifyRssiChanged(WifiAp rssiChanged) {
Log.d(LOG_TAG, "native_notifyRssiChanged");
native_notifyRssiChanged(rssiChanged.toByteArray());
}
public void notifyScanFinished(WifiApList scanFinished) {
Log.d(LOG_TAG, "native_notifyScanFinished");
native_notifyScanFinished(scanFinished.toByteArray());
}
public void notifyStaConnChanged(WifiAp staConnChanged) {
Log.d(LOG_TAG, "native_notifyStaConnChanged");
native_notifyStaConnChanged(staConnChanged.toByteArray());
}
public void notifyStationChanged(int stationChanged) {
Log.d(LOG_TAG, "native_notifyStationChanged");
WifiStaServiceProto.ProtoUint8 proto_stationChanged = new WifiStaServiceProto.ProtoUint8();
proto_stationChanged.value = stationChanged;
native_notifyStationChanged(proto_stationChanged.toByteArray(proto_stationChanged));
}
//静态的java方法,这个方法会在native侧调用.注意关注三个参数
private static byte[] postEventFromNative(Object Control_ref, int what, byte[] obj) {
//获取类对象
final WifiStaServiceServiceStub serviceimpl = (WifiStaServiceServiceStub)((WeakReference)Control_ref).get();
//因为是从jni那边从来的,也就验证了底层有没有拿到这个对象
if (serviceimpl == null) {
Log.e(LOG_TAG, "postEventFromNative error : service is null");
return null;
}
Log.d(LOG_TAG, "postEventFromNative what= " + what + " obj= " + obj);
switch (what) {
case METHOD_ACTIVATE:
ActivateOutput ret_activate = mService.activate();
if (ret_activate != null) {
return ret_activate.toByteArray();
}
break;
case METHOD_ADDAP:
if (obj != null) {
try {
WifiStaServiceProto.AddApInput in_addAp = WifiStaServiceProto.AddApInput.parseFrom(obj);
AddApOutput ret_addAp = mService.addAp(WifiConfiguration.fromByteArray(WifiStaServiceProto.WifiConfiguration.toByteArray(in_addAp.wifiConfiguration)));
if (ret_addAp != null) {
Log.d(LOG_TAG, "AddApOutput is not null ");
return ret_addAp.toByteArray();
} else {
Log.d(LOG_TAG, "AddApOutput is null ");
}
} catch (com.google.protobuf.nano.InvalidProtocolBufferNanoException e) {
Log.d(LOG_TAG, e.toString());
}
}
break;
case METHOD_CONNECT:
if (obj != null) {
try {
WifiStaServiceProto.ConnectInput in_connect = WifiStaServiceProto.ConnectInput.parseFrom(obj);
ConnectOutput ret_connect = mService.connect(WifiConfiguration.fromByteArray(WifiStaServiceProto.WifiConfiguration.toByteArray(in_connect.wifiConfiguration)));
if (ret_connect != null) {
Log.d(LOG_TAG, "ConnectOutput is not null ");
return ret_connect.toByteArray();
} else {
Log.d(LOG_TAG, "ConnectOutput is null ");
}
} catch (com.google.protobuf.nano.InvalidProtocolBufferNanoException e) {
Log.d(LOG_TAG, e.toString());
}
}
break;
default:
break;
}
return null;
}
}
头文件定义了java代码对应的native方法,以及一个回调类.主要是用来回调java侧代码的postEventFromNative方法.
#ifndef _Included_com_yf_soa_wifistaservice_WifiStaServiceNativeListener
#define _Included_com_yf_soa_wifistaservice_WifiStaServiceNativeListener
#include
#include "WifiStaServiceNativeListener.h"
#include "wifistaservice/wifistaservice_skeleton.h"
#ifdef __cplusplus
extern "C" {
#endif
namespace yf {
namespace soa {
struct fields_t {
jfieldID context;
jmethodID post_event;//方法 ID(因为一个类中会存在多个方法,需要一个唯一标识来确定调用类中的哪个方法)
};
/*
* Class: com_yf_soa_wifistaservice_WifiStaServiceServiceStub 对应java代码的类对象包名
* Method: native_init java类对象方法native名
* Signature: ()V 方法和参数签名
*/
JNIEXPORT void JNICALL Java_com_yf_soa_wifistaservice_WifiStaServiceServiceStub_native_1init
(JNIEnv *, jclass, jstring);
/*
* Class: com_yf_soa_wifistaservice_WifiStaServiceServiceStub
* Method: native_setup
* Signature: (Ljava/lang/Object;)V
*/
JNIEXPORT void JNICALL Java_com_yf_soa_wifistaservice_WifiStaServiceServiceStub_native_1setup
(JNIEnv *, jclass, jobject, jstring);
/*
* Class: com_yf_soa_wifistaservice_WifiStaServiceServiceStub
* Method: native_finalize
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_yf_soa_wifistaservice_WifiStaServiceServiceStub_native_1finalize
(JNIEnv *, jclass);
/*
* Class: com_yf_soa_wifistaservice_WifiStaServiceServiceStub
* Method: native_offerService
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_yf_soa_wifistaservice_WifiStaServiceServiceStub_native_1offerService
(JNIEnv *, jclass);
/*
* Class: com_yf_soa_wifistaservice_WifiStaServiceServiceStub
* Method: native_stopOfferService
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_yf_soa_wifistaservice_WifiStaServiceServiceStub_native_1stopOfferService
(JNIEnv *, jclass);
/*
* Class: com_yf_soa_wifistaservice_WifiStaServiceServiceStub
* Method: native_notifyRssiChanged
* Signature: (Lcom/yf/soa/wifistaservice/WifiAp;)V
*/
JNIEXPORT void JNICALL Java_com_yf_soa_wifistaservice_WifiStaServiceServiceStub_native_1notifyRssiChanged
(JNIEnv *, jclass, jbyteArray);
/*
* Class: com_yf_soa_wifistaservice_WifiStaServiceServiceStub
* Method: native_notifyScanFinished
* Signature: (Lcom/yf/soa/wifistaservice/WifiApList;)V
*/
JNIEXPORT void JNICALL Java_com_yf_soa_wifistaservice_WifiStaServiceServiceStub_native_1notifyScanFinished
(JNIEnv *, jclass, jbyteArray);
/*
* Class: com_yf_soa_wifistaservice_WifiStaServiceServiceStub
* Method: native_notifyStaConnChanged
* Signature: (Lcom/yf/soa/wifistaservice/WifiAp;)V
*/
JNIEXPORT void JNICALL Java_com_yf_soa_wifistaservice_WifiStaServiceServiceStub_native_1notifyStaConnChanged
(JNIEnv *, jclass, jbyteArray);
/*
* Class: com_yf_soa_wifistaservice_WifiStaServiceServiceStub
* Method: native_notifyStationChanged
* Signature: (Lcom/yf/soa/wifistaservice/StationState_ref;)V
*/
JNIEXPORT void JNICALL Java_com_yf_soa_wifistaservice_WifiStaServiceServiceStub_native_1notifyStationChanged
(JNIEnv *, jclass, jbyteArray);
class WifiStaServiceNativeListenerImpl: public WifiStaServiceNativeListener {
public:
//参数包含jni指针,和2个object对象
WifiStaServiceNativeListenerImpl(JNIEnv* env, jobject thiz, jobject weak_thiz);
~WifiStaServiceNativeListenerImpl();
virtual void syncDetachCurrentThread();
virtual jbyteArray notify(JNIEnv *env, int msg, const jbyteArray obj);//通知
private://定义两个全局对象
jclass mClass;//从classpath路径下搜索ClassMethod这个类,并返回该类的Class对象
jobject mObject;//类的实例
};
class WifiStaServiceNative : public yf::platform::WifiStaServiceSkeleton {
public:
virtual ~WifiStaServiceNative();
static WifiStaServiceNative& instantiate() {
static WifiStaServiceNative elmn;
return elmn;
}
//注册listener对象
virtual void registerListener(const std::shared_ptr<WifiStaServiceNativeListener> listener);
virtual sovpap::core::Future<nm_wifistaservice::internal::methods::Activate::Output> Activate();
virtual sovpap::core::Future<nm_wifistaservice::internal::methods::AddAp::Output> AddAp(const DataTypes::WifiConfiguration& wifiConfiguration);
virtual sovpap::core::Future<nm_wifistaservice::internal::methods::Connect::Output> Connect(const DataTypes::WifiConfiguration& wifiConfiguration);
void notifyRssiChanged(const DataTypes::WifiAp& rssiChanged);
void notifyScanFinished(const DataTypes::WifiApList& scanFinished);
void notifyStaConnChanged(const DataTypes::WifiAp& staConnChanged);
void notifyStationChanged(const DataTypes::StationState_ref& stationChanged);
private:
explicit WifiStaServiceNative();
WifiStaServiceNative& operator = (const WifiStaServiceNative&)=delete;
std::shared_ptr<WifiStaServiceNativeListener> m_listener;
enum notifyType {
METHOD_ACTIVATE,
METHOD_ADDAP,
METHOD_CONNECT
};
};
} // namespace soa
} // namespace yf
#ifdef __cplusplus
}
#endif
#endif // _Included_com_yf_soa_wifistaservice_WifiStaServiceNativeListener
看一下另一个回调函数的头文件
#ifndef WIFISTASERVICENATIVELISTENER_H
#define WIFISTASERVICENATIVELISTENER_H
#include
using namespace android;
#ifndef __cplusplus
# error ERROR: This file requires C++ compilation (use a .cpp suffix)
#endif
namespace yf {
namespace soa {
class WifiStaServiceNativeListener
{
public:
virtual void syncDetachCurrentThread() = 0;
virtual jbyteArray notify(JNIEnv *env, int msg, const jbyteArray obj) = 0;
virtual ~WifiStaServiceNativeListener(){};
};
} // namespace soa
} // namespace yf
#endif // WIFISTASERVICENATIVELISTENER_H
通过JNIEnv我们可以获取一个Java虚拟机对象,其函数如下:
jint GetJavaVM(JNIEnv *env, JavaVM **vm);
- vm:用来存放获得的虚拟机的指针的指针。
- return:成功返回0,失败返回其他。
JNIEnv指针仅在创建它的线程有效。如果我们需要在其他线程访问JVM,那么必须先调用
AttachCurrentThread
将当前线程与JVM进行关联,然后才能获得JNIEnv对象。当然,我们在必要时需要调用DetachCurrentThread
来解除链接。jint AttachCurrentThread(JavaVM* vm , JNIEnv** env , JavaVMAttachArgs* args);
- vm:虚拟机对象指针。
- env:用来保存得到的JNIEnv的指针。
- args:链接参数,参数结构体如下所示。
- return:链接成功返回0,连接失败返回其他。
#include
#include
#include
#include
#include "WifiStaServiceServiceJni.h"
#include
#include "ara/core/promise.h"
#include "ara/core/initialization.h"
#ifdef LOG_TAG
#undef LOG_TAG
#endif
#define LOG_TAG "WifiStaServiceServiceJni"
#ifdef __cplusplus
extern "C" {
#endif
namespace yf {
namespace soa {
std::string g_instance_name;
static fields_t fields;
static pthread_key_t sThreadKey;
static JavaVM* javaVM;
static android::Mutex sJNIEnvLock;
jobject g_WifiStaServiceServiceStubClass;
static JNIEnv *getJNIEnv() {
android::Mutex::Autolock l(sJNIEnvLock);//加锁,防止多线程获取不同步
ALOGD("[%s:%d][%s]", __FUNCTION__, __LINE__, __FILE__);
if (javaVM == NULL) {
ALOGE("[%s:%d][%s] Java VM is NULL", __FUNCTION__, __LINE__, __FILE__);
return NULL;
}
JNIEnv *envnow = NULL;
int status = javaVM->GetEnv((void **)&envnow, JNI_VERSION_1_6);
ALOGD("[%s:%d][%s] GetEnv::status = [%d]", __FUNCTION__, __LINE__, __FILE__, status);
if (status == JNI_EDETACHED) {
if( 0 <= javaVM->AttachCurrentThread(&envnow, NULL)) {
ALOGD("[%s:%d][%s] AttachCurrentThread::status = [%d]", __FUNCTION__, __LINE__, __FILE__, status);
/**
* use that key with pthread_setspecific to store JNIEnv in thead-local-storage.
* In that, it'll be passed into your destructor as the argument.
*
*/
if (NULL == pthread_getspecific(sThreadKey)) {
pthread_setspecific(sThreadKey, &envnow);
}
}
}
return envnow;
}
/*
* Class: com_yf_soa_wifistaservice_WifiStaServiceServiceStub
* Method: native_init
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_yf_soa_wifistaservice_WifiStaServiceServiceStub_native_1init
(JNIEnv * env, jclass clazz, jstring ap_env) {
ALOGD("=================== JNI call native_init ========================");
//从classpath路径下搜索ClassMethod这个类,并返回该类的Class对象
jclass jcls = env->FindClass("com/yf/soa/wifistaservice/WifiStaServiceServiceStub");
//调用 NewGlobalRef 基于局部引用创建,会阻GC回收所引用的对象。可以跨方法、跨线程使用。JVM不会自
//动释放,必须调用DeleteGlobalRef手动释放。 (*env)->DeleteGlobalRef(env,g_cls_string)
g_WifiStaServiceServiceStubClass = env->NewGlobalRef(jcls);
//将方法id保存在结构体中的jmethodid中
fields.post_event = env->GetStaticMethodID(jcls, "postEventFromNative", "(Ljava/lang/Object;I[B)[B");
//获取全局的javavm
env->GetJavaVM(&javaVM);
if (fields.post_event == NULL) {
ALOGD("JNI_native_init fields.post_event is null");
return;
}
if (getenv("AA_CONFIG_FILES_PATH")) {
ALOGD("env already setted, AA_CONFIG_FILES_PATH: %s", getenv("AA_CONFIG_FILES_PATH"));
} else {
if (ap_env) {
const char *jap_env = env->GetStringUTFChars(ap_env, NULL);
if (0 != setenv("AA_CONFIG_FILES_PATH", jap_env, 1)) {
ALOGE("setenv error ");
}
if (!ara::core::Initialize().HasValue()) {
ALOGE("ara::core::init error ");
ara::core::Abort("ara::core::Initialize() failed for Service, calling abort...");
}
} else {
ALOGE("native_init without ap env set up");
}
}
}
/*
* Class: com_yf_soa_wifistaservice_WifiStaServiceServiceStub
* Method: native_setup
* Signature: (Ljava/lang/Object;)V
*/
JNIEXPORT void JNICALL Java_com_yf_soa_wifistaservice_WifiStaServiceServiceStub_native_1setup
(JNIEnv *env, jclass clazz, jobject weak_this, jstring instance) {
ALOGD("=================== JNI call native_setup ========================");
//新建监听器对象
std::shared_ptr<WifiStaServiceNativeListenerImpl> listener = std::make_shared<WifiStaServiceNativeListenerImpl>(env, clazz, weak_this);
ALOGD("=================== JNI call native_setup new WifiStaServiceNativeListenerImpl ok========================");
g_instance_name = std::string(env->GetStringUTFChars(instance, NULL));
//注册监听回调,这样就能收到其他库的回调监听了.
WifiStaServiceNative::instantiate().registerListener(listener);
}
/*
* Class: com_yf_soa_wifistaservice_WifiStaServiceServiceStub
* Method: native_finalize
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_yf_soa_wifistaservice_WifiStaServiceServiceStub_native_1finalize
(JNIEnv * env, jclass clazz) {
ALOGD("=================== JNI call native_finalize ========================");
}
/*
* Class: com_yf_soa_wifistaservice_WifiStaServiceServiceStub
* Method: native_offerService
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_yf_soa_wifistaservice_WifiStaServiceServiceStub_native_1sendService
(JNIEnv *, jclass) {
ALOGD("=================== JNI call native_offerService ========================");
WifiStaServiceNative::instantiate().OfferService();
}
/*
* Class: com_yf_soa_wifistaservice_WifiStaServiceServiceStub
* Method: native_stopOfferService
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_yf_soa_wifistaservice_WifiStaServiceServiceStub_native_1stopSendService
(JNIEnv *, jclass) {
ALOGD("=================== JNI call native_stopOfferService ========================");
WifiStaServiceNative::instantiate().StopOfferService();
}
/*
* Class: com_yf_soa_wifistaservice_WifiStaServiceServiceStub
* Method: native_notifyRssiChanged
* Signature: (Lcom/yf/soa/wifistaservice/WifiAp;)V
* 通知wifi信号的方法,java侧会将数据传到jni侧.
*/
JNIEXPORT void JNICALL Java_com_yf_soa_wifistaservice_WifiStaServiceServiceStub_native_1notifyRssiChanged
(JNIEnv *env, jclass clazz, jbyteArray jrssichanged) {
ALOGD("=================== JNI call native_notifyRssiChanged ========================");
DataTypes::WifiAp arxml_rssiChanged;
DataTransfer::WifiAp transfer_rssichanged;
::com::yf::soa::wifistaservice::WifiAp proto_rssichanged;
if (jrssichanged) {
//下面的逻辑就是通过byte数组,然后通过google的protobuf转换传给其他的需要者
jbyte *data = env->GetByteArrayElements(jrssichanged, 0);
int data_len = env->GetArrayLength(jrssichanged);
proto_rssichanged.ParseFromArray(data, data_len);
env->ReleaseByteArrayElements(jrssichanged, data, 0);
transfer_rssichanged.fromProto(proto_rssichanged).toArxml(arxml_rssiChanged);
}
WifiStaServiceNative::instantiate().notifyRssiChanged(arxml_rssiChanged);
}
//实现WifiStaServiceNativeListenerImpl类,构造函数
WifiStaServiceNativeListenerImpl::WifiStaServiceNativeListenerImpl(JNIEnv* env, jobject thiz, jobject weak_thiz) {
ALOGD("WifiStaServiceNativeListenerImpl::WifiStaServiceNativeListenerImpl");
//这个地方我们看到是一个本地的jclass,主要是用来判断是否为空.由上面的native_setup函数传参
//thiz是代表静态的native_setup方法.weak_thiz代表java侧的接口IWifiStaServiceService
jclass clazz = env->GetObjectClass(thiz);
if (clazz == NULL) {
return;
}
//获取在init函数保存的全局passclassload 路径对象
mClass = (jclass)g_WifiStaServiceServiceStubClass;
//保存全局的java侧对象的类实例
mObject = env->NewGlobalRef(weak_thiz);
}
//析构函数做一些释放的操作,比如我们保存的一些全局引用
WifiStaServiceNativeListenerImpl::~WifiStaServiceNativeListenerImpl() {
ALOGD("WifiStaServiceNativeListenerImpl::~WifiStaServiceNativeListenerImpl");
JNIEnv *env = getJNIEnv();
if (NULL == env) {
return;
}
env->DeleteGlobalRef(mObject);
env->DeleteGlobalRef(mClass);
syncDetachCurrentThread();
}
//注册回调后,在notify会收到其他c++程序发来的消息,这个消息我们需要转发到java侧.看看怎么做.
jbyteArray WifiStaServiceNativeListenerImpl::notify(JNIEnv* env, int msg, const jbyteArray obj) {
ALOGD("WifiStaServiceNativeListenerImpl::notify");
//具体的数据,这里是字节数组
jbyteArray retobj = nullptr;
if (NULL == env) {
ALOGW("ERROR: JNIEnv is NULL LINE");
return retobj;
}
//如果说在native_init里面保存的java方法postEventFromNative id号是空的,那就是有问题,直接return
if (NULL == fields.post_event) {
ALOGW("notify fields.post_event is NULL");
return retobj;
}
ALOGW("notify msg %d", msg);
//没有问题的话,就调用java的postEventFromNative方法进行回调.首先Java postEventFromNative方法是个静态static的,
//所以调用CallStaticObjectMethod
//1.mClass是代表这个java的类对象路径com/yf/soa/wifistaservice/WifiStaServiceServiceStub
//2.fields.post_event是保存着对象WifiStaServiceServiceStub里面postEventFromNative对象id
//3.mObject是实例化WifiStaServiceServiceStub类
//4.msg是消息type
//5.obj每个消息type都会有自己的数据
//6.java侧通过postEventFromNative方法返回的数据,jni侧获取到
retobj = (jbyteArray)env->CallStaticObjectMethod(mClass, fields.post_event, mObject, msg, obj);
return retobj;
}
void WifiStaServiceNativeListenerImpl::syncDetachCurrentThread() {
// ALOGD("syncDetachCurrentThread");
// android::Mutex::Autolock l(sJNIEnvLock);
// javaVM->DetachCurrentThread();
}
WifiStaServiceNative::WifiStaServiceNative()
: yf::platform::WifiStaServiceSkeleton(ara::core::InstanceSpecifier(ara::core::StringView(g_instance_name.c_str(), g_instance_name.size())))
{
ALOGD("WifiStaServiceNative::WifiStaServiceNative");
}
WifiStaServiceNative::~WifiStaServiceNative() {
ALOGD("WifiStaServiceNative::~WifiStaServiceNative");
}
void WifiStaServiceNative::registerListener(const std::shared_ptr<WifiStaServiceNativeListener> listener) {
ALOGD("WifiStaServiceNative::registerListener");
m_listener = listener;
}
sovpap::core::Future<nm_wifistaservice::internal::methods::Activate::Output> WifiStaServiceNative::Activate() {
ara::core::Promise<nm_wifistaservice::internal::methods::Activate::Output> prom;
DataTransfer::ActivateOutput dataTransferOutput;
::com::yf::soa::wifistaservice::ActivateOutput protoOutput;
nm_wifistaservice::internal::methods::Activate::Output arxmlOutput;
//获取jni函数表,可用于多线程
JNIEnv *env = getJNIEnv();
//不同的type,调用notify函数获取java侧返回的数据
jbyteArray jOutput = m_listener->notify(env, METHOD_ACTIVATE, nullptr);
if (jOutput) {
jbyte *data = env->GetByteArrayElements(jOutput, 0);
int data_len = env->GetArrayLength(jOutput);
protoOutput.ParseFromArray(data, data_len);
env->ReleaseByteArrayElements(jOutput, data, 0);
dataTransferOutput.fromProto(protoOutput).toArxml(arxmlOutput);
} else {
ALOGE("%s notify ret obj is null", __FUNCTION__);
}
m_listener->syncDetachCurrentThread();
prom.set_value(std::move(arxmlOutput));
return prom.get_future();
}
sovpap::core::Future<nm_wifistaservice::internal::methods::AddAp::Output> WifiStaServiceNative::AddAp(const DataTypes::WifiConfiguration& wifiConfiguration) {
ara::core::Promise<nm_wifistaservice::internal::methods::AddAp::Output> prom;
DataTransfer::AddApInput dataTransferInput;
DataTransfer::AddApOutput dataTransferOutput;
::com::yf::soa::wifistaservice::AddApInput protoInput;
::com::yf::soa::wifistaservice::AddApOutput protoOutput;
nm_wifistaservice::internal::methods::AddAp::Input arxmlInput;
nm_wifistaservice::internal::methods::AddAp::Output arxmlOutput;
JNIEnv *env = getJNIEnv();
arxmlInput.WifiConfiguration = wifiConfiguration;
dataTransferInput.fromArxml(arxmlInput).toProto(protoInput);
jbyteArray jInput = env->NewByteArray(protoInput.ByteSize());
jbyte *pInput = env->GetByteArrayElements(jInput, NULL);
protoInput.SerializeToArray(pInput, protoInput.ByteSize());
env->ReleaseByteArrayElements(jInput, pInput, 0);
jbyteArray jOutput = m_listener->notify(env, METHOD_ADDAP, jInput);
if (jOutput) {
jbyte *data = env->GetByteArrayElements(jOutput, 0);
int data_len = env->GetArrayLength(jOutput);
protoOutput.ParseFromArray(data, data_len);
env->ReleaseByteArrayElements(jOutput, data, 0);
dataTransferOutput.fromProto(protoOutput).toArxml(arxmlOutput);
} else {
ALOGE("%s notify ret obj is null", __FUNCTION__);
}
m_listener->syncDetachCurrentThread();
prom.set_value(std::move(arxmlOutput));
return prom.get_future();
}
void WifiStaServiceNative::notifyRssiChanged(const DataTypes::WifiAp& _rssiChanged) {
RssiChanged.Send(_rssiChanged);
}
void WifiStaServiceNative::notifyScanFinished(const DataTypes::WifiApList& _scanFinished) {
ScanFinished.Send(_scanFinished);
}
void WifiStaServiceNative::notifyStaConnChanged(const DataTypes::WifiAp& _staConnChanged) {
StaConnChanged.Send(_staConnChanged);
}
void WifiStaServiceNative::notifyStationChanged(const DataTypes::StationState_ref& _stationChanged) {
StationChanged.Send(_stationChanged);
}
} // namespace soa
} // namespace yf
#ifdef __cplusplus
}
#endif
• 调用 GetObjectClass 函数获取实例对象的 Class 引用
• 调用 GetFieldID 函数获取 Class 引用中某个实例变量的 ID
• 调用 GetXXXField 函数获取变量的值,需要传入实例变量所属对象和变量 ID
• 调用 SetXXXField 函数修改变量的值,需要传入实例变量所属对象、变量 ID 和变量的值
• 调用 FindClass 函数获取类的 Class 引用
• 调用 GetStaticFieldID 函数获取 Class 引用中某个静态变量 ID
• 调用 GetStaticXXXField 函数获取静态变量的值,需要传入变量所属 Class 的引用和变量 ID
• 调用 SetStaticXXXField 函数设置静态变量的值,需要传入变量所属 Class 的引用、变量 ID和变量的
值
• 调用 GetObjectClass 函数获取实例对象的 Class 引用
• 调用 GetFieldID 函数获取 Class 引用中某个实例变量的 ID
• 调用 GetXXXField 函数获取变量的值,需要传入实例变量所属对象和变量 ID
• 调用 SetXXXField 函数修改变量的值,需要传入实例变量所属对象、变量 ID 和变量的值
• 调用 FindClass 函数获取类的 Class 引用
• 调用 GetStaticFieldID 函数获取 Class 引用中某个静态变量 ID
• 调用 GetStaticXXXField 函数获取静态变量的值,需要传入变量所属 Class 的引用和变量 ID
• 调用 SetStaticXXXField 函数设置静态变量的值,需要传入变量所属 Class 的引用、变量 ID和变量的
值