如何在Android下使用JNI

如上面所说

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

  2.环境配置

  2.1.安装jdk1.6
  (1)从jdk官方网站下载jdk-6u29-linux-i586.bin文件。
  (2)执行jdk安装文件
  [html] view plaincopyprint?
  01.$chmod a+x jdk-6u29-linux-i586.bin
  02.$jdk-6u29-linux-i586.bin
  $chmod a+x jdk-6u29-linux-i586.bin
  $jdk-6u29-linux-i586.bin
  (3)配置jdk环境变量

  [html] view plaincopyprint?
  01.$sudo vim /etc/profile
  02.#JAVAEVIRENMENT
  03.exportJAVA_HOME=/usr/lib/java/jdk1.6.0_29
  04.exportJRE_HOME=$JAVA_HOME/jre
  05.exportCLASSPATH=$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH
  06.exportPATH=$JAVA_HOME/bin:$JRE_HOME/bin:$PATH
  $sudo vim /etc/profile
  #JAVAEVIRENMENT
  exportJAVA_HOME=/usr/lib/java/jdk1.6.0_29
  exportJRE_HOME=$JAVA_HOME/jre
  exportCLASSPATH=$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH
  exportPATH=$JAVA_HOME/bin:$JRE_HOME/bin:$PATH
  保存后退出编辑,并重启系统。

  (4)验证安装

  [html] view plaincopyprint?
  01.$java -version
  02.javaversion "1.6.0_29"
  03.Java(TM)SE Runtime Environment (build 1.6.0_29-b11)
  04.JavaHotSpot(TM) Server VM (build 20.4-b02, mixed mode)
  05.$javah
  06.用法:javah[选项]<类>
  07.其中[选项]包括:
  08.-help输出此帮助消息并退出
  09.-classpath<路径>用于装入类的路径
  10.-bootclasspath<路径>用于装入引导类的路径
  11.-d<目录>输出目录
  12.-o<文件>输出文件(只能使用-d或-o中的一个)
  13.-jni生成JNI样式的头文件(默认)
  14.-version输出版本信息
  15.-verbose启用详细输出
  16.-force始终写入输出文件
  17.使用全限定名称指定<类>(例
  18.如,java.lang.Object)。
  $java -version
  javaversion "1.6.0_29"
  Java(TM)SE Runtime Environment (build 1.6.0_29-b11)
  JavaHotSpot(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.2.安装android应用程序开发环境
  ubuntu下安装android应用程序开发环境与windows类似,依次安装好以下软件即可:
  (1)Eclipse
  (2)ADT
  (3)AndroidSDK
  与windows下安装唯一不同的一点是,下载这些软件的时候要下载Linux版本的安装包。
  安装好以上android应用程序的开发环境后,还可以选择是否需要配置emulator和adb工具的环境变量,以方便在进行JNI开发的时候使用。配置步骤如下:
  把emulator所在目录android-sdk-linux/tools以及adb所在目录android-sdk-linux/platform-tools添加到环境变量中,android-sdk-linux指androidsdk安装包android-sdk_rxx-linux的解压目录。
  [plain] view plaincopyprint?
  01.$sudo vim /etc/profile
  02.exportPATH=~/software/android/android-sdk-linux/tools:$PATH
  03. exportPATH=~/software/android/android-sdk-linux/platform-tools:$PATH
  $sudo vim /etc/profile
  exportPATH=~/software/android/android-sdk-linux/tools:$PATH
  exportPATH=~/software/android/android-sdk-linux/platform-tools:$PATH
  编辑完毕后退出,并重启生效。

  2.3.安装NDK
  NDK是由android提供的编译android本地代码的一个工具。
  (1)从androidndk官网http://developer.android.com/sdk/ndk/index.html下载ndk,目前最新版本为android-ndk-r6b-linux-x86.tar.bz2.
  (2)解压ndk到工作目录:
  [plain] view plaincopyprint?
  01.$tar -xvf android-ndk-r6b-linux-x86.tar.bz2
  02.$sudo mv android-ndk-r6b /usr/local/ndk
  $tar -xvf android-ndk-r6b-linux-x86.tar.bz2
  $sudo mv android-ndk-r6b /usr/local/ndk
  (3)设置ndk环境变量

  [plain] view plaincopyprint?
  01.$sudo vim /etc/profile
  02.exportPATH=/usr/local/ndk:$PATH
  $sudo vim /etc/profile
  exportPATH=/usr/local/ndk:$PATH

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

  (4)验证安装

  [plain] view plaincopyprint?
  01.$ cd/usr/local/ndk/samples/hello-jni/
  02.$ ndk-build
  03.Gdbserver : [arm-linux-androideabi-4.4.3] libs/armeabi/gdbserver
  04.Gdbsetup : libs/armeabi/gdb.setup
  05.Install : libhello-jni.so => libs/armeabi/libhello-jni.so
  $ 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

  3.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文件如下:

  

  编辑res/layout/main.xml文件
  我们在主界面上添加了一个EditText控件和一个Button控件。

  (3)编辑JNITest.java文件

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

  再看这一段:

  [java] view plaincopyprint?
  01.privatenativeString GetReply();
  privatenativeString GetReply();
  native表示这个方法由本地代码定义,需要通过jni接口调用本地c/c++代码。

  [java] view plaincopyprint?
  01.publicvoidonClick(View arg0) {
  02.edtName.setText(reply);
  03.}
  publicvoidonClick(View arg0) {
  edtName.setText(reply);
  }

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

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

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

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

  [plain] view plaincopyprint?
  01.$cd ~/project/Android/JNITest/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类。

  下面继续:

  [plain] view plaincopyprint?
  01.$cd classes
  02.$javah org.tonny.jni.JNITest
  03.$ls
  04.org org_tonny_jni_JNITest.h
  $cd classes
  $javah org.tonny.jni.JNITest
  $ls
  org org_tonny_jni_JNITest.h

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

  [plain] view plaincopyprint?
  01.$javah -classpath ~/project/Android/JNITest/bin/classesorg.tonny.jni.JNITest
  $javah -classpath ~/project/Android/JNITest/bin/classesorg.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文件,编辑代码如下:

  [cpp] view plaincopyprint?
  01.#include<jni.h>
  02.#include<string.h>
  03.#include"org_tonny_jni_JNITest.h"
  04.
  05.
  06.JNIEXPORTjstring JNICALLJava_org_tonny_jni_JNITest_GetReply
  07.(JNIEnv *env, jobject obj){
  08.return(*env)->NewStringUTF(env,(char*)"Hello,JNITest");
  09.}
  #include<jni.h>
  #include<string.h>
  #include"org_tonny_jni_JNITest.h"

  JNIEXPORTjstring JNICALLJava_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文件如下:

  [plain] view plaincopyprint?
  01.LOCAL_PATH:= $(call my-dir)
  02.include$(CLEAR_VARS)
  03.LOCAL_MODULE := libJNITest
  04.LOCAL_SRC_FILES:= org_tonny_jni_JNITest.c
  05.include$(BUILD_SHARED_LIBRARY)
  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文件。

  [plain] view plaincopyprint?
  01.$cd ~/project/Android/JNITest/
  02.$ndk-build
  03.Invalidattribute name:
  04.package
  05.Install : libJNITest.so => libs/armeabi/libJNITest.so
  $cd ~/project/Android/JNITest/
  $ndk-build
  Invalidattribute name:
  package
  Install : libJNITest.so => libs/armeabi/libJNITest.so
  可以看到,在工程目录的libs/armeabi目录下生成了libJNITest.so文件。

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

  [plain] view plaincopyprint?
  01.$cd ~/software/android/android-sdk-linux/tools
  02.$./emulator @AVD-2.3.3-V10 -partition-size 512
  $cd ~/software/android/android-sdk-linux/tools
  $./emulator @AVD-2.3.3-V10 -partition-size 512
  AVD-2.3.3-V10表示你的模拟器名称,与在Eclipse->AVDManager下的AVDName对应,-partition-size表示模拟器的存储设备容量。

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

  [plain] view plaincopyprint?
  01.$cd ~/project/Android/JNITest/libs/armeabi/
  02.$adb remount
  03.$adb push libJNITest.so /system/lib
  04.80 KB/s (10084 bytes in 0.121s)
  $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)在终端上执行JNITest程序,这个我们可以在Eclipse下,右键点击JNITest工程,RunAs->Android Application,即可在模拟器上启动程序
温馨提示:答案为网友推荐,仅供参考
android studio JNI 调试 (debug)
JNI调试需要LLDB调试器和NDK(Native Development Kit)的支持。确保你的Android Studio已经安装了LLDB和NDK。如果没有,可以通过Android Studio的“SDK Manager”进行安装。配置JNI调试 在“Run”菜单中,选择“Edit Configurations”。找到你的应用配置,切换到“

如何在Android下使用JNI
安装好以上android应用程序的开发环境后,还可以选择是否需要配置emulator和adb工具的环境变量,以方便在进行JNI开发的时候使用。配置步骤如下: 把emulator所在目录android-sdk-linux\/tools以及adb所在目录android-sdk-linux\/platform-tools添加到环境变量中,android-sdk-linux指androidsdk安装包android-sdk_rxx-linux的解压目录。

Android Studio cmake编译FFmpeg以及Jni调用
在Android Studio中使用cmake编译FFmpeg以及进行Jni调用的步骤如下:一、编译FFmpeg 安装与配置NDK:下载并解压Android NDK。配置环境变量,确保在命令行中可以访问NDK工具。编译FFmpeg源代码:下载FFmpeg源代码。修改configure文件以适应Android平台,如设置交叉编译工具链等。编写build.sh脚本,用于编译FFmpeg。脚...

在android开发jni,为什么jni.h导不进来
确保你的Android.mk文件中包含了正确的LOCAL_C_INCLUDES路径,以包含JNI头文件。例如:makefileLOCAL_C_INCLUDES += $ 这行代码的作用是指定编译器在查找头文件时应该包含的目录。$是一个变量,它通常在你的NDK环境中被定义,指向包含jni.h等头文件的目录。4. 使用支持JNI的IDE: 如果你正在使用Eclip...

如何在android中启动二进制文件
一、通过NDK开发集成二进制文件(推荐)准备二进制文件:确保文件为Android支持的ABI格式,存放于项目libs\/<ABI>\/目录;若需适配多处理器,在Application.mk中配置APP_ABI := all。通过JNI调用:在Java层声明native方法,用System.loadLibrary("库名")加载二进制库;在C\/C++层实现启动二进制...

如何在Android Studio中导入JNI生成的.so库
首先在Android Studio工程的app目录下创建整个jni目录,jni目录里写Android.mk、Application.mk以及各类C\/C++和汇编源文件。然后跟原来一样,用ndk_build工具去编,然后工具会自动生成libs目录,里面还有每个你在Application.mk里所指定处理器架构的so文件。完成之后,编辑app目录下的build.gradle文件,为其...

Android 中Native方法是怎样调用的
通过jni接口调用native 步骤如下:1.创建一个 android project, 名字叫Why 2 在工程Why中添加一个Java类,class名为Jni。这个类是一个JNI接口的Java类,文件名为Jni.java。package com.yarin.android.Why;public class Jni { public native int getCInt();public native String getCString();} 3.将...

如何在android中启动二进制文件
在Android中启动二进制文件可以通过以下几种方法实现:通过NDK开发集成二进制文件:准备二进制文件,并确保其为Android支持的ABI格式,存放于项目libs\/<ABI>\/目录。若需适配多处理器,在Application.mk中配置APP_ABI := all。通过JNI调用,在Java层声明native方法,并使用System.loadLibrary("库名"...

android上如何运行使用汇编语言编程
在Android平台上使用汇编语言编程,一种常用的方法是通过NDK(Native Development Kit)在JNI(Java Native Interface)的C++代码中内联ARM汇编代码。具体来说,可以利用GCC编译器自带的__asm命令来实现。这种方法简洁且高效,能够直接将汇编代码嵌入到C++代码中,进而利用JNI与Java代码进行交互。不过,对于不同...

android中jni开发怎么生成头文件
利用Windows的cmd生成jni头文件 1.进入到你自己Android工程目录下的app\\build\\intermediates\\classes\\debug 2.然后Shift加鼠标右键,点击红色方框的内容 3.出现cmd命令行,输入如下命令 javah -jni com.example.lenovo.application.JniClass 4.会在当前目录生成*.h头文件,把它拷贝进jni目录就可以了。jni...

相似回答
大家正在搜