當前位置:首頁 » 安卓系統 » 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

熱點內容
怎麼查看泰拉伺服器ip 發布:2025-05-14 23:03:29 瀏覽:72
c語言學生成績查詢系統 發布:2025-05-14 22:58:30 瀏覽:4
怎麼進別人的伺服器 發布:2025-05-14 22:45:55 瀏覽:772
用編程寫音樂 發布:2025-05-14 22:45:08 瀏覽:782
如何識別電腦的網路配置 發布:2025-05-14 22:38:46 瀏覽:847
pipforpython3 發布:2025-05-14 22:38:34 瀏覽:350
如何把迷你世界的伺服器搞崩 發布:2025-05-14 22:37:15 瀏覽:94
如何讓安卓卡死機 發布:2025-05-14 22:36:27 瀏覽:634
wemall微商城源碼 發布:2025-05-14 22:15:20 瀏覽:804
隆地優選交易密碼是什麼 發布:2025-05-14 21:53:23 瀏覽:97