首页 文章 精选 留言 我的

精选列表

搜索[android studio],共10000篇文章
优秀的个人博客,低调大师

Android应用程序键盘(Keyboard)消息处理机制分析(17)

Step 11.InputDispatcher.dispatchOnceInnerLocked 这个函数定义在frameworks/base/libs/ui/InputDispatcher.cpp文件中: voidInputDispatcher::dispatchOnceInnerLocked(nsecs_tkeyRepeatTimeout, nsecs_tkeyRepeatDelay,nsecs_t*nextWakeupTime){ ...... //Readytostartanewevent. //Ifwedon'talreadyhaveapendingevent,gograbone. if(!mPendingEvent){ if(mInboundQueue.isEmpty()){ ...... }else{ //Inboundqueuehasatleastoneentry. EventEntry*entry=mInboundQueue.headSentinel.next; ...... mInboundQueue.dequeue(entry); mPendingEvent=entry; } ...... } ...... switch(mPendingEvent->type){ ...... caseEventEntry::TYPE_KEY:{ KeyEntry*typedEntry=static_cast<KeyEntry*>(mPendingEvent); ...... done=dispatchKeyLocked(currentTime,typedEntry,keyRepeatTimeout, &dropReason,nextWakeupTime); break; } ...... } ...... } 我们忽略了这个函数的次要逻辑,主要关注键盘事件的主要处理流程。首先,如果前面发生的键盘事件都已经处理完毕,那么这里的mPendingEvent就为NULL,又因为前面我们把刚刚发生的键盘事件加入了mInboundQueue队列,因此,这里mInboundQueue不为NULL,于是,这里就把mInboundQueue队列中的键盘事件取出来,放在mPendingEvent变量中: mInboundQueue.dequeue(entry); mPendingEvent=entry; 由于这里发生的是键盘事件,即mPendingEvent->type的值为EventEntry::TYPE_KEY,于是,在接下来的switch语句中就会执行dispatchKeyLocked函数来分发键盘消息。 Step 12.InputDispatcher.dispatchKeyLocked 这个函数定义在frameworks/base/libs/ui/InputDispatcher.cpp文件中: boolInputDispatcher::dispatchKeyLocked( nsecs_tcurrentTime,KeyEntry*entry,nsecs_tkeyRepeatTimeout, DropReason*dropReason,nsecs_t*nextWakeupTime){ ...... //Identifytargets. if(!mCurrentInputTargetsValid){ int32_tinjectionResult=findFocusedWindowTargetsLocked(currentTime, entry,nextWakeupTime); ...... } //Dispatchthekey. dispatchEventToCurrentInputTargetsLocked(currentTime,entry,false); returntrue; } InputDispatcher类中的mCurrentInputTargetsValid成员变量表示InputDispatcher是否已经标志出谁是当前激活的Activity窗口,如果没有,就需要通过findFocusedWindowTargetsLocked函数来把它找出来。当把当前激活的Activity窗口找出来以后,接下来就调用dispatchEventToCurrentInputTargetsLocked函数把键盘事件分发给它了。 我们先来看一InputDispatcher是如何找到当前激活的Activity窗口的,然后再分析它把键盘事件分发给当前激活Activity窗口的过程。 Step 13.InputDispatcher.findFocusedWindowTargetsLocked 这个函数定义在frameworks/base/libs/ui/InputDispatcher.cpp文件中: int32_tInputDispatcher::findFocusedWindowTargetsLocked(nsecs_tcurrentTime, constEventEntry*entry,nsecs_t*nextWakeupTime){ mCurrentInputTargets.clear(); int32_tinjectionResult; //Ifthereisnocurrentlyfocusedwindowandnofocusedapplication //thendroptheevent. if(!mFocusedWindow){ if(mFocusedApplication){ ...... injectionResult=handleTargetsNotReadyLocked(currentTime,entry, mFocusedApplication,NULL,nextWakeupTime); gotoUnresponsive; } ...... injectionResult=INPUT_EVENT_INJECTION_FAILED; gotoFailed; } //Checkpermissions. if(!checkInjectionPermission(mFocusedWindow,entry->injectionState)){ injectionResult=INPUT_EVENT_INJECTION_PERMISSION_DENIED; gotoFailed; } //Ifthecurrentlyfocusedwindowispausedthenkeepwaiting. if(mFocusedWindow->paused){ ...... injectionResult=handleTargetsNotReadyLocked(currentTime,entry, mFocusedApplication,mFocusedWindow,nextWakeupTime); gotoUnresponsive; } //Ifthecurrentlyfocusedwindowisstillworkingonpreviouseventsthenkeepwaiting. if(!isWindowFinishedWithPreviousInputLocked(mFocusedWindow)){ ...... injectionResult=handleTargetsNotReadyLocked(currentTime,entry, mFocusedApplication,mFocusedWindow,nextWakeupTime); gotoUnresponsive; } //Success!Outputtargets. injectionResult=INPUT_EVENT_INJECTION_SUCCEEDED; addWindowTargetLocked(mFocusedWindow,InputTarget::FLAG_FOREGROUND,BitSet32(0)); ...... returninjectionResult; } 回忆前面我们分析应用程序注册键盘消息接收通道的过程时,在Step 9中,当前处于激活状态的应用程序会通过调用InputDispatcher类setInputWindows函数把把当前获得焦点的Activity窗口设置到mFocusedWindow中去,因此,这里的mFocusedWindow不为NULL,于是,就通过了第一个if语句的检查。 第二个if语句检查权限问题,原来,这个键盘事件除了是由硬件触发的外,也可以由其它进程注入进来的,如果这个键盘事件是由其它进程注入进来的,那么entry->injectState就不为NULL,它里面包含了事件注册者的进程ID和用户ID,于是,这里就会调用checkInjectionPermission来检查这个事件注入者的进程ID和用户ID,看看它是否具有这个权限。这里我们不考虑这种情况,因此,这里的entry->injectState为NULL,于是,这个if语句的检查也通过了。 第三个if语句检查当前激活的Activity窗口是否是处于paused状态,如果是的话,也不用进一步处理了。一般情况下,当前激活的Activity窗口都是处于resumed状态的,于是,这个if语句的检查也通过了。 第四个if语句检查当前激活的Activity窗口是否还正在处理前一个键盘事件,如果是的话,那就要等待它处理完前一个键盘事件后再来处理新的键盘事件了。这里我们也假设当前激活的Activity窗口不是正在处理前面的键盘事件,因此,这个if语句的检查也通过了。 最后,就调用addWindowTargetLocked函数把当前激活的Activity窗口添加到InputDispatcher类的mCurrentInputTargets成员变量中去。 Step 14.InputDispatcher.addWindowTargetLocked 这个函数定义在frameworks/base/libs/ui/InputDispatcher.cpp文件中: voidInputDispatcher::addWindowTargetLocked(constInputWindow*window,int32_ttargetFlags, BitSet32pointerIds){ mCurrentInputTargets.push(); InputTarget&target=mCurrentInputTargets.editTop(); target.inputChannel=window->inputChannel; target.flags=targetFlags; target.xOffset=-window->frameLeft; target.yOffset=-window->frameTop; target.pointerIds=pointerIds; } 这个函数简单,就是把传进来的参数window添加到mCurrentInputTargets中去就完事了,后面InputDispatcher就会从mCurrentInputTargets中取出恰当的Activity窗口,然后把键盘事件分发给它。 回到Step 12中的dispatchKeyLocked函数,它接下来就调用dispatchEventToCurrentInputTargetsLocked来进一步处理了。 Step 15.InputDispatcher.dispatchEventToCurrentInputTargetsLocked 这个函数定义在frameworks/base/libs/ui/InputDispatcher.cpp文件中: voidInputDispatcher::dispatchEventToCurrentInputTargetsLocked(nsecs_tcurrentTime, EventEntry*eventEntry,boolresumeWithAppendedMotionSample){ ...... for(size_ti=0;i<mCurrentInputTargets.size();i++){ constInputTarget&inputTarget=mCurrentInputTargets.itemAt(i); ssize_tconnectionIndex=getConnectionIndexLocked(inputTarget.inputChannel); if(connectionIndex>=0){ sp<Connection>connection=mConnectionsByReceiveFd.valueAt(connectionIndex); prepareDispatchCycleLocked(currentTime,connection,eventEntry,&inputTarget, resumeWithAppendedMotionSample); }else{ ...... } } 这个函数的实现也比较简单,前面我们已经把当前需要接受键盘事件的Activity窗口添加到mCurrentInputTargets中去了,因此,这里就分别把它们取出来,然后调用prepareDispatchCycleLocked函数把键盘事件分发给它们处理。 前面我们在分析应用程序注册键盘消息接收通道的过程时,在Step 18中(InputDispatcher.registerInputChannel),把Server端的InputChannel封装成了一个Connection,然后以这个InputChannel中的Receive Pipe Fd作为键值把这个Connection对象保存在mConnectionsByReceiveFd中。这里,既然我们已经通过mCurrentInputTargets得到了表示当前需要接收键盘事件的Activity窗口的InputTarget对象,而且这个InputTarget对象的inputChannel就表示当初在InputDispatcher中注册的Server端InputChannel,因此,这里就可以把这个Connection对象取出来,最后调用prepareDispatchCycleLocked函数来进一步处理。 本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/966635,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android应用程序键盘(Keyboard)消息处理机制分析(8)

回到Step 18中,我们继续分析EventHub.getEvent函数的实现。 在中间的for循环里面,首先会检查当前是否有输入设备被关闭,如果有,就返回一个设备移除的事件给调用方: //Reportanydevicesthathadlastbeenadded/removed. if(mClosingDevices!=NULL){ device_t*device=mClosingDevices; LOGV("Reportingdeviceclosed:id=0x%x,name=%s\n", device->id,device->path.string()); mClosingDevices=device->next; if(device->id==mFirstKeyboardId){ outEvent->deviceId=0; }else{ outEvent->deviceId=device->id; } outEvent->type=DEVICE_REMOVED; outEvent->when=systemTime(SYSTEM_TIME_MONOTONIC); deletedevice; mNeedToSendFinishedDeviceScan=true; returntrue; } 接着,检查当前是否有新的输入设备加入进来: if(mOpeningDevices!=NULL){ device_t*device=mOpeningDevices; LOGV("Reportingdeviceopened:id=0x%x,name=%s\n", device->id,device->path.string()); mOpeningDevices=device->next; if(device->id==mFirstKeyboardId){ outEvent->deviceId=0; }else{ outEvent->deviceId=device->id; } outEvent->type=DEVICE_ADDED; outEvent->when=systemTime(SYSTEM_TIME_MONOTONIC); mNeedToSendFinishedDeviceScan=true; returntrue; } 接着,再检查是否需要结束监控输入事件: if(mNeedToSendFinishedDeviceScan){ mNeedToSendFinishedDeviceScan=false; outEvent->type=FINISHED_DEVICE_SCAN; outEvent->when=systemTime(SYSTEM_TIME_MONOTONIC); returntrue; } 最后,就是要检查当前是否有还未处理的输入设备事件发生了: //Grabthenextinputevent. for(;;){ //Consumebufferedinputevents,ifany. if(mInputBufferIndex<mInputBufferCount){ conststructinput_event&iev=mInputBufferData[mInputBufferIndex++]; constdevice_t*device=mDevices[mInputDeviceIndex]; LOGV("%sgot:t0=%d,t1=%d,type=%d,code=%d,v=%d",device->path.string(), (int)iev.time.tv_sec,(int)iev.time.tv_usec,iev.type,iev.code,iev.value); if(device->id==mFirstKeyboardId){ outEvent->deviceId=0; }else{ outEvent->deviceId=device->id; } outEvent->type=iev.type; outEvent->scanCode=iev.code; if(iev.type==EV_KEY){ status_terr=device->layoutMap->map(iev.code, &outEvent->keyCode,&outEvent->flags); LOGV("iev.code=%dkeyCode=%dflags=0x%08xerr=%d\n", iev.code,outEvent->keyCode,outEvent->flags,err); if(err!=0){ outEvent->keyCode=AKEYCODE_UNKNOWN; outEvent->flags=0; } }else{ outEvent->keyCode=iev.code; } outEvent->value=iev.value; //Useaneventtimestampinthesametimebaseas //java.lang.System.nanoTime()andandroid.os.SystemClock.uptimeMillis() //asexpectedbytherestofthesystem. outEvent->when=systemTime(SYSTEM_TIME_MONOTONIC); returntrue; } //Finishreadingalleventsfromdevicesidentifiedinpreviouspoll(). //ThiscodeassumesthatmInputDeviceIndexisinitially0andthatthe //reventsmemberofpollfdisinitializedto0whenthedeviceisfirstadded. //SincemFDs[0]isusedforinotify,weprocessregulareventsstartingatindex1. mInputDeviceIndex+=1; if(mInputDeviceIndex>=mFDCount){ break; } conststructpollfd&pfd=mFDs[mInputDeviceIndex]; if(pfd.revents&POLLIN){ int32_treadSize=read(pfd.fd,mInputBufferData, sizeof(structinput_event)*INPUT_BUFFER_SIZE); if(readSize<0){ if(errno!=EAGAIN&&errno!=EINTR){ LOGW("couldnotgetevent(errno=%d)",errno); } }elseif((readSize%sizeof(structinput_event))!=0){ LOGE("couldnotgetevent(wrongsize:%d)",readSize); }else{ mInputBufferCount=readSize/sizeof(structinput_event); mInputBufferIndex=0; } } } 未处理的输入事件保存在成员变量mInputBufferData中,如果有的话,就可以直接返回了,否则的话,就要通过系统调用poll来等待输入设备上发生新的事件了,在我们这个场景中,就是等待键盘有键被按下或者松开了。: intpollResult=poll(mFDs,mFDCount,-1); 这里的mFDs包含了我们所要监控的输入设备的打开文件描述符,这是在前面的openPlatformInput函数中初始化的。 本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/966621,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android JNI入门第三篇——jni头文件分析

一、 首先写了java文件: publicclassHeaderFile{ privatenativevoiddoVoid(); nativeintdoShort(); nativevoiddoArray(Object[]o); nativeintdoInt(inti);//byte,short,int,long,float,double,boolean,char nativeintdoInt(doubled);//byte,short,int,long,float,double,boolean,char nativeintdoInt(Objecto); nativeintdoInt(doubled1,doubled2); staticnativeintdoInt(doubled1,doubled2,doubled3); staticnativeintdoInt(doubled1,floatf,booleanb,char[]c); nativeintdoInt(int[]i); nativeintdoInt(int[]i1,double[]i2); staticnativeintdoInt(int[]i1,double[]i2,Object[]o); publicnativeStringdoString(Strings); publicnativeObjectdoObject(Objecto); publicnativeEnumerationdoInterface(Iteratorit); publicnativeStudentdoStudent(Students); //nativeint[]doInt(int[]i);//byte,short,int,long,float,double,boolean,char publicnativeString[]doString(String[]s); publicnativeObject[]doObjects(Object[]o); publicnativeEnumeration[]doInterface(Iterator[]it); publicnativeStudent[]doStudent(Student[]s); publicnativestaticObjectdoAll(int[]i,String[]s,Student[]student); } java文件中包含了private、public、protect等类型的方法,static 方法和非static 方法,返回类型有基础类型、对象等。 二、下面看一下生成的头文件: /*DONOTEDITTHISFILE-itismachinegenerated*/ #include<jni.h> /*Headerforclasscom_nedu_jni_helloword_HeaderFile*/ #ifndef_Included_com_nedu_jni_helloword_HeaderFile #define_Included_com_nedu_jni_helloword_HeaderFile #ifdef__cplusplus extern"C"{ #endif /* *Class:com_nedu_jni_helloword_HeaderFile *Method:doVoid *Signature:()V */ JNIEXPORTvoidJNICALLJava_com_nedu_jni_helloword_HeaderFile_doVoid (JNIEnv*,jobject); /* *Class:com_nedu_jni_helloword_HeaderFile *Method:doShort *Signature:()I */ JNIEXPORTjintJNICALLJava_com_nedu_jni_helloword_HeaderFile_doShort (JNIEnv*,jobject); /* *Class:com_nedu_jni_helloword_HeaderFile *Method:doArray *Signature:([Ljava/lang/Object;)V */ JNIEXPORTvoidJNICALLJava_com_nedu_jni_helloword_HeaderFile_doArray (JNIEnv*,jobject,jobjectArray); /* *Class:com_nedu_jni_helloword_HeaderFile *Method:doInt *Signature:(I)I */ JNIEXPORTjintJNICALLJava_com_nedu_jni_helloword_HeaderFile_doInt__I (JNIEnv*,jobject,jint); /* *Class:com_nedu_jni_helloword_HeaderFile *Method:doInt *Signature:(D)I */ JNIEXPORTjintJNICALLJava_com_nedu_jni_helloword_HeaderFile_doInt__D (JNIEnv*,jobject,jdouble); /* *Class:com_nedu_jni_helloword_HeaderFile *Method:doInt *Signature:(Ljava/lang/Object;)I */ JNIEXPORTjintJNICALLJava_com_nedu_jni_helloword_HeaderFile_doInt__Ljava_lang_Object_2 (JNIEnv*,jobject,jobject); /* *Class:com_nedu_jni_helloword_HeaderFile *Method:doInt *Signature:(DD)I */ JNIEXPORTjintJNICALLJava_com_nedu_jni_helloword_HeaderFile_doInt__DD (JNIEnv*,jobject,jdouble,jdouble); /* *Class:com_nedu_jni_helloword_HeaderFile *Method:doInt *Signature:(DDD)I */ JNIEXPORTjintJNICALLJava_com_nedu_jni_helloword_HeaderFile_doInt__DDD (JNIEnv*,jclass,jdouble,jdouble,jdouble); /* *Class:com_nedu_jni_helloword_HeaderFile *Method:doInt *Signature:(DFZ[C)I */ JNIEXPORTjintJNICALLJava_com_nedu_jni_helloword_HeaderFile_doInt__DFZ_3C (JNIEnv*,jclass,jdouble,jfloat,jboolean,jcharArray); /* *Class:com_nedu_jni_helloword_HeaderFile *Method:doInt *Signature:([I)I */ JNIEXPORTjintJNICALLJava_com_nedu_jni_helloword_HeaderFile_doInt___3I (JNIEnv*,jobject,jintArray); /* *Class:com_nedu_jni_helloword_HeaderFile *Method:doInt *Signature:([I[D)I */ JNIEXPORTjintJNICALLJava_com_nedu_jni_helloword_HeaderFile_doInt___3I_3D (JNIEnv*,jobject,jintArray,jdoubleArray); /* *Class:com_nedu_jni_helloword_HeaderFile *Method:doInt *Signature:([I[D[Ljava/lang/Object;)I */ JNIEXPORTjintJNICALLJava_com_nedu_jni_helloword_HeaderFile_doInt___3I_3D_3Ljava_lang_Object_2 (JNIEnv*,jclass,jintArray,jdoubleArray,jobjectArray); /* *Class:com_nedu_jni_helloword_HeaderFile *Method:doString *Signature:(Ljava/lang/String;)Ljava/lang/String; */ JNIEXPORTjstringJNICALLJava_com_nedu_jni_helloword_HeaderFile_doString__Ljava_lang_String_2 (JNIEnv*,jobject,jstring); /* *Class:com_nedu_jni_helloword_HeaderFile *Method:doObject *Signature:(Ljava/lang/Object;)Ljava/lang/Object; */ JNIEXPORTjobjectJNICALLJava_com_nedu_jni_helloword_HeaderFile_doObject (JNIEnv*,jobject,jobject); /* *Class:com_nedu_jni_helloword_HeaderFile *Method:doInterface *Signature:(Ljava/util/Iterator;)Ljava/util/Enumeration; */ JNIEXPORTjobjectJNICALLJava_com_nedu_jni_helloword_HeaderFile_doInterface__Ljava_util_Iterator_2 (JNIEnv*,jobject,jobject); /* *Class:com_nedu_jni_helloword_HeaderFile *Method:doStudent *Signature:(Lcom/nedu/jni/helloword/Student;)Lcom/nedu/jni/helloword/Student; */ JNIEXPORTjobjectJNICALLJava_com_nedu_jni_helloword_HeaderFile_doStudent__Lcom_nedu_jni_helloword_Student_2 (JNIEnv*,jobject,jobject); /* *Class:com_nedu_jni_helloword_HeaderFile *Method:doString *Signature:([Ljava/lang/String;)[Ljava/lang/String; */ JNIEXPORTjobjectArrayJNICALLJava_com_nedu_jni_helloword_HeaderFile_doString___3Ljava_lang_String_2 (JNIEnv*,jobject,jobjectArray); /* *Class:com_nedu_jni_helloword_HeaderFile *Method:doObjects *Signature:([Ljava/lang/Object;)[Ljava/lang/Object; */ JNIEXPORTjobjectArrayJNICALLJava_com_nedu_jni_helloword_HeaderFile_doObjects (JNIEnv*,jobject,jobjectArray); /* *Class:com_nedu_jni_helloword_HeaderFile *Method:doInterface *Signature:([Ljava/util/Iterator;)[Ljava/util/Enumeration; */ JNIEXPORTjobjectArrayJNICALLJava_com_nedu_jni_helloword_HeaderFile_doInterface___3Ljava_util_Iterator_2 (JNIEnv*,jobject,jobjectArray); /* *Class:com_nedu_jni_helloword_HeaderFile *Method:doStudent *Signature:([Lcom/nedu/jni/helloword/Student;)[Lcom/nedu/jni/helloword/Student; */ JNIEXPORTjobjectArrayJNICALLJava_com_nedu_jni_helloword_HeaderFile_doStudent___3Lcom_nedu_jni_helloword_Student_2 (JNIEnv*,jobject,jobjectArray); /* *Class:com_nedu_jni_helloword_HeaderFile *Method:doAll *Signature:([I[Ljava/lang/String;[Lcom/nedu/jni/helloword/Student;)Ljava/lang/Object; */ JNIEXPORTjobjectJNICALLJava_com_nedu_jni_helloword_HeaderFile_doAll (JNIEnv*,jclass,jintArray,jobjectArray,jobjectArray); #ifdef__cplusplus } #endif #endif 三、头文件分析如下: 1、文件的前九行就不用说了,他们是是C、C++的头,应该很好理解。 2、方法的注释部分,每个方法都有它的注释部分,这些都是相似的,对其中一个分析: /* *Class:com_nedu_jni_helloword_HeaderFile *Method:doVoid *Signature:()V */ 注释部分分为三部分Class、Method、Signature。 Class:表示Native方法的类名称。 Method:表示方法名称 Signature:是方法的标识,它是一个标识符,主要供我们在JNI操作java对象的方法使用的。 Signature一般是两部分构成,一个方法的参数,另一个是返回类型。方法参数在括号里面,返回类型在后面, 例如 ()V返回为void,没有参数。 (DFZ[C)I返回为int,参数为double、float、char[] (Ljava/lang/String;)Ljava/lang/String;返回String,参数为String 如果不清楚其中的字符含义,就不能知道其中的意思,其中字符对应有基本类型、对象类型、数组类型。分析如下 1)基本类型的对应关系如下: 2)方法参数或者返回值为java中的对象时,必须以“L”加上其路径,不过此路径必须以“/”分开,自定义的对象也使用本规则,不在包中时直接“L”加上类名称。比如说java.lang.String为“java/lang/String”,com.nedu.jni.helloword.Student为"com/nedu/jni/helloword/Student" 3)方法参数或者返回值为数组时类型前加上[,例如[I表示int[],[[[D表示 double[][][],即几维数组就加几个[。 看一下例子: 3、方法的声明 JNIEXPORTvoidJNICALLJava_com_nedu_jni_helloword_HeaderFile_doArray(JNIEnv*,jobject,jobjectArray); 从上面的头文件可以看出方法基本有7部分组成。 1、3部分是都是JNI的关键字,表示此函数是要被JNI调用的。 2、表示方法的返回类型 4、为JNI中标识此方法来源于java的标识头 5、方法所在类的包名+类名 6、方法名 7、参数,它们有一个共同的特点,包含JNIEnv *――它是一个接口指针,用于定位函数表中的函数! 在JNI规范中一般称 为 “Interface Pointer”。看到这儿好像和过程调用很类似了!是的,JNI中 的操作过程,就是面向过程的!后面的jobject是 一个指向该类的指针,类似与C语言中的this。这个 第二个参数是变化的,当该方法为类的实例方法时该参数为jobject;当该方法为类方法(即静态方法) 时该参数为jclass,指向该类的class。 根据不同方法前缀生成的头文件比较如下: 1、static与非static的比较: /* *Class:com_nedu_jni_helloword_HeaderFile *Method:doInt *Signature:(DD)I */ JNIEXPORTjintJNICALLJava_com_nedu_jni_helloword_HeaderFile_doInt__DD (JNIEnv*,<spanstyle="background-co lor:rgb(255,0,0);">jobject</span>,jdouble,jdouble); /* *Class:com_nedu_jni_helloword_HeaderFile *Method:doInt *Signature:(DDD)I */ JNIEXPORTjintJNICALLJava_com_nedu_jni_helloword_HeaderFile_doInt__DDD (JNIEnv*,<spanstyle="color:#000000;background-color:rgb(255,0,0);">jclass</span>,jdouble,jdouble,jdouble); 第一个是非static方法,第二个是static方法,不同点如上红色标记。其中的不同将在以后提到。 2、private、friendly、protected以及public这些方法限制符不会在JNI的头文件中出现。这些访问修饰符只有在其它类 使用这些方法时有效!JNI中不关心此修饰符! /** *@author张兴业 *邮箱:xy-zhang@163.com *qq:363302850 */ 本文转自xyz_lmn51CTO博客,原文链接:http://blog.51cto.com/xyzlmn/817213 ,如需转载请自行联系原作者

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册