Android NDK开发之HelloWorld

来源:互联网 发布:大时代数据 编辑:程序博客网 时间:2024/05/17 23:30

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 
下载完成之后,解压搞定。

解压后的目录结构如下图所示: 
(图1)

打开Eclipse,点Window->Preferences->Android->NDK,设置NDK路径,例如我的是:D:\Android\android-ndk_r10-windows 
(图2)

新建一个Android工程,在工程上右键点击Android Tools->Add Native Support… ,然后给我们的.so文件取个名字,例如我的是:XS_NDK_01 
(图3)

这时候工程就会多一个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,如下图: 
(图4)

再工程右键,点Properties->C/C++ Build的Building Settings中去掉Use default build command,然后输入${NDKROOT}/ndk-build.cmd,如下图: 
(图5)

然后创建一个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(365384722@QQ.COM) *<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>jstringJava_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的三种方法

一、Eclipse关联cygwin

1. 工程->右击选择Properties->选择Builders,Builders中选择New创建一个Program

     

2. 参数配置

    


二、Eclipse关联ndk-build(自建Builder方法)

 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.cmdndk-build即可

 


三、Eclipse关联ndk-build(利用CDT的方法)

 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-CommandANDROID_NDK为环境变量中配置的Android-NDK路径;Build-Directory为当前工程目录

    

    

 5. 配置工程属性,Project->Properties,如下图,本例以OpenCV为例,其中CNU CGNU C++中配置的是OpenCV的链接库

     


 

========

By SkySeraph-2014 



基于 Android NDK 的学习之旅-----Android.mk 介绍

一个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


0 0
原创粉丝点击