当前位置:首页 » 安卓系统 » androidjnieclipse

androidjnieclipse

发布时间: 2022-05-05 16:03:44

❶ 如何在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 plainprint?
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 plainprint?
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 plainprint?
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 plainprint?
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 plainprint?
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 plainprint?
01.$sudo vim /etc/profile
02.exportPATH=/usr/local/ndk:$PATH
$sudo vim /etc/profile
exportPATH=/usr/local/ndk:$PATH

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

(4)验证安装

[plain] view plainprint?
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 plainprint?
01.privatenativeString GetReply();
privatenativeString GetReply();
native表示这个方法由本地代码定义,需要通过jni接口调用本地c/c++代码。

[java] view plainprint?
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 plainprint?
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 plainprint?
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 plainprint?
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 plainprint?
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 plainprint?
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 plainprint?
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 plainprint?
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 plainprint?
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 jni abifilters为什么没产生文件

android studio 中简单的jni开发
Let’s Go!!!
准备工作不再需要什么cgwin来编译ndk(太特么操蛋了),现在只需要你下载一下NDK的库就ok了,然后你也可以去离线下载http://www.androiddevtools.cn最新版,这里吐槽一下android studio对NDK的支持还有待提高。
效果
看下今天的效果:(安卓jni获取 apk的包名及签名信息)

必须的步骤
1.配置你的ndk路径(local.properties)
ndk.dir=E:\Android\sdk\android-ndk-r11b-windows-x86_64\android-ndk-r11b
2.grale配置使用ndk(gradle.properties)
android.useDeprecatedNdk=true
3.在mole下的build.gradle添加ndk以及jni生成目录
ndk{
moleName “JNI_ANDROID”
abiFilters “armeabi”, “armeabi-v7a”, “x86” //输出指定三种abi体系结构下的so库,目前可有可无。
}
sourceSets.main{
jniLibs.srcDirs = [‘libs’]
}
准备工作做好了开始写代码:(jni实现获取应用的包名和签名信息)
步骤1:先写要实现本地方法的类,及加载库(JNI_ANDROID也就是ndk 里面配的moleName)
?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

<code class="hljs java">package com.losileeya.getapkinfo;

/**
* User: Losileeya ([email protected])
* Date: 2016-07-16
* Time: 11:09
* 类描述:
*
* @version :
*/
public class JNIUtils {
/**
* 获取应用的签名
* @param o
* @return
*/
public static native String getSignature(Object o);

/**
* 获取应用的包名
* @param o
* @return
*/
public static native String getPackname(Object o);

/**
* 加载so库或jni库
*/
static {
System.loadLibrary("JNI_ANDROID");
}
}</code>

注意我们 的加载c方法都加了native关键字,然后要使用jni下的c/c++文件就必须使用System.loadLibrary()。
步骤2:使用javah命令生成.h(头文件)
javah -jni com.losileeya.getapkinfo.JNIUtils
执行完之后你可以在mole下文件夹app\build\intermediates\classes\debug下看见生成的 .h头文件为:
com_losileeya_getapkinfo_JNIUtils.h
?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

<code class="hljs vala">/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_losileeya_getapkinfo_JNIUtils */

#ifndef _Included_com_losileeya_getapkinfo_JNIUtils
#define _Included_com_losileeya_getapkinfo_JNIUtils
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT jstring JNICALL Java_com_losileeya_getapkinfo_JNIUtils_getPackname(JNIEnv *, jobject, jobject);
JNIEXPORT jstring JNICALL Java_com_losileeya_getapkinfo_JNIUtils_getSignature(JNIEnv *, jobject, jobject);
#ifdef __cplusplus
}
#endif
#endif</jni.h></code>

在工程的main目录下新建一个名字为jni的目录,然后将刚才的.h文件剪切过来,当然文件名字是可以修改的
步骤3:根据.h文件生成相应的c/cpp文件
?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

<code class="hljs scala">//
// Created by Administrator on 2016/7/16.
//
#include <stdio.h>
#include <jni.h>
#include <stdlib.h>
#include "appinfo.h"
JNIEXPORT jstring JNICALL Java_com_losileeya_getapkinfo_JNIUtils_getPackname(JNIEnv *env, jobject clazz, jobject obj)
{
jclass native_class = env->GetObjectClass(obj);
jmethodID mId = env->GetMethodID(native_class, "getPackageName", "()Ljava/lang/String;");
jstring packName = static_cast<jstring>(env->CallObjectMethod(obj, mId));
return packName;
}

JNIEXPORT jstring JNICALL Java_com_losileeya_getapkinfo_JNIUtils_getSignature(JNIEnv *env, jobject clazz, jobject obj)
{
jclass native_class = env->GetObjectClass(obj);
jmethodID pm_id = env->GetMethodID(native_class, "getPackageManager", "()Landroid/content/pm/PackageManager;");
jobject pm_obj = env->CallObjectMethod(obj, pm_id);
jclass pm_clazz = env->GetObjectClass(pm_obj);
// 得到 getPackageInfo 方法的 ID
jmethodID package_info_id = env->GetMethodID(pm_clazz, "getPackageInfo","(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;");
jstring pkg_str = Java_com_losileeya_getapkinfo_JNIUtils_getPackname(env, clazz, obj);
// 获得应用包的信息
jobject pi_obj = env->CallObjectMethod(pm_obj, package_info_id, pkg_str, 64);
// 获得 PackageInfo 类
jclass pi_clazz = env->GetObjectClass(pi_obj);
// 获得签名数组属性的 ID
jfieldID signatures_fieldId = env->GetFieldID(pi_clazz, "signatures", "[Landroid/content/pm/Signature;");
jobject signatures_obj = env->GetObjectField(pi_obj, signatures_fieldId);
jobjectArray signaturesArray = (jobjectArray)signatures_obj;
jsize size = env->GetArrayLength(signaturesArray);
jobject signature_obj = env->GetObjectArrayElement(signaturesArray, 0);
jclass signature_clazz = env->GetObjectClass(signature_obj);
jmethodID string_id = env->GetMethodID(signature_clazz, "toCharsString", "()Ljava/lang/String;");
jstring str = static_cast<jstring>(env->CallObjectMethod(signature_obj, string_id));
char *c_msg = (char*)env->GetStringUTFChars(str,0);

return str;
}</jstring></jstring></stdlib.h></jni.h></stdio.h></code>

注意:要使用前得先声明,方法名直接从h文件考过来就好了,studio目前还是很操蛋的,对于jni的支持还是不很好。
步骤4:给项目添加Android.mk和Application.mk
此步骤显然也是不必要的,如果你需要生成so库添加一下也好,为什么不呢考过去改一下就好了,如果你不写这2文件也是没有问题的,因为debug下也是有这些so库的。
好吧,勉强看一下这2货:
Android.mk
?

1
2
3
4
5

<code class="hljs ruby">LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := JNI_ANDROID
LOCAL_SRC_FILES =: appinfo.cpp
include $(BUILD_SHARED_LIBRARY)</code>

Application.mk
?

1
2

<code class="hljs makefile">APP_MODULES := JNI_ANDROID
APP_ABI := all</code>

android studio下External Tools的高级配置NDK一键javah,ndk生成so库
eclipse开发ndk的时候你可能就配置过javah,所以android studio也可以配置,是不是很兴奋:
Settings—>Tools—->External Tools就可以配置我们的终端命令了,别急一个一个来:
javah -jni 命令的配置(一键生成h文件)

我们先来看参数的配置:
1.Program:JDKPath\bin\javah.exe 这里配置的是javah.exe的路径(基本一致)
2.Parametes: -classpath . -jni -d MoleFileDir/src/main/jni FileClass这里指的是定位在Mole的jni文件你指定的文件执行jni指令<㖞�"/kf/ware/vc/" target="_blank" class="keylink">++IpDQo8cD48aW1nIGFsdD0="" src="/uploadfile/Collfiles/20160718/201607181017581505.png" title="\" />
我们同样来看参数的配置:
1.Program:E:\Android\sdk\android-ndk-r11b-windows-x86_64\android-ndk-r11b\ndk-build.cmd 这里配置的是ndk下的ndk-build.cmd的路径(自己去找下)
2.Working:MoleFileDir\src\main\
javap-s(此命令用于c掉java方法时方法的签名)

我们同样来看参数的配置:
1.Program:JDKPath\bin\javap.exe 这里配置的是javap.exe的路径(基本一致)
2.Parametes: -classpathMoleFileDir/build/intermediates/classes/debug -s FileClass 这里指的是定位到build的debug目录下执行 javap -s class文件
3.Working:MoleFileDir
这里介绍最常用的3个命令,对你的帮助应该还是很大的来看一下怎么使用:
javah -jni的使用:选中native文件—>右键—>External Tools—>javah -jni
效果如下:

是不是自动生成了包名.类名的.h文件。
ndk-build的使用:选中jni文件—>右键—>External Tools—>ndk-build
效果如下:

是不是一键生成了7种so库,你还想去debug目录下面去找吗
javap-s的使用:选中native文件—>右键—>External Tools—>javap-s
效果如下:

看见了每个方法下的descriptor属性的值就是你所要的方法签名。
3种一键生成的命令讲完了,以后你用到了什么命令都可以这样设置,是不是很给力。

❸ 如何在eclipse里面实现对android的jni中c/c++代码的单步调试

1、右键点击工程文件, 在properties -> C/C++ Build中:

2、完了设置断点(只能在C++中)就可以启动调试了。

❹ 在android开发jni,为什么jni.h导不进来

这个是个库,需要你有NDK或者源码编译环境,单纯的eclipse是不行的。。。会提示错误。

如果想编译成功,你可以参考如下Android.mk,关键是

LOCAL_C_INCLUDES +=

$(JNI_H_INCLUDE)

////////////////////////////////////////////////////////////////

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)


LOCAL_MODULE_TAGS := optional


LOCAL_MODULE:= liblocalmeida


LOCAL_SRC_FILES:=

libmedia_jni.cpp


LOCAL_SHARED_LIBRARIES :=

liblog

libutils

libandroid_runtime


LOCAL_C_INCLUDES +=

$(JNI_H_INCLUDE)


LOCAL_PROGUARD_ENABLED:= disabled


include $(BUILD_SHARED_LIBRARY)

❺ android 怎么调用jni里面的方法

调用jni里面的方法,过程如下:
第一步:
使用Java编写HelloWorld 的Android应用程序:

package com.lucyfyr;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;

public class HelloWorld extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Log.v("fresne", printJNI("I am HelloWorld Activity"));
}
static
{
//加载库文件
System.loadLibrary("HelloWorldJni");
}
//声明原生函数 参数为String类型 返回类型为String
private native String printJNI(String inputStr);
}

这一步我们可以使用eclipse来生成一个App;
因为eclipse会自动为我们编译此Java文件,后面要是用到。

第二步:
生成共享库的头文件:
进入到eclipse生成的Android Project中 :/HelloWorld/bin/classes/com/lucyfyr/ 下:
可以看到里面后很多后缀为.class的文件,就是eclipse为我们自动编译好了的java文件,其中就有:
HelloWorld.class文件。
退回到classes一级目录:/HelloWorld/bin/classes/
执行如下命令:
javah com.lucyfyr.HelloWorld
生成文件:com_lucyfyr_HelloWorld.h

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_lucyfyr_HelloWorld */
#ifndef _Included_com_lucyfyr_HelloWorld
#define _Included_com_lucyfyr_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_lucyfyr_HelloWorld
* Method: printJNI
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_lucyfyr_HelloWorld_printJNI
(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif

可以看到自动生成对应的函数:Java_com_lucyfyr_HelloWorld_printJNI
Java_ + 包名(com.lucyfyr) + 类名(HelloWorld) + 接口名(printJNI):必须要按此JNI规范来操作;
java虚拟机就可以在com.simon.HelloWorld类调用printJNI接口的时候自动找到这个C实现的Native函数调用。
当然函数名太长,可以在.c文件中通过函数名映射表来实现简化。

第三步:
实现JNI原生函数源文件:
新建com_lucyfyr_HelloWorld.c文件:

❻ android-ndk-r12b 在eclipse上怎么配置环境变量

一.插件的安装
如果你下载的是Eclipse Standard,请下载对应版本的cdt(我直接使用的是Eclipse IDE for C/C++ Developers 不要安装cdt的哦,我人比较懒,(*^__^*) 嘻嘻……)

比如 CDT 8.1.2 for Eclipse Juno cdt-master-8.1.2.zip,插入也比较简单和adt安装方式一样。再次不在赘述。以前NDK的版本还要Sequoyah插件(好久不更新了)来进行本地开发,现在不需要了。
二.环境的配置
1).首先进行配置NDK的配置,打开Eclipse的 Window->preferences->Android->NDK 然后选择路径你的NDK路径我的目录如下D:\android-sdk\android-ndk-r9 这个目录下有docs,sources,tests,samples e等等。 然后点击Apply,OK即可

2).首先导入hello—jni工程,然后点击右键->Properties你看见如下图所示的界面,这不是一个可以编译的NDK工程。你需要运行Cygwin或者在Eclipse配置。
我们首先使用Cygwin来生成程序的.so文件。打开Cygwin运行命令cd $ndk 这个ndk是之前你配置Cygwin环境变量设置的字符。然后cd samples/hello-jni
然后$ndk/ndk-build,你就可以看见生成.so文件成功的页面,这时候刷新或者clean工程 点击run as运行android程序。如下图:三.Eclipse 工程配置在Eclipse中开发c/c++
第二步运行完之后,你会发现你把Hello from JNI修改为AAA(随便写的) 这个字符串不好使,输出之后还是Hello from JNI 。你需要再次运行Cygwin才可以。当然这样比较麻烦,你可以在Eclipse中配置一下,就不要在运行Cygwin了。直接运行eclipse就可以了。
1)在HelloJni上右键->New->other(这一步一定是other)->c/c++>Convert to a C/C++ Project(Adds c/c++ Nature)->Next
然后选择你的工程HelloJni,选择转化为c工程,选择Makefile Project Cygwin GCC,点击Finish,再次点击Finish即可

2)你发现你的工程.c文件有很多错误。这个时候点击工程右键->Propreties这个时候你会发现和第二步的2)图多了二项 c/c++ Build 和c/c++ General.
点击 c/c++ Build
Use defult build commond的勾去掉 在Build command 填入bash <NDK路径>\ndk-build 例如bash D:\android-sdk\android-ndk-r9\ndk-build点击Apply OK即可。
点击c/c++ General
打开列表点击Paths and Symbols 在Includes 你看见Assembly GNU C (如果你在1)步选择的C++project还会有GNU C++) .这个时候要选择你所要的依赖库,由于hello-jni不需要过多的库文件所以
只需要点击Add D:\android-sdk\android-ndk-r9\platforms\android-9\arch-arm\usr\include 这样你就可以直接修改在Run as了。Ok成功运行。

❼ 安卓开发什么时候使用jni

android JNI是连接android Java部分和C/C++部分的纽带,完整使用JNI需要Java代码和C/C++代码。其中C/C++代码用于生成库文件,Java代码用于引用C /C++库文件以及调用C/C++方法。

android Java部分代码:

jnitest.java
02
03packagecom.hello.jnitest;
04
05
06
07importandroid.app.Activity;
08
09importandroid.os.Bundle;
10
11
12
{
14
15/**.*/
16
17@Override
18
19publicvoidonCreate(BundlesavedInstanceState){
20
21super.onCreate(savedInstanceState);
22
23setContentView(R.layout.main);
24
25Naddtest=newNadd();
26
27setTitle("TheNativeAddResultis"+String.valueOf(test.nadd(10,20)));
28
29}
30
31}
32
33Nadd.java
34
35packagecom.hello.jnitest;
36
37
38
39publicclassNadd{
40
41static{
42
43System.loadLibrary("hello_jni");
44
45}
46
47
48
49publicnativeintnadd(inta,intb);
50
51}

Java代码说明:

1)jnitest.java是一个activity的类对象,在该类对象中生成调用JNI函数的类对象,同时调用JNI方法,最后将JNI方法的结果显示到标题栏上;

2)Nadd.java是一个引用和声明JNI库和函数的类,其中System.loadLibrary();函数用来引用JNI库,默认JNI库放在 android系统的/system/lib/目录下;public nadd int nadd(int a, int b);为声明需要在java程序中使用的JNI库中的函数;

JNI中java部分的代码到此就结束了,总结一下在java代码中需要做两件事:

1)使用System.loadLibrary()函数来引用JNI库;

2)声明调用JNI库的函数且前面添加native关键字;


android C/C++部分代码:

01#defineLOG_TAG"hello-JNI"
02#include<stdio.h>
03#include<stdlib.h>
04#include<unistd.h>
05#include<sys/types.h>
06#include<sys/stat.h>
07#include<fcntl.h>
08#include<assert.h>
09#include"jni.h"
10#include"JNIHelp.h"
11#include"android_runtime/AndroidRuntime.h"
12staticjintcom_hello_jnitest_jnitest_nadd(JNIEnv*env,jobjectobj,jinta,jintb)
13{
14return(a*b);
15}
[]={
17{"nadd","(II)I",(void*)com_hello_jnitest_jnitest_nadd},
18};
19staticintregister_android_test_hello(JNIEnv*env)
20{
21returnandroid::AndroidRuntime::registerNativeMethods(env,"com/hello/jnitest/Nadd",gMethods,NELEM(gMethods));
22}
23jintJNI_OnLoad(JavaVM*vm,void*reserved)
24{
25JNIEnv*env=NULL;
26if(vm->GetEnv((void**)&env,JNI_VERSION_1_4)!=JNI_OK){
27printf("ErrorGetEnv ");
28return-1;
29}
30assert(env!=NULL);
31if(register_android_test_hello(env)<0){
32printf("register_android_test_helloerror. ");
33return-1;
34}
35returnJNI_VERSION_1_4;
36}

JNI C/C++代码说明:

1)JNI_OnLoad()函数。该函数在Java程序调用System.loadLibrary()时,被调用执行,用于向JavaVM注册JNI函数等。在本例中首先通过参数JavaVM(Java虚拟机指针)获取当前应用程序所在的线程,即:JNIEnv。再通过调用 android::AndroidRuntime::registerNativeMethods()注册native实现的函数指针。

2)JNI函数和Java调用函数的映射关系。使用JNINativeMethod将java调用的函数名与JNI实现的函数名联系在一起;

3)JNI函数实现;


Android.mk代码:

1LOCAL_PATH:=$(callmy-dir)
2include$(CLEAR_VARS)
3LOCAL_PRELINK_MODULE:=false
4LOCAL_SRC_FILES:=
5com_hello_jnitest.cpp
6LOCAL_SHARED_LIBRARIES:=
7libandroid_runtime
8LOCAL_MODULE:=libhello_jni
9include$(BUILD_SHARED_LIBRARY)

需要注意的是:

1)JNI C/C++部分的代码需要在android源代码树上进行编译,编译完成后我的做法是直接将生成的.so通过adb push方法上传到android虚拟机的/system/lib/目录下;

2)java代码可以在eclipse下直接编译且在虚拟机上执行;


编译JNI C/C++部分代码(在android内核源代码根目录下):

#make libhello_jni

之后在out/target/proct/generic/system/lib/目录下生成libhello_jni.so


上传libhello_jni.so到android虚拟机:

#adb push out/target/proct/generic/system/lib/libhello_jni.so /system/lib

注意:此时有可能出现Out of Memory的错误提示。当出现如上错误提示时,需要使用#adb remount重新加载一下就可以了。

另外,也有可能直接使用eclipse启动android虚拟机时出现上述错误且使用#adb remount也出现的情况,此时需要手动启动android虚拟机,如:#emulator -avd xxx -partition-size 128,之后在使用#adb push就可以了。

❽ 如何在Android Studio中导入JNI生成的.so库

由于在原来的ADT的Eclipse环境中,用ndk_build工具生成了相应的各个.so库文件之后,eclipse工具就会自动把这些库导入到apk中。而Android Studio目前为止(0.86版本)还无法做到那么自动,但是我们可以通过以下方式进行。

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

完成之后,编辑app目录下的build.gradle文件,为其添加以下代码:
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}

完整的build.gradle文件如下所示:

apply plugin: 'com.android.application'

android {
compileSdkVersion 20
buildToolsVersion "20.0.0"

defaultConfig {
applicationId "com.adwo.gamecenter.civetcoffeegamecenter"
minSdkVersion 9
targetSdkVersion 20
versionCode 1
versionName "1.0"
}
buildTypes {
release {
runProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
}

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:20.0.0'
}

❾ 不用gdb,如何在eclipse里面实现对android的JNI中C/C++代码的单步调试

1、右键点击工程文件, 在properties -> C/C++ Build中:

❿ android jni程序(c++)如何编译适用于arm-v8指令集的32位程序

可以看到Android上层的Application和ApplicationFramework都是使用Java编写,

底层包括系统和使用众多的LIiraries都是C/C++编写的。

所以上层Java要调用底层的C/C++函数库必须通过Java的JNI来实现。

下面将学习Android是如何通过Jni来实现Java对C/C++函数的调用。以HelloWorld程序为例:

第一步:

使用Java编写HelloWorld 的Android应用程序:

package com.lucyfyr;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;

public class HelloWorld extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Log.v("fresne", printJNI("I am HelloWorld Activity"));
}
static
{
//加载库文件
System.loadLibrary("HelloWorldJni");
}
//声明原生函数 参数为String类型 返回类型为String
private native String printJNI(String inputStr);
}

这一步我们可以使用eclipse来生成一个App;

因为eclipse会自动为我们编译此Java文件,后面要是用到。

第二步:

生成共享库的头文件:

进入到eclipse生成的Android Project中 :/HelloWorld/bin/classes/com/lucyfyr/
下:

可以看到里面后很多后缀为.class的文件,就是eclipse为我们自动编译好了的java文件,其中就有:

HelloWorld.class文件。

退回到classes一级目录:/HelloWorld/bin/classes/

执行如下命令:

javah com.lucyfyr.HelloWorld

生成文件:com_lucyfyr_HelloWorld.h

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_lucyfyr_HelloWorld */
#ifndef _Included_com_lucyfyr_HelloWorld
#define _Included_com_lucyfyr_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_lucyfyr_HelloWorld
* Method: printJNI
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_lucyfyr_HelloWorld_printJNI
(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif

可以看到自动生成对应的函数:Java_com_lucyfyr_HelloWorld_printJNI

Java_ + 包名(com.lucyfyr) + 类名(HelloWorld) + 接口名(printJNI):必须要按此JNI规范来操作;

java虚拟机就可以在com.simon.HelloWorld类调用printJNI接口的时候自动找到这个C实现的Native函数调用。

当然函数名太长,可以在.c文件中通过函数名映射表来实现简化。

第三步:

实现JNI原生函数源文件:

新建com_lucyfyr_HelloWorld.c文件:

#include <jni.h>
#define LOG_TAG "HelloWorld"
#include <utils/Log.h>
/* Native interface, it will be call in java code */
JNIEXPORT jstring JNICALL Java_com_lucyfyr_HelloWorld_printJNI(JNIEnv *env, jobject obj,jstring inputStr)
{
LOGI("fresne Hello World From libhelloworld.so!");
// 从 instring 字符串取得指向字符串 UTF 编码的指针
const char *str =
(const char *)(*env)->GetStringUTFChars( env,inputStr, JNI_FALSE );
LOGI("fresne--->%s",(const char *)str);
// 通知虚拟机本地代码不再需要通过 str 访问 Java 字符串。
(*env)->ReleaseStringUTFChars(env, inputStr, (const char *)str );
return (*env)->NewStringUTF(env, "Hello World! I am Native interface");
}
/* This function will be call when the library first be load.
* You can do some init in the libray. return which version jni it support.
*/
jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
void *venv;
LOGI("fresne----->JNI_OnLoad!");
if ((*vm)->GetEnv(vm, (void**)&venv, JNI_VERSION_1_4) != JNI_OK) {
LOGE("fresne--->ERROR: GetEnv failed");
return -1;
}
return JNI_VERSION_1_4;
}

OnLoadJava_com_lucyfyr_HelloWorld_printJNI

函数里面做一些log输出 注意JNI中的log输出的不同。

JNI_OnLoad函数JNI规范定义的,当共享库第一次被加载的时候会被回调,

这个函数里面可以进行一些初始化工作,比如注册函数映射表,缓存一些变量等,

最后返回当前环境所支持的JNI环境。本例只是简单的返回当前JNI环境。

http://www.cnblogs.com/bastard/archive/2012/05/19/2508913.html

热点内容
主播网站源码 发布:2025-05-15 02:50:56 浏览:167
中文编程语言有哪些 发布:2025-05-15 02:48:59 浏览:535
配置中心应急流程有哪些 发布:2025-05-15 02:37:31 浏览:669
php宏定义 发布:2025-05-15 02:32:54 浏览:270
咸鱼支付密码哪里改 发布:2025-05-15 02:32:53 浏览:520
存储机箱 发布:2025-05-15 02:31:31 浏览:836
编程很累吗 发布:2025-05-15 02:29:25 浏览:552
疫情期间访问国外网络 发布:2025-05-15 02:24:24 浏览:247
我的世界网易版游戏服务器 发布:2025-05-15 02:23:46 浏览:221
全球编程网站 发布:2025-05-15 02:22:55 浏览:334