Android NDK开发CSDN上的博文教程文档格式.docx
《Android NDK开发CSDN上的博文教程文档格式.docx》由会员分享,可在线阅读,更多相关《Android NDK开发CSDN上的博文教程文档格式.docx(43页珍藏版)》请在冰豆网上搜索。
lib
/data/data/com.conowen.helloworld/lib/libHelloWorld.so
0x44edea98
2.04-29
12.204:
Added
shared
3.04-29
No
JNI_OnLoad
found
in
0x44edea98,
skipping
init
(2)因为Dalvik虚拟机加载C库时,第一件事是调用JNI_OnLoad()函数,所以我们可以在JNI_OnLoad()里面进行一些初始化工作,如注册JNI函数等等。
注册本地函数,可以加快java层调用本地函数的效率。
另外:
与JNI_OnLoad()函数相对应的有JNI_OnUnload()函数,当虚拟机释放该C库时,则会调用JNI_OnUnload()函数来进行善后清除动作。
4、例子(关于jni里面的数据类型转换与常用jni方法下一篇博文介绍)
下面以havlenapetr的FFmpeg工程里面的onLoad.cpp为例详细说一下:
[cpp]
1.//onLoad.cpp文件
2.
3.#define
TAG
"
ffmpeg_onLoad"
4.
5.#include
<
stdlib.h>
6.#include
android/log.h>
7.#include
jniUtils.h"
8.
9.extern
C"
{
10.
11.extern
int
register_android_media_FFMpegAVRational(JNIEnv
*env);
12.
13.#ifdef
BUILD_WITH_CONVERTOR
14.extern
register_android_media_FFMpeg(JNIEnv
15.#endif
16.
17.extern
register_android_media_FFMpegAVFormatContext(JNIEnv
18.extern
register_android_media_FFMpegAVInputFormat(JNIEnv
19.
20.}
21.
22.extern
register_android_media_FFMpegAVCodecContext(JNIEnv
23.extern
register_android_media_FFMpegUtils(JNIEnv
24.extern
register_android_media_FFMpegAVFrame(JNIEnv
25.
26.#ifdef
BUILD_WITH_PLAYER
27.extern
register_android_media_FFMpegPlayerAndroid(JNIEnv
28.#endif
29.
30.static
JavaVM
*sVm;
31.
32./*
33.
*
Throw
an
exception
with
the
specified
class
and
optional
message.
34.
*/
35.int
jniThrowException(JNIEnv*
env,
const
char*
className,
msg)
36.
jclass
exceptionClass
env->
FindClass(className);
37.
if
(exceptionClass
==
NULL)
38.
__android_log_print(ANDROID_LOG_ERROR,
39.
TAG,
40.
Unable
find
%s"
41.
className);
42.
return
-1;
43.
}
44.
45.
(env->
ThrowNew(exceptionClass,
!
JNI_OK)
46.
47.
48.
Failed
throwing
'
%s'
49.
msg);
50.
51.
0;
52.}
53.
54.JNIEnv*
getJNIEnv()
55.
JNIEnv*
env
NULL;
56.
(sVm->
GetEnv((void**)
&
JNI_VERSION_1_4)
57.
58.
59.
obtain
JNIEnv"
60.
61.
62.
env;
63.}
64.
65./*
66.
Register
native
JNI-callable
methods.
67.
68.
className"
looks
like
java/lang/String"
.
69.
70.int
jniRegisterNativeMethods(JNIEnv*
71.
72.
JNINativeMethod*
gMethods,
73.
numMethods)
74./*从com_media_ffmpeg_FFMpegPlayer.cpp文件跳到此,完成最后的注册
75.
向
Dalvik虚拟机(即AndroidRuntime)登记传过来的参数gMethods[]所含的本地函数
76.
77.{
78.
clazz;
79.
80.
__android_log_print(ANDROID_LOG_INFO,
Registering
%s
natives\n"
81.
clazz
82.
(clazz
83.
Native
registration
unable
\n"
84.
85.
86.
RegisterNatives(clazz,
0)
87.
RegisterNatives
failed
for
88.
89.
90.
91.}
92.//Dalvik虚拟机加载C库时,第一件事是调用JNI_OnLoad()函数
93.jint
JNI_OnLoad(JavaVM*
vm,
void*
reserved)
94.
//定义JNI
Env
95.
jint
result
JNI_ERR;
96.
sVm
vm;
97.
/*JavaVM:
:
GetEnv
原型为
(*GetEnv)(JavaVM*,
void**,
jint);
98.
GetEnv()函数返回的
Jni
环境对每个线程来说是不同的,
99.
由于Dalvik虚拟机通常是Multi-threading的。
每一个线程调用JNI_OnLoad()时,
100.
所用的JNI
Env是不同的,因此我们必须在每次进入函数时都要通过vm->
GetEnv重新获取
101.
102.
103.
//得到JNI
104.
(vm->
105.
failed!
106.
result;
107.
108.
109.
loading
."
110.
111./*开始注册
112.
传入参数是JNI
113.
由于下面有很多class,只以register_android_media_FFMpegPlayerAndroid(env)为例子
114.
115.
116.#ifdef
117.
if(register_android_media_FFMpeg(env)
118.
can'
t
android_media_FFMpeg"
119.
goto
end;
120.
121.#endif
122.
123.
if(register_android_media_FFMpegAVFormatContext(env)
124.
android_media_FFMpegAVFormatContext"
125.
126.
127.
128.
if(register_android_media_FFMpegAVCodecContext(env)
129.
android_media_FFMpegAVCodecContext"
130.
131.
132.
133.
if(register_android_media_FFMpegAVRational(env)
134.
android_media_FFMpegAVRational"
135.
136.
137.
138.
if(register_android_media_FFMpegAVInputFormat(env)
139.
android_media_FFMpegAVInputFormat"
140.
141.
142.
143.
if(register_android_media_FFMpegUtils(env)
144.
android_media_FFMpegUtils"
145.
146.
147.
148.
if(register_android_media_FFMpegAVFrame(env)
149.
android_media_FFMpegAVFrame"
150.
151.
152.
153.#ifdef
154.
if(register_android_media_FFMpegPlayerAndroid(env)
{//跳到----》com_media_ffmpeg_FFMpegPlayer.cpp文件
155.
android_media_FFMpegPlayerAndroid"
156.
157.
158.#endif
159.
160.
loaded"
161.
162.
163.
164.end:
165.
166.}
1.//com_media_ffmpeg_FFMpegPlayer.cpp文件
2./*
3.
由于代码量较大,com_media_ffmpeg_FFMpegPlayer.cpp开始的一部分省略,只是贴出注册函数的相关部分。
5.
6.static
kClassPathName
com/media/ffmpeg/FFMpegPlayer"
;
7./*
由于gMethods[]是一个<
名称,函数指针>
对照表,在程序执行时,
9.
可多次调用registerNativeMethods()函数来更换本地函数的指针,
从而达到弹性调用本地函数的目的。
11.
12.static
JNINativeMethod
gMethods[]
13.
{"
setDataSource"
(Ljava/lang/String;
)V"
(void
*)com_media_ffmpeg_FFMpegPlayer_setDataSource},
14.
_setVideoSurface"
(Landroid/view/Surface;
*)com_media_ffmpeg_FFMpegPlayer_setVideoSurface},
15.
prepare"
()V"
*)com_media_ffmpeg_FFMpegPlayer_prepare},
_start"
*)com_media_ffmpeg_FFMpegPlayer_start},
17.
_stop"
*)com_media_ffmpeg_FFMpegPlayer_stop},
18.
getVideoWidth"
()I"
*)com_media_ffmpeg_FFMpegPlayer_getVideoWidth},
getVideoHeight"
*)com_media_ffmpeg_FFMpegPlayer_getVideoHeight},
20.
seekTo"
(I)V"
*)com_media_ffmpeg_FFMpegPlayer_seekTo},
_pause"
*)com_media_ffmpeg_FFMpegPlayer_pause},
22.
isPlaying"
()Z"
*)com_media_ffmpeg_FFMpegPlayer_isPlaying},
23.
getCurrentPosition"
*)com_media_ffmpeg_FFMpegPlayer_getCurrentPosition},
24.
getDuration"
*)com_media_ffmpeg_FF