android下NDK开发环境搭建及TestJNI入门实例完整过程

1.先搭建好基本的ndk的开发环境

在windows下安装下面两个软件

1、 Android NDK 安装

2、 安装Cygwin与使用NDK编译

本文建立在已经完成Android开发环境搭建的基础上。其基础环境至少需要包含以下内容:

1、 JDK

2、 Eclipse

3、 Android SDK and ADT

一、Android NDK 安装与配置

下载Android NDK。下载地址:http://developer.android.com/tools/sdk/ndk/index.html

下载后解压缩到你的工作目录,例如:D:\Java\android-ndk-r8,结果如下图:

注意:samples下面包含几个实例开发演示项目,第一次接触NDK开发,建议先从示例开始。

二、安装Cygwin与使用NDK编译

由于NDK开发大都涉及到C/C++在GCC环境下编译、运行,所以在Windows环境下,需要用Cygwin模拟Linux编译环境。

下载:

Cygwin的下载地址:http://www.cygwin.com/

点击右上角的“setup.exe”即可下载。

安装:

    第一步:运行setup.exe程序,直接点击Next进入下一步。

第二步:选择安装方式。第一次可以采用Direct Connection在线下载安装,如有现成的离线包,可以选择离线安装(Install from Local Directory)。

第三步:选择安装目录。比如D:\Java\Cygwin,注意此目录是指Cygwin最终的安装目录,不是下载文件暂存目录。

第四步:设置本地包暂存路径。暂存目录默认是放到setup.exe的同级目录下,建议放到指定的文件夹,如D:\Cygwin_install_file。安装完成后把这个文件夹打包备份,以后再配置时不用重新下载。

第五步:设置网络连接方式。这个目前河蟹没爬过来,选第一个即可。

第六步:选择下载站点地址。据说国内163站点的速度不错,我也是用的这个。

第七步:等待加载安装项载入,选择安装项。点击Devel-Default,使之变成Devel-Install,展开后可以看到其下的子项被选中了(网上多数教程都说选中某12个包,找起来太坑爹了,直接全下载了吧,全选多了150M左右)。此界面其他设置都不用动。

第八步:等待下载完成。下载完成时间决定于你选择的安装包数量及网络连接速度,安装我安装的版本,约983M,下载完成后会自动安装到上文设置的安装目录,安装也要时间的,总时间较长,去吃个饭没啥问题。

提醒:第四步的备份建议,尽量去做。如果有备份,第二步中选择离线安装。

验证:

运行安装目录下的“Cygwin.bat”,第一次运行时,它会自动创建用户信息,用户信息存放在“.\Cygwin\home”中。

在运行“Cygwin.bat”打开的命令行窗口输入:“cygcheck -c cygwin”命令,会打印出当前Cygwin的版本和运行状态,如果status是ok的话,则cygwin运行正常。

分别输入:“make –v”和,“gcc –v”命令如果检测成功,会有make和gcc相关版本信息打印出来。

设置NDK路径:

在windows的系统环境变量中添加NDK的路径。使用“/cygdrive/d/Java/android-ndk-r8”这种Linux风格路径,如果使用Windows下的“D:\Java\android-ndk-r8”,Cygwin在编译时会发出警告。

运行Cygwin命令行,可以直接使用此环境变量,当然也可以手动的cd到该目录:

三、新建TestJni工程,使用NDK编译程序

1.创建Android工程

2首先建立一个名为TestJni的Android工程,包名默认为com.example.hellojni,src目录下自动创建MainActivity.java。

设计JNI接口,新建一个java文件,TestJni.java.如图

—工程目录图

TestJni.java代码如下

package com.example.hellojni;

public class TestJni {
    public native boolean init();
    public native int add(int x,int y);
    public native void destory();
}

3.编译JNI

在E:\workplace\TestJni\bin\classes\com\example\hellojni文件夹下会生成TestJni.class文件。

在bin文件夹下,如果没有则创建目录:/com/example/jni,并把TestJNI.class复制到/bin/com/example/jni目录下。然后在终端里进入工程的bin目录,输入javah -jni com.example.jni.TestJNI,此时会生成一个com_example_jni_TestJNI.h文件。

注意:我在输入javah -jni com.example.jni.TestJNI的命令时会出错,改为

javah -classpath E:/software_tool/android/adt-bundle-windows-x86_64-20140702/sdk/platforms/android-20/android.jar;bin/classes -d jni com.example.hellojni.TestJni

4.用C/C++实现JNI

有了JNI的C/C++头文件,就可以在C层实现JNI接口了。首先在工程目录下创建一个jni目录,这个目录就是专门用来放C/C++代码的。把com_example_hellojni_TestJni.h文件复制到jni目录下,并在这里创建一个com_example_jni_TestJni.cpp文件。

由于我想用C++来实现JNI,所以上面两个文件我只是用来作为动态链接库的接口,具体的实现我希望放在一个类里面来完成,因此我再添加两个文件:Add.h和Add.cpp。如上操作结果见工程目录图

com_example_hellojni_TestJni.h

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_hellojni_TestJni */

#ifndef _Included_com_example_hellojni_TestJni
#define _Included_com_example_hellojni_TestJni
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_example_hellojni_TestJni
 * Method:    init
 * Signature: ()Z
 */
JNIEXPORT jboolean JNICALL Java_com_example_hellojni_TestJni_init
  (JNIEnv *, jobject);

/*
 * Class:     com_example_hellojni_TestJni
 * Method:    add
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_com_example_hellojni_TestJni_add
  (JNIEnv *, jobject, jint, jint);

/*
 * Class:     com_example_hellojni_TestJni
 * Method:    destory
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_example_hellojni_TestJni_destory
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

com_example_hellojni_TestJni.cpp

#include <stdio.h>
#include <stdlib.h>
#include "com_example_hellojni_TestJni.h"
#include "Add.h"

CAdd *pCAdd = NULL;
JNIEXPORT jboolean JNICALL Java_com_example_hellojni_TestJni_init(JNIEnv *env,jobject obj) {
   if (pCAdd == NULL) {
        pCAdd = new CAdd;
    }
   return pCAdd != NULL;
}
JNIEXPORT jint JNICALL Java_com_example_hellojni_TestJni_add(JNIEnv *env, jobject obj,
        jint x, jint y) {
        int res = -1;
       if (pCAdd != NULL) {
          res = pCAdd->add(x, y);
        }
       return res;
}
JNIEXPORT void JNICALL Java_com_example_hellojni_TestJni_destory(JNIEnv *env, jobject obj)
{    if (pCAdd != NULL)
    {
        pCAdd = NULL;
    }
}

Add.cpp

#include "Add.h"
 CAdd::CAdd() {
 }
 CAdd::~CAdd() {
 }
 int CAdd::add(int x, int y) {
 return x + y;
}

Add.h

#ifndef _TEST_JNI_ADD_H_
#define _TEST_JNI_ADD_H_
class CAdd {
    public:
        CAdd();
        ~CAdd();
        int add(int x,int y);
};
#endif

到此C/C++代码实现结束

5、创建Android.mk

JNI实现了之后就要把C/C++代码编译成动态链接库.so文件,这样Java程序才能调用JNI的接口。要编译so文件,需要写Android.mk和Application.mk两个文件。我们先来写Android.mk。

先在工程目录的jni下创建一个Android.mk文件:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := TestJni
LOCAL_SRC_FILES := com_example_hellojni_TestJni.cpp
LOCAL_SRC_FILES += Add.cpp
include $(BUILD_SHARED_LIBRARY)

其中LOCAL_PATH是C/C++代码所在目录,也就是我们的jni目录。

LOCAL_MODULE是要编译的库的名称。编译器会自动在前面加上lib,在后面加上.so。

LOCAL_SRC_FILES是要编译的C/C++文件。

现在我们在工程的根目录下创建一个Application.mk文件,并输入如下内容:

APP_PROJECT_PATH := $(call my-dir)
APP_MODULES := TestJni

6、编译动态链接库(.so文件)

默认在Windows7下配置好了NDK开发环境,打开cygwin,进入到工程目录

编译生成.SO库

编译成功后会在工程目录的libs/armeabi目录下生成一个libTestJni.so文件。

7 在Java中调用JNI

现在我们的Android应用可以调用JNI计算加法的代码,如下:

MainActivity.java

package com.example.hellojni;

import android.support.v7.app.ActionBarActivity;
import android.app.Activity;
import android.app.SearchManager.OnCancelListener;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends Activity{

    static{
        System.loadLibrary("TestJni");
    }
    EditText tvX = null;
    EditText tvY = null;
    EditText tvSum = null;
    Button   btnAdd = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tvX = (EditText)findViewById(R.id.et_x);
        tvY = (EditText)findViewById(R.id.et_y);
        tvSum = (EditText)findViewById(R.id.et_sum);
        btnAdd = (Button)findViewById(R.id.btn_add);
        btnAdd.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                int x = Integer.valueOf( tvX.getText().toString());
                int y = Integer.valueOf( tvY.getText().toString());
                int sum = 0;
                TestJni jni = new TestJni();
                boolean flag = jni.init();
                if(flag){
                sum = jni.add(x, y);
                }
                tvSum.setText(String.valueOf(sum));
            }
        });
    }

}

8.XML文件(activity_main.xml)

<LinearLayout 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:orientation="horizontal"
    >

    <EditText
        android:id="@+id/et_x"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
         >

    </EditText>

    <TextView
        android:id="@+id/tv1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="+" >

     </TextView>
      <EditText
        android:id="@+id/et_y"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
         >
      </EditText>
      <Button
          android:id = "@+id/btn_add"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="="
          />
       <EditText
        android:id="@+id/et_sum"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
         >

      </EditText>

</LinearLayout>

程序运行结果如图

总结一下JNI开发基本步骤

①编写.java类

②生成.class文件

③生成.h文件

③查阅.h文件

  JNIEXPORT 和 JNICALL 是jni的宏

  函数前的注释Signature: ()Ljava/lang/String;中的括号含义为:表示函数的参数为空,Ljava/lang/String表示函数的返回值是java的String对象

④编写.c/cpp文件

⑤创建 Android.mk文件(和.c文件同级目录)

⑥编译生成.so文件

NDK开发中的一些常见错误及解决办法

一、常见的几个错误及其解决办法

1. android.mk文件不存在

错误代码形如:

AndroidNDK: Your APP_BUILD_SCRIPT points to an unknown file: ./jni/Android.mk

/cygdrive/h/heima6/jni2/ziliao/android-ndk-r7b/build/core/add-application.mk:133:* Android NDK: Aborting… 。 停止。

解决办法:

创建Android.mk文件。

2.android.mk文件的配置信息有错误

错误代码形如:

***Android NDK: Missing LOCAL_MODULE before including BUILD_SHARED_LIBRARY injni/Android.mk 。 停止。

解决办法:

修改Android.mk文件中的错误。有时候可能是一些看不见的特色字符导致,可以删除后重新建立一个。

3.c代码语法出现错误,编译不通过Error1.

错误代码形如:

make:* [obj/local/armeabi/objs/Hello/Hello.o]Error 1

解决办法:

检查C程序代码

4.java层c代码库没有找到

错误代码形如:

Causedby: java.lang.UnsatisfiedLinkError:Library Hell0 not found静态加载代码库的时候代码库没有找到.(调用库时出错)

解决办法:

检查库库的名字,看是否写错了。看

5.c代码函数签名出现错误(函数名出错)

错误代码形如:

Causedby: java.lang.UnsatisfiedLinkError: hello_from_c

解决办法:

C代码中函数名不合特定规范,改过来就行了。

  1. 其他隐含错误

    如:在C代码中视图去访问已经释放了的内存空间。

时间: 2024-12-24 16:01:35

android下NDK开发环境搭建及TestJNI入门实例完整过程的相关文章

Ubuntu 12.04 32位 eclipse android SDK NDK开发环境搭建

文章写作时间: 2017/04/05 一.软件包如下: 1.jdk 1.8(JAVA 开发及运行坏境) 2.eclipse(IDE工具) 3.ADT23.0(eclipse 开发安卓插件) 4.SDK24 (Android 开发环境) 5.NDK R10 (NDK开发环境) 下载链接 http://pan.baidu.com/s/1nvjYfnr 二.安装步骤 1.JDK安装 a.在/home/"用户名" 下新建文件夹"Java_JDK"(mkdir /home/&

Windows下NDK开发环境搭建

Cygwin 介绍 cygwin是windwos下的linux环境模拟器.   为什么需要cygwin?  因为NDK只能在Linux环境下运行. 安装流程 1.打开cygwin的可执行文件,执行扩展库安装地址. 我这里选择Install from Local Directory,因为扩展库我已经下载到本地了. 2.选择安装目录,目录名不能有空格或者中文 3.因为选择的是本地安装,所以需要指定插件包 4.选择需要安装的插件,Devel(编译),Shells(执行脚本) 5.安装完成后在点击桌面的

Android Studio NDK开发环境搭建

一.   下载安装Android studio 和 NDK 二.   在Android studio中配置NDK(和SDK配置一样) 三.   用Android studio建立一个工程,打开project,建立一个调用C的类,然后在mian文件夹下建立一个jni文件夹. 四.   打开cmd ,输入cd 工程文件夹路径,如cd C:Users\CFF\Desktop\MyApplication\app\src\main\java,然后按回车. 五.   输入javah –jni +调用C的类路

Windows下Android+NDK开发环境搭建(JDK[8u45]+Eclipse+Android SDK[r24.1.2]+ADT+NDK[r10d])

一.Android开发环境搭建 1.安装JDK. (1)简介:JDK,即Java Development Kit,是Java语言的软件开发工具包.JRE,即Java Runtime Environment,是Java的运行环境,是面向Java的使用者而非开发者. (2)下载:点击打开链接(Oracle官网),选择对应系统的版本,我下载的是jdk-8u45-windows-i586.exe. (3)安装:双击进行安装,程序刚安装时设置的安装目录为JDK的安装目录,中途需要设置JRE的安装目录.为进

NDK在windows下的开发环境搭建及开发过程

在Android应用的开发project中.无论是游戏还是普通应用.都时常会用到.so即动态链接库,关于.so是什么玩意儿,有什么优点.这个大家能够在网上查一下,本人不做过多解释. .so本是linux下的文件类型,所以编译.so必需要在linux环境下,那么怎样在win下进行编译呢?随便在网上搜下,教程也是五花八门,不清不楚,没有一定功底,即便看着教程到最后预计还是功败垂成,更别说刚開始学习的人,看了保证头晕眼花,本人也是依据网上的一些样例.总结了一个个人觉得还算比較简单的一个.so的编译方法

cocos搭建android下的开发环境

没想到cocos3.2也出现了一点bug,还要经过一周晚上的努力,全部搞定.可以在android下使用啦 上个截图庆祝下 有需要的可以看http://item.taobao.com/item.htm?id=40745006457 cocos搭建android下的开发环境,布布扣,bubuko.com

基于QT 5.7.0 for Android 的 Windows 开发环境搭建

基于QT 5.7.0 for Android 的 Windows 开发环境搭建 本文属于转载原文地址https://my.oschina.net/armsky/blog/740645 一.下载软件1.jdk:jdk-8u102-windows-i586.exehttp://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.htmlhttp://download.oracle.com/otn-pub/ja

Ma下java开发环境搭建

Mac下Java开发环境搭建 mac配置java开发环境:eclipse + jdk1.8 前言 搭建开发环境之前,先了解一下一些概念:java,javaSE,javaEE,JVM,JDK,JRE java发展历程 JavaSE.JavaME.JavaEE三者之间的关系JavaSE(J2SE):(Java2 Platform Standard Edition,java平台标准版)JavaEE(J2EE):(Java 2 Platform,Enterprise Edition,java平台企业版)

ubuntu下php开发环境搭建,nginx+(cgi)php5fpm+memcached+xdebug

由于只是开发环境,所以都是选择比较简单的apt-get安装方式 ,但中间也遇到一点问题. 首先安装nginx nginx的安装和配置其实很简单,nginx本身非常轻量级, 直接 sudo apt-get install nginx 就可以了 他的配置文件是在/etc/nginx/里面,网站项目路径是在/var/www里面,安装之后一定要确保nginx的启动账户有对网站目录的访问权限,否则会报错. 第二步,安装cgi linux底下的cgi程序非常多,在这里我选择的是php5-fpm 方便  在这