`
king_tt
  • 浏览: 2116646 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

【移动开发】如何使用ndk和jni

 
阅读更多

概述

Android系统的底层库由c/c++编写,上层Android应用程序通过Java虚拟机调用底层接口,衔接底层c/c++库与Java应用程序间的接口正是JNI(Java Native Interface)。本文将描述如何在Ubuntu下配置Android JNI的开发环境,以及如何编写一个简单的c函数库和JNI接口,并通过编写Java程序调用这些接口,最终运行在模拟器上的过程。


环境配置

1. 安装jdk 1.6

(1) 从jdk官方网站http://www.oracle.com/technetwork/java/javase/downloads/jdk-6u29-download-513648.html

下载jdk-6u29-linux-i586.bin文件。

(2) 执行jdk安装文件

$ chmod a+x jdk-6u29-linux-i586.bin

$ jdk-6u29-linux-i586.bin

(3) 配置jdk环境变量

$ sudo vim /etc/profile

#JAVA EVIRENMENT

export JAVA_HOME=/usr/lib/java/jdk1.6.0_29

export JRE_HOME=$JAVA_HOME/jre

export CLASSPATH=$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH

export PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$PATH

保存后退出编辑,并重启系统。

(4) 验证安装

$ java -version

java version "1.6.0_29"

Java(TM) SE Runtime Environment (build 1.6.0_29-b11)

Java HotSpot(TM) Server VM (build 20.4-b02, mixed mode)


$ javah

用法:javah [选项] <类>

其中[选项] 包括:

-help 输出此帮助消息并退出

-classpath <路径> 用于装入类的路径

-bootclasspath <路径> 用于装入引导类的路径

-d <目录> 输出目录

-o <文件> 输出文件(只能使用-d 或-o 中的一个)

-jni 生成JNI样式的头文件(默认)

-version 输出版本信息

-verbose 启用详细输出

-force 始终写入输出文件

使用全限定名称指定<类>(例如,java.lang.Object)。

2. 安装Android开发环境

ubuntu下安装android应用程序开发环境与windows类似, 依次安装好以下软件即可:

(1) Eclipse

(2) AVD

(3) Android SDK

与windows下安装唯一不同的一点是,下载这些软件的时候要下载Linux版本的安装包。

安装好以上android应用程序的开发环境后,还可以选择是否需要配置emulator和adb工具的环境变量,以方便在进行JNI开发的时候使用。

配置步骤如下:

把emulator所在目录android-sdk-linux/tools以及adb所在目录android-sdk-linux/platform-tools添加到环境变量中,android-sdk-linux指android sdk安装包android-sdk_rxx-linux的解压目录。

$ sudo vim /etc/profile

export PATH=~/software/android/android-sdk-linux/tools:$PATH

export PATH=~/software/android/android-sdk-linux/platform-tools:$PATH

编辑完毕后退出,并重启生效。


3. 安装NDK

NDK是由android提供的编译android本地代码的一个工具。

(1) 从android ndk官网http://developer.android.com/sdk/ndk/index.html下载ndk,目前最新版本为android-ndk-r6b-linux-x86.tar.bz2.

(2) 解压ndk到工作目录:

$ tar -xvf android-ndk-r6b-linux-x86.tar.bz2

$ sudo mv android-ndk-r6b /usr/local/ndk

(3) 设置ndk环境变量

$ sudo vim /etc/profile

export PATH=/usr/local/ndk:$PATH

编辑完毕后保存退出,并重启生效。

(4) 验证安装

$ cd /usr/local/ndk/samples/hello-jni/

$ ndk-build

Gdbserver : [arm-linux-androideabi-4.4.3] libs/armeabi/gdbserver

Gdbsetup : libs/armeabi/gdb.setup

Install : libhello-jni.so => libs/armeabi/libhello-jni.so


JNI实现

我们需要定义一个符合JNI接口规范的c/c++接口,这个接口不用太复杂,例如输出一个字符串。接下来,则需要把c/c++接口的代码文件编译成共享库(动态库).so文件,并放到模拟器的相关目录下。最后,启动Java应用程序,就可以看到最终效果了。

3.1.编写Java应用程序代码

(1) 启动Eclipse,新建android工程

Project:JNITest

Package:org.tonny.jni

Activity:JNITest

(2) 编辑资源文件

编辑res/values/strings.xml文件如下:

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="hello">Hello World, JNITestActivity!</string>
    <string name="app_name">JNITest</string>
    <string name="btn_show">Show</string>

</resources>

编辑res/layout/activity_jnitest.xml文件如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello" />

    <EditText
        android:id="@+id/ed_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginLeft="5dp"
        android:layout_marginRight="5dp" />

    <Button
        android:id="@+id/btn_show"
        android:layout_width="109dp"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="@string/btn_show" />

</LinearLayout>

在主界面上添加了一个EditText控件和一个Button控件。

(3) 编辑JNITest.java文件

public class JNITest extends Activity {

    static {
        System.loadLibrary("JNITest");
    }

    private native String GetReply();

    private EditText edtName;
    private Button btnShow;

    String reply;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_jnitest);

        reply = GetReply();

        edtName = (EditText) this.findViewById(R.id.ed_name);

        btnShow = (Button) this.findViewById(R.id.btn_show);

        btnShow.setOnClickListener(new Button.OnClickListener() {

            public void onClick(View arg0) {

                edtName.setText(reply);

            }

        });

    }

}

看这一段代码:

    static {
        System.loadLibrary("JNITest");
    }

static表示在系统第一次加载类的时候,先执行这一段代码,在这里表示加载动态库libJNITest.so文件。

再看这一段:

private native String GetReply();

native表示这个方法由本地代码定义,需要通过jni接口调用本地c/c++代码。

btnShow.setOnClickListener(new Button.OnClickListener() {

            public void onClick(View arg0) {

                edtName.setText(reply);

            }

        });

这段代码表示点击按钮后,把native方法的返回的字符串显示到EditText控件。

(4) 编译工程,生成.class文件。


3.2.用javah工具生成符合JNI规范的C语言头文件

在终端中,进入android工程所在的bin目录

$ cd ~/project/Android/JNITest/bin

用ls命令查看,可以看到bin目录下有个classes目录,其目录结构为classes/org/tonny/jni,即classes的子目录结构是android工程的包名org.tonny.jni。

注意,准备执行javah命令的时候,必须进入到org/tonny/jni的上级目录,即classes目录,否则javah会提示找不到相关的java类。

下面继续:

$ cd classes

$ javah org.tonny.jni.JNITest

$ ls

org org_tonny_jni_JNITest.h

执行javah org.tonny.jni.JNITest命令,在classes目录下会生成org_tonny_jni_JNITest.h 头文件。如果不进入到classes目录下的话,也可以这样:

$ javah -classpath ~/project/Android/JNITest/bin/classes org.tonny.jni.JNITest

-classpath 参数表示装载类的目录。


3.3.编写c/c++代码

生成org_tonny_jni_JNITest.h 头文件后,就可以编写相应的函数代码了。在android工程目录下新建jni目录,即~/project/Android/JNITest/jni,把org_tonny_jni_JNITest.h头文件拷贝(剪切)到jni目录下,并在jni目录下新建org_tonny_jni_JNITest.c文件,编辑代码如下:

 #include<jni.h> 
#include<string.h>
#include"org_tonny_jni_JNITest.h"

JNIEXPORT jstring JNICALL Java_org_tonny_jni_JNITest_GetReply
(JNIEnv *env, jobject obj){
    return (*env)->NewStringUTF(env,(char*)"Hello,JNITest");
}

可以看到,该函数的实现相当简单,返回一个字符串为:"Hello,JNITest"


3.4.编写Android.mk文件

在~/project/Android/JNITest/jni目录下新建Android.mk文件,android可以根据这个文件的编译参数编译模块。编辑Android.mk文件如下:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := libJNITest 

LOCAL_SRC_FILES := org_tonny_jni_JNITest.c

include $(BUILD_SHARED_LIBRARY)

LOCAL_MODULE 表示编译的动态库名称

LOCAL_SRC_FILES 表示源代码文件


3.5.用ndk工具编译并生成.so文件

进入到JNITest的工程目录,执行ndk-build命令即可生成libJNITest.so文件。

$ cd ~/project/Android/JNITest/

$ ndk-build

Invalid attribute name:

package

Install : libJNITest.so => libs/armeabi/libJNITest.so

可以看到,在工程目录的libs/armeabi目录下生成了libJNITest.so文件。

3.6.在模拟器上运行

(1) 首先,把android模拟器启动起来。进入到emulator所在目录,执行emulator命令:

$ cd ~/software/android/android-sdk-linux/tools

$ ./emulator @AVD-2.3.3-V10 -partition-size 512

AVD-2.3.3-V10表示你的模拟器名称,与在Eclipse->AVD Manager下的AVD Name对应,-partition-size表示模拟器的存储设备容量。

(2) 接下来,需要把libJNITest.so文件拷贝到模拟器的/system/lib目录下,执行以下命令:

$ cd ~/project/Android/JNITest/libs/armeabi/

$ adb remount

$ adb push libJNITest.so /system/lib

80 KB/s (10084 bytes in 0.121s)

当在终端上看到有80 KB/s (10084 bytes in 0.121s) 传输速度等信息的时候,说明拷贝成功。

(3) 在Eclipse下,右键点击JNITest工程,Run As->Android Application,即可在模拟器上启动程序。

在模拟器上点击【Show】按钮,即可看到Hello,JNITest,而这个字符串正是在org_tonny_jni_JNITest.c代码文件中所定义的。


3.7 在真机上运行

在真机上运行,没有在模拟器上面这么麻烦。需要注意的是,需要把app卸载,然后再重新安装一遍,否则so文件有可能不会被编译到apk中。


源码下载

http://pan.baidu.com/s/1qW5Ckgs


参考资料

http://www.2cto.com/kf/201111/111053.html

http://www.2cto.com/kf/201111/111052.html

http://bbs.51cto.com/thread-948244-1.html

分享到:
评论

相关推荐

    android_ndk_jni_dev_HelloNDK.zip

    android_ndk_jni_dev.zip 配套例子

    Android C++高级编程: 使用NDK

     《移动开发经典丛书·Android C++高级编程:使用NDK》介绍了原生应用开发、可用的原生API以及故障排除技术的详细叙述,包括用按步骤的指导和屏幕截图以帮助Android开发人员迅速达到开发原生应用的目的。...

    Android C++高级编程使用NDK

    《移动开发经典丛书:Android C++高级编程:使用NDK》提供了移植、开发以及利用Android平台上的C++和其他原生代码所需要的知识和技能,以便于运行图形化的高级应用和更复杂的原生应用。 内容简介  Android是移动...

    pro-android-c-w-ndk-master.tar

    《移动开发经典丛书:Android C++高级编程:使用NDK》提供了移植、开发以及利用Android平台上的C++和其他原生代码所需要的知识和技能,以便于运行图形化的高级应用和更复杂的原生应用。 内容简介  Android是移动...

    Android C++高级编程:使用NDK_Onur Cinar, 于红PDF电子书下载 带书签目录 完整版

    丛书名: 移动开发经典丛书 出版社:清华大学出版社 ISBN:9787302343011 上架时间:2013-12-30 出版日期:2014 年1月 开本:16开 页码:344 版次:1-1 第1章 Android平台上的C++入门 1 1.1 Microsoft Windows 1 ...

    Android应用源码史上最强NDK入门项目实战-IT计算机-毕业设计.zip

    Android应用源码开发Demo,主要用于毕业设计学习。

    Android JNI详解,让你彻底了解JNI (上)

    Android开发中,随着对移动程序的安全性、性能等方面的重视,JNI技术也越发重要。如今,多数企业在招聘中、高级程序员时,基本上都要求熟悉JNI开发,所以,掌握JNI技术,也是我们迈进心仪企业的必备条件。本套课程共...

    Android JNI精细化讲解,让你彻底了解JNI(中)

    Android开发中,随着对移动程序的安全性、性能等方面的重视,JNI技术也越发重要。如今,多数企业在招聘中、高级程序员时,基本上都要求熟悉JNI开发,所以,掌握JNI技术,也是我们迈进心仪企业的必备条件。本套课程共...

    Android JNI详解,让你彻底了解JNI (下)

    Android开发中,随着对移动程序的安全性、性能等方面的重视,JNI技术也越发重要。如今,多数企业在招聘中、高级程序员时,基本上都要求熟悉JNI开发,所以,掌握JNI技术,也是我们迈进心仪企业的必备条件。本套课程共...

    《Android应用开发揭秘》源码

    精通Java、C、C++等语言,专注于移动通信软件开发,在机顶盒软件开发和MTK平台软件开发方面有非常深厚的积累。2007年获得中国软件行业协会游戏软件分会(CGIA)认证及国际游戏开发教育联合会国际认证。曾经领导和参与...

    《Android应用开发揭秘》附带光盘代码.

     16.2 安装和配置NDK开发环境  16.2.1 系统和软件需求  16.2.2 NDK开发环境搭建  16.2.3 编译第一个NDK程序  16.3 AndroidNDK开发  16.3.1 JNI接口设计  16.3.2 使用C\C++实现本地  方法  16.3 编译C\C++...

    【推荐】超全的移动安全自学资料精编合集(43份).zip

    Android安全开发基础: 图形界面(UI)和碎片(Fragment)(上) Android安全开发基础: 图形界面(UI)和碎片(Fragment)(下) Android安全开发基础: 持久化技术 Android安全开发基础: 多媒体 Android安全开发基础:...

    移动安全系列教学下载共43份.zip

    Android安全开发基础--10--图形界面(UI)和碎片(Fragment)(上).pdf Android安全开发基础--11--图形界面(UI)和碎片(Fragment)(下).pdf Android安全开发基础--12--持久化技术.pdf Android安全开发基础--13-...

    vlfeat_android:带有OpenCVAndrioid下的VLfeat,带有VLfeat-v0.9.19的JNINDK

    以支持移动开发,尤其是在分类,检测和图像处理方面我所做的(VLfeat,OpenCV,Android) 有一些步骤可以将所有源代码移植到andriod,我在这里使用的是带有OpenCVAndriod JNI。 我复制了vlfeat的源代码,构建了一个...

    Android应用开发揭秘pdf高清版

    最重要的是还全面介绍了如何利用原生的C,C++(NDK)和Python、Lua等脚本语言(AndroidScriptingEnvironment)来开发Android应用,《Android应用开发揭秘》实战性强,书中的每个知识点都有配精心设计的示例,尤为...

    Android开发艺术探索.任玉刚(带详细书签).pdf

    第14章 JNI和NDK编程 473 14.1 JNI的开发流程 474 14.2 NDK的开发流程 478 14.3 JNI的数据类型和类型签名 484 14.4 JNI调用Java方法的流程 486 第15章 Android性能优化 489 15.1 Android的性能优化方法 490 ...

    ccv_android:CCV + Android + NDK,可移植的CCV到android

    该项目的目标是将它们移植到Android平台中,以支持移动开发,尤其是在分类,检测和图像处理方面 我做了什么(CCV,OpenCV,Android) 有一些步骤将所有源代码移植到Android,我在这里使用的是带有OpenCVAndroid ...

    NetSdk-release

    千眸NetSdk-release版,千眸 Android NetSdk是一套基于Android 5.0及以上版本设备的应用... 您可以使用本套SDK开发Android系统移动设备监控应用,您可以轻松远程操作设备,完成功能丰富,交互性强的监控类应用程序APP。

Global site tag (gtag.js) - Google Analytics