ADT插件:管理Android SDK和相关的开发工具的
NDK插件:用于开发Android NDK的插件,ADT版本在20以上,就能安装NDK插件,另外NDK集成了CDT插件(所以本文直接针对ADT 20以上版本进行说明)
到Android官网下载最新的NDK,注:NDK版本在r7以上之后就集成了Cygwin,而且还是十分精简版。比起下载Cygwin要方便多啦(Cygwin以前需要单独安装和配置,现在已被集成)!
下载链接见:http://developer.android.com/tools/sdk/ndk/index.html
下载完成之后,解压搞定。
打开Eclipse,点Window->Preferences->Android->NDK,设置NDK路径,例如我的是:D:\Android\android-ndk_r10-windows
新建一个Android工程,在工程上右键点击Android Tools->Add Native Support… ,然后给我们的.so文件取个名字,例如我的是:XS_NDK_01
这时候工程就会多一个jni的文件夹,jni下有Android.mk和XS_NDK_01.cpp文件。Android.mk是NDK工程的Makefile,XS_NDK_01.cpp就是NDK的源文件。
(关于 Android.mk 的说明可以参考资料:http://www.cnblogs.com/luxiaofeng54/archive/2011/08/13/2137577.html)
JNI接口的命名规范是:Java_ + 调用该方法的包名(包名的点用代替) + + 调用该接口的类名 + _ + 方法名,对于实例方法,有两个参数是必要的,一个JNI的环境指针JNIEnv *,另一个是调用该方法的Java实例jobject
接下来编辑XS_NDK_01.cpp文件,写一个HelloWorld的demo,代码如下:
<code class="hljs cpp has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include <string.h></span> <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include <jni.h></span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">extern</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"C"</span>{ jstring Java_com_shanhy_example_ndk01_MainActivity_getStringFromJNI(JNIEnv* env, jobject thiz) { <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//返回一个字符串给Java层</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> env->NewStringUTF(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"小单 的 JNI HellWorld 程序."</span>); } }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li></ul>
完成了,然后运行。运行之前先编译NDK,然后在编译JAVA代码。编译也许会遇到Unable to launch cygpath. Is Cygwin on the path?如何解决?
Eclipse -> Window -> Preperences -> C/C++ -> Build -> Environment 添加一个环境变量NDKROOT,如下图:
再工程右键,点Properties->C/C++ Build的Building Settings中去掉Use default build command,然后输入${NDKROOT}/ndk-build.cmd,如下图:
然后创建一个Activity调用我们刚刚编写的HelloWorld,代码如下:
<code class="hljs java has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">package</span> com.shanhy.example.ndk01; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> android.app.Activity; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> android.content.Context; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> android.os.Bundle; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> android.view.View; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> android.view.View.OnClickListener; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> android.widget.Button; <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/** * HelloWorld NDK 开发 * *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @author</span> SHANHY([email protected]) *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @date</span> 2015年11月19日 */</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">MainActivity</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">extends</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Activity</span> {</span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//也就是你mk配置文件中的 LOCAL_MODULE := XS_NDK_01</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> String libSoName = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"XS_NDK_01"</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> Context mContext = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> Button btnClick = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> String mStrMSG = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>; <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/** Called when the activity is first created. */</span> <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onCreate</span>(Bundle savedInstanceState) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>.onCreate(savedInstanceState); setContentView(R.layout.main); mContext = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>; btnClick = (Button) findViewById(R.id.btn_click); btnClick.setOnClickListener(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> OnClickListener() { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onClick</span>(View v) { <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//调用 JNI 层实现的方法</span> mStrMSG = getStringFromJNI(); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(mStrMSG == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) { mStrMSG = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"调用JNI失败"</span>; } LogUtils.toastMessage(mContext, mStrMSG); } }); } <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/** * 声明本地方法 * * 该方法为native方法.由C实现 * *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @return</span> JNI 给出的信息 */</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">native</span> String <span class="hljs-title" style="box-sizing: border-box;">getStringFromJNI</span>(); <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/** * 载入JNI生成的so库文件 */</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> { System.loadLibrary(libSoName); } }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li></ul>
至此,我们就完成了一个简单的例子,如需更进一步对NDK进行开发,请查阅相关资料。
=====================================
下面几种可能出现的错误的解决方案(如果直接按我上面的例子,是不会出现下面的错误的):
1、Method ‘NewStringUTF’ could not be resolved 问题(方法“NewStringUTF”无法被解析)
原因:
<code class="hljs applescript has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">I had this issue. Based <span class="hljs-function_start" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">on</span></span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">my</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"solution,"</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">it</span> seems <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">to</span> be something funny going <span class="hljs-function_start" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">on</span></span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> Eclipse, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">since</span> I had another project open <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">with</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">as</span> far <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">as</span> I was able <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">to</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">tell</span>) <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">the</span> exact <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">some</span> properties, paths, etc., besides <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> being labeled a Library Project. Just <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">by</span> observing <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">the</span> corresponding struct <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> jhi.h, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">the</span> callback prototypes are all there! Ctrl-click <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">the</span> include statement <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">and</span> Eclipse will even link you <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">the</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">reference</span>! Go <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">to</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">the</span> project's Properties -> C/C++ General -> Code Analysis. Click <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">the</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Use project settings"</span> radio button (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">or</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Configure Workspace Settings..."</span> button). Disable (uncheck) <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">the</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Method cannot be resolved"</span> checkbox. Click <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Apply,"</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"OK."</span> Then <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> your project, refresh, clean, refresh, build. There must have been something I did differently <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> creating <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">the</span> new project. Or maybe <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">it</span> was because <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">of</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">the</span> locations <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">of</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">the</span> projects, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">or</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">the</span> fact <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">that</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">the</span> previous was a Library. Maybe <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">it</span> really <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">is</span> an Eclipse bug? For <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">reference</span>, I'm using ADT v21<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">.1</span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">.0</span>-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">569685</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">and</span> NDK r8e <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> Windows。</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul>
项目右键->Properties->C/C++General->Code Analysis,选择”Use project settings或者Use workspace settings” 中的 Method cannot be resolved(方法无法被解析)取消选择,应用->保存,然后刷新、清理、刷新、build项目。
2、jni/hellocpp/main.cpp:16:18: error: base operand of ‘->’ has non-pointer type ‘JNIEnv {aka _JNIEnv}’ 问题
这是 android java 调用c++程序时报的错误
文件 XS_NDK_01.cpp 文件代码,按如下方式编写出现的错误:
<code class="hljs coffeescript has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">#include <string.h></span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">#include <jni.h></span> jstring Java_com_duicky_MainActivity_getStringFromJNI( JNIEnv* env,jobject thiz ) { <span class="hljs-regexp" style="color: rgb(0, 136, 0); box-sizing: border-box;">//</span> 返回一个字符串给Java层 <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(*env)</span>-></span>NewStringUTF(env, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"HelloWorld from JNI !!"</span>); <span class="hljs-regexp" style="color: rgb(0, 136, 0); box-sizing: border-box;">//</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> env->NewStringUTF(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"小单 的 JNI HellWorld 程序."</span>); } </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li></ul>
错误在于:
我开始是 (*env)->NewStringUTF(env, “小单 的 JNI HellWorld 程序.”); 这样写的,这是c的写法(文件应该是.c扩展名),而我的是cpp程序(.cpp扩展名),需要改写成:
env->NewStringUTF( “小单 的 JNI HellWorld 程序.”);
3、 java.lang.UnsatisfiedLinkError: Native method not found: com.shanhy.example.ndk01.MainActivity.getStringFromJNI:()Ljava/lang/String; 错误
有可能是:
1、c++中的方法Java_xxx_xxx 中的Java 首字母一定要大写
2、如果是 .cpp 文件 则用 extern “C” {“您的方法在这里”},大括号里是您的本地方法(如我上面的例子中那样写)。
Eclipse自动编译NDK/JNI的三种方法
1. 工程->右击选择Properties->选择Builders,在Builders中选择New创建一个Program
2. 参数配置
1. Project->Properties->Builders->New,新建一个Builder
2. 参数配置
2.1 Main
①Name:NDK_Builder
②Location为ndk-build.cmd的路径,可以如图所示绝对路径,也可以以环境变量的形式,即 ${ANDROID_NDK}\ndk-build.cmd,其中ANDROID_NDK为配置的NDK路径
③Working Directory,为当前的工程下。
这里的${}的表达是使用了EC的环境变量,可以使用Variables...按钮找到一些3 EC的环境变量。
对于Linux上的配置,和这里的配置一样,只是把Location的地址改为ndk-build即可
2.2 Refresh
2.3 Build Options
注:Linux环境下只需修改ndk-build.cmd为ndk-build即可
1. 前期准备:Eclipse环境+Android环境+Eclipse C/C++环境
2. 编写Android JAVA/JNI代码,可参考OpenCV实例1
3. 将Android项目转换为C/C++项目(使其具备C++属性),如下图,New -> Other -> C/C++ -> Convert to a C/C++ Project.
4. 配置NDK编译路径,Project->Properties,如下图,其中Build-Command中ANDROID_NDK为环境变量中配置的Android-NDK路径;Build-Directory为当前工程目录
5. 配置工程属性,Project->Properties,如下图,本例以OpenCV为例,其中CNU C和GNU C++中配置的是OpenCV的链接库
========
By SkySeraph-2014
一个Android.mk file用来向编译系统描述你的源代码。具体来说:该文件是GNU Makefile的一小部分,会被编译系统解析一次或多次。你可以在每一个Android.mk file中定义一个或多个模块,你也可以在几个模块中使用同一个源代码文件。编译系统为你处理许多细节问题。
一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为 makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。
makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。
Make工具最主要也是最基本的功能就是通过makefile文件来描述源程序之间的相互关系并自动维护编译工作。而makefile 文件需要按照某种语法进行编写,文件中需要说明如何编译各个源文件并连接生成可执行文件,并要求定义源文件之间的依赖关系。makefile 文件是许多编译器--包括Windows NT 下的编译器--维护编译信息的常用方法,只是在集成开发环境中,用户通过友好的界面修改 makefile 文件而已。
下面直接看一个实例:
Jni 文件树 如下
Android.mk文件 如下:
、LOCAL_PATH := $(call my-dir)
一个Android.mk file首先必须定义好LOCAL_PATH变量。它用于在开发树中查找源文件。在这个例子中,宏函数’my-dir’, 由编译系统提供,用于返回当前路径(即包含Android.mk file文件的目录)。
2、include $( CLEAR_VARS)
CLEAR_VARS 由编译系统提供,指定让GNU MAKEFILE为你清除许多LOCAL_XXX变量(例如 LOCAL_MODULE, LOCAL_SRC_FILES, LOCAL_STATIC_LIBRARIES, 等等...),除LOCAL_PATH 。这是必要的,因为所有的编译控制文件都在同一个GNU MAKE执行环境中,所有的变量都是全局的。
3、LOCAL_MODULE := HcSyncml
LOCAL_MODULE变量必须定义,以标识你在Android.mk文件中描述的每个模块。名称必须是唯一的,而且不包 含任何空格。注意编译系统会自动产生合适的前缀和后缀,换句话说,一个被命名为'HcSyncml'的共享库模块,将会生成'libHcSyncml.so'文件。
4、LOCAL_C_INCLUDES := $(LOCAL_PATH)/extra_inc$(LOCAL_PATH)/main_inc
LOCAL_C_INCLUDES 中加入所需要包含的头文件路径
5、LOCAL_SRC_FILES
LOCAL_SRC_FILES中加入源文件路径(需要编译的文件),多个文件用 ‘\’ 隔开
6、LOCAL_LDLIBS += -L$(SYSROOT)/usr/lib –llog
表示允许打印Log