Eclipse下NDK环境搭建实现Java、C\C++混合编程(图详)

Eclipse下NDK环境搭建实现Java、C\C++混合编程(图详)

一、Eclipse下NDK环境搭建

Windows7 64位旗舰版下,在搭建好Eclipse下Android开发环境前提下,Android开发环境搭建详情过程,请自行百度,一定注意Eclipse版本与ADT、SDK相互兼容。[转载请注明出处]

Android NDK系统框架图:

作者的NDK环境:

Jdk1.7版、Eclipse-jee-juno-win32最新版、ADT-23.0.4,SDK

请在Eclipse下Help——>Instrall NewSoftWare——> --All Available Sites-- 查找可用站点下载SDK

1首先,下载安装ndk-r8,最新版本未必兼容Eclipse

下载地址:http://developer.android.com/sdk/ndk/index.html

下载后解压缩待用。

2)链接ndk

在Eclipse下Window\Preferences——>Android——>NDK

在此要,选择刚刚解压缩的ndk文件根目录(提示:凡是安装目录命名一律英文,中文或数字开头的命名避免)

3)配置Builder(生成.os文件)

打开Eclipse,新建一个Android Application Project(取名为HelloNdk),在Project Explorer(工程目录)为HelloNdk新建jni文件夹,该文件夹就用来保存NDK需要编译的c/c++代码等。

项目根目录建立jni文件夹方法:

右击HelloNdk工程/Android Tools/Add Native Support…,.os文件默认命名为工程名HelloNdk,自带生成Android.mk和HelloNdk.cpp文件(有用)

 (a)Project->Properties->Builders->New,新建一个Builder

 

(b)在弹出的【Choose configuration type】对话框,选择【Program】,点击【OK】:

(c)在弹出的【Edit Configuration】对话框中,配置选项卡【Main】。

在“Name“中输入新builders的名称(我取名为Ndk_Builder)。

在“Location”中输入nkd-build.cmd的路径。

(我的是D:\AndroidDev\android-ndk-r7\ndk-build.cmd,根据各自的ndk路径设置,也可以点击“Browser File System…”来选取这个路径)。

在“Working Diretcoty”中输入${workspace_loc:/TestNdk}(也可以点击“Browse Workspace”来选取TestNdk目录)。

 

(d)【Edit Configuration】对话框中,配置选项卡【Refresh】。

勾选“Refresh resources upon completion”,

勾选“The entire workspace”,

勾选“Recuresively include sub-folders”。

 

(e)【Edit Configuration】对话框中,配置选项卡【Build options】。

勾选“After a “Clean””,

勾选“During manual builds”,

勾选“During auto builds”,

勾选“Specify working set of relevant resources”。

 

点击“Specify Resources…”

勾选TestNdk工程的“jni“目录,点击”finish“。

点击“OK“,完成配置。

 配置C/C++ BuildC/C++ General

右击HelloNdk工程/Properties,打开Propeties for HelloNdk。

a)       左击C/C++ Build,如下图所示

 

b)       再设置C/C++ General——>Paths and Symbols,如下图所示

  

点击右边Add…,如下图所示

 

勾选如图,左击Variables按钮,弹出Select build variable对话框

提示:$(NDK_MORE)     ndk_r8目录下     ...\android-ndk-r8\platforms\android-14\arch-arm\usr\include

作者已将其定义为系统变量NDK_MORE,设置方法同 jdk 环境变量 设置,见下图。

 

 

至此,Eclipse就能够自动调用NDK编译jin目录下的C/C++代码了。

 

二、 Demo运行

1)    Scr\com.example.hellondk目录下新建JniClient.java

1 package com.example.hellondk;
2 
3 public class JniClient {
4     public static native int AddInt(int a, int b);
5 }

2) 用cmd命令定位到JniClient.class 所在目录,输入“javac JniClient.java“后回车,作者项目目录截图如下:

3)    将在该目录下生产的JniClinet.class拷贝到HelloNdk\bin\classes\com\example\hellondk\目录内,其中有许多.class文件,(Eclipse会自动在该目录下生成JniClinet.class,最好还是覆盖)。

4)    cmd命令定位到HelloNdk\bin\classes目录,输入”javah com.example.hellondk.JniClient“后回车。

5)在 HelloNdk\bin\classes目录内会【自动】生成com_example_hellondk_JniClient.h

将其拷贝到Eclipse的HelloNdk工程 \jni文件夹目录下。

com_example_hellondk_JniClient.h代码见下

 1 /* DO NOT EDIT THIS FILE - it is machine generated */
 2 #include <jni.h>
 3 /* Header for class com_example_hellondk_JniClient */
 4 
 5 #ifndef _Included_com_example_hellondk_JniClient
 6 #define _Included_com_example_hellondk_JniClient
 7 #ifdef __cplusplus
 8 extern "C" {
 9 #endif
10 /*
11  * Class:     com_example_hellondk_JniClient
12  * Method:    AddInt
13  * Signature: (II)I
14  */
15 JNIEXPORT jint JNICALL Java_com_example_hellondk_JniClient_AddInt
16   (JNIEnv *, jclass, jint, jint);
17 
18 #ifdef __cplusplus
19 }
20 #endif
21 #endif

 

 

6)    将头文件中的AddInt函数声明复制到HelloNDK.cpp,编写C++代码,实现两个数相加,返回结果和。

因为暂时没有编译,文件会有许多处错误,正常。

HelloNDK.cpp全部代码如下:

1 #include <jni.h>
2 #include <com_example_hellondk_JniClient.h>
3 JNIEXPORT jint JNICALL Java_com_niming_hellondk_JniClient_AddInt
4   (JNIEnv *env, jclass, jint a, jint b){
5     return a + b;
6 }

7)   返回MainActivity.java我们来书写Java代码,调用刚刚编辑的C++函数。

利用一个Button,触发TextView显示两数和

12 public class MainActivity extends Activity {
13 
14       final int a =10;
15       final int b = 8;
16           @Override
17       protected void onCreate(Bundle savedInstanceState) {
18               super.onCreate(savedInstanceState);
19               setContentView(R.layout.activity_main);
20              
21              final TextView tv = (TextView) findViewById(R.id.textView1);
22              Button btn = (Button) findViewById(R.id.button1);
23              btn.setOnClickListener(new OnClickListener(){
24      
25                  @Override
26                  public void onClick(View v) {
27                      int c = JniClient.AddInt(a, b);//调用本地函数
28                      final String str = Integer.toString(c);
29                      tv.setText(str);
30                  }
31              });
32              
33          }
34      static{
35          System.loadLibrary("HelloNDK");//加载本地库
36      }
37 
38 
39     @Override
40     public boolean onCreateOptionsMenu(Menu menu) {
41         // Inflate the menu; this adds items to the action bar if it is present.
42         getMenuInflater().inflate(R.menu.main, menu);
43         return true;
44     }
45     
46 }

 

activity_main.xml文件

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="95dp"
        android:layout_marginTop="61dp"
        android:text="TextView" />

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/textView1"
        android:layout_centerVertical="true"
        android:layout_marginLeft="30dp"
        android:text="加加" />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/button1"
        android:layout_marginTop="77dp"
        android:layout_toRightOf="@+id/textView1"
        android:text="Button" />

</RelativeLayout>

至此,代码全部书写完毕。

8)    Eclipse中,Project / clean

 

9)    我们发现C++代码被编译成.so文件(每次改动重复Project/clean…操作)

 

OK,第一个NDK_Demo完成,可以连接真机测试。

10)  右击项目HelloNdk\Run As\Android Application查看结果

 

 


三、 小结

使用Java调用原生代码(C/C++)的大致过程:

1)  在Java类文件中加入新函数的声明,并将其定义为原生类型。见JniClient.java

2)  添加一个库的静态初始化器(initializer),原生函数将编译进这个库中。即System.loadLibrary("HelloNDK"); 

3)  向原生源文件中添加函数,头文件利用javah 命令自动生成如com_example_hellondk_JniClient.h,函数的命名需要遵循一定的命名规则,编写.cpp代码。

4)  Project / clean…生成 .so文件

如      Install        : libtemplateApp.so => libs/armeabi/libtemplateApp.so

5)  Java调用、载入shared library(共享库)的.so文件,打包成  *.apk

posted @ 2017-06-21 14:18  倪明  阅读(584)  评论(0)    收藏  举报