国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android studio 下JNI編程實例并生成so庫的實現代碼

2019-10-22 18:27:45
字體:
來源:轉載
供稿:網友

最近需要使用JNI編程,學了下JNI,并且在Android Studio下實現了一個小demo。這期間有一些坑,還好都解決了,想分享出來,希望大家少走彎路。本文中采用的平臺是Windows,NDK環境已經搭建好,這方面資料很多,大家可以自行百度。

本文分為兩個部分:

1.如何通過編寫Jni實現native方法的調用。

2.怎樣生成.so動態庫提供給第三方使用。

以下是正文:

一,編寫jni文件,實現本地方法

1,建立一個新工程,只有一個MainActivity,里面加載庫文件并且調用若干本地方法,然后通過Android Studio里的build-makeProject生成class文件。

public class MainActivity extends Activity {  private final String TAG = "JNITEST"  @Override  protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    String s=returnString();    Log.d(TAG,s);    int a=1000;    Log.d(TAG,sayhello(a));  }  //加載jni  static {    System.loadLibrary("nativeTest");  }  //聲明native方法  private native int sayhello(int t);  private native String returnString();}

2,生成.h頭文件,里面有Android工程里本地方法的聲明。這個文件可以自己寫,但是推薦用javah自動生成。生成方法為:在控制臺或者Android studio自帶的控制臺使用javah命令將上一步make之后生成的class文件生成.h頭文件,這里在用javah的時候有可能會出問題,比如我第一次就出現了找不到app.activity ,即找不到類文件,這種問題一般是沒有理解javah的用法造成的。我當時采用以下兩種方法:

方法1: cd到 E:/shijue/JniHello/app/src/main

然后輸入 javah -d jni -classpath I:/Andriod/AndroidSDK/platforms/android-15/android.jar;
E:/shijue/JniHello/app/build/intermediates/classes/debug com.example.machenike_pc.jnihello.MainActivity

說明:javah是生成頭文件的命令,深綠色為生成文件夾jni,紫紅色為android.jar所在的位置,淺綠色為class文件的路徑+類全名(路徑最后一個文件夾是debug之后空格+類全名)

(這里補充下-classpath的含義:javah操作是針對類文件,-bootclasspath和-classpath就是指定在哪里進行類文件搜索。JDK搜索類文件先后順序如下:Bootstrap classes,User classes。Bootstrap默認的是JDK自帶的jar或zip文件,它包括jre/lib下rt.jar等文件,JDK首先搜索這些文件.可以通過-bootclasspath來設置它。文件之間用分號";"進行分割。User classes搜索順序為當前目錄、環境變量 CLASSPATH、-classpath。它們用于告知JDK搜索類文件根目錄名、jar文檔名、zip文檔名,用分號";"進行分隔。)

方法2: cd到E:/shijue/JniHello/app/build/intermediates/classes/debug目錄下,直接javah -d jni com.example.machnike_pc.jnihello.MainActivity 即可

 

3,在生成的jni目錄下寫一個c或者c++文件,文件名隨意,實現本地方法 ,之后需要在該路徑下再加一個空的cpp或c文件(估計是軟件的bug,不加的話很可能出ndk錯誤),比如我加了個util.cpp的文件,里面什么都不寫。

下面是我的c++代碼

#include<jni.h>#include<stdio.h>#include<com_example_machenike_pc_jnitest2_MainActivity.h>#ifdef __cplusplusextern "C" {#endifJNIEXPORT jint JNICALL Java_com_example_machenike_1pc_jnitest2_MainActivity_sayhello (JNIEnv *, jobject, jint);JNIEXPORT jstring JNICALL Java_com_example_machenike_1pc_jnitest2_MainActivity_returnString (JNIEnv *, jobject);#ifdef __cplusplus}#endifJNIEXPORT jint JNICALL Java_com_example_machenike_1pc_jnitest2_MainActivity_sayhello  (JNIEnv * env, jobject jobj, jint jnumber)  {    int modify=jnumber+1;    return modify;  }JNIEXPORT jstring JNICALL Java_com_example_machenike_1pc_jnitest2_MainActivity_returnString  (JNIEnv *env, jobject jobj)  {    return env->NewStringUTF("I'm comes from to Native Function!");   }

4,如果ndk版本不是最新的,需要在gradle.properties文件下加入:

android.useDeprecatedNdk=true

5,配置ndk路徑,這里也可以在AS的設置里面配置。我采用的方法是在local.properties文件最后一行加入:

ndk.dir=I/://Andriod//NDK//android-ndk-r10b

6,build.gradle(app下):文件下加入:(defaultconfig里面)

ndk{
moduleName "nativeTest"
}

此時運行程序已經可以實現本地方法了,之后可以再生成so庫文件,方便使用。

二,生成.so動態庫

(這里說一下,貌似Android studio已經寫好了.mk文件,上面的步驟完成后,直接rebuild一下就自動生成為了.so動態庫,下面的方法也能生成,可以看一下,很有用)

1,在jni文件夾下新建Android.mk文件,寫入以下內容:

LOCAL_PATH := $(call my-dir)           //固定寫法,把路徑賦給LOCAL_PATH變量
include $(CLEAR_VARS)                  //清除其他LOCAL變量
LOCAL_MODULE := nativeTest             //這個模塊的名字,最后生成的.so的名字就是它,要跟java里面的loadLibray的名字一樣。
LOCAL_SRC_FILES := nativeTest.cpp/     //這里是要編譯的文件,/ 符號是換行
            util.cpp
include $(BUILD_SHARED_LIBRARY)        //SHARED_LIBRARY就是動態庫,即.so文件

 這里的寫法是最簡單的一個例子,用的時候把注釋去掉。每一行都是很關鍵,不能省略。至于makefile怎么編寫內容比較多,此處不贅述。

2,在工程根目錄下新建application.make文件,寫入以下內容:

APP_PROJECT_PATH := $(call my-dir)
APP_MODULES := nativeTest
3,在命令行下,cd到jni目錄(就是之前javah -d jni生成的那個文件夾)下,輸入指令: ndk-build,等一會即可生成.so文件。位于lib目錄下,將其放到app/src/main/jniLibs目錄下就能用了。

FAQ:

1,生成的so文件在使用時需要注意:包名不能變,拿上文舉例,本地方法位于com_example_machenike_pc_jnitest2_MainActivity這個類下,如果在別的地方用,需要完整的建立這個包名和類。
2,c和cpp文件均可以用來寫jni,寫法上略有不同。
3,需要注意java里面成員方法和靜態方法通過javah生成的頭文件略有不同,一個參數是jclass,另一個是jobject。
4,不用javah生成頭文件也行,推薦第一次寫的時候用javah生成,后面修改的時候(比如參數改變)可以直接在c文件里手動修改。

補充:

SourcePath: D:/work/androidstudio/VisualRecognition/app/src/main/java (絕對路徑)

TargetPath: D:/work/androidstudio/VisualRecognition/visual/src/main/jni (絕對路徑)

TargetClassName: com.yf.visualrecognition.UnityPlayerActivity (你的包名+類名)

格式: javah -d ${SourceFile} -classpath ${TargetPath} ${TargetClassName}

生成.h文件:javah -d E:/AndroidProject/GitHubProject/OpenCV/OpenCV/app/src/main/jni -classpath E:/AndroidProject/GitHubProject/OpenCV/OpenCV/app/src/main/java com.cosco.opencv.OpenCVHelper


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 泰安市| 保德县| 论坛| 林周县| 多伦县| 呼和浩特市| 西乌珠穆沁旗| 景东| 大同市| 资溪县| 仙游县| 柘城县| 新乡县| 通城县| 穆棱市| 广宗县| 潼关县| 电白县| 兰考县| 平乡县| 茌平县| 瓦房店市| 道真| 巩义市| 六枝特区| 泗阳县| 都兰县| 孝昌县| 治多县| 台东市| 南平市| 延安市| 祁连县| 铁岭县| 河北省| 景宁| 襄城县| 林甸县| 富平县| 富阳市| 榕江县|