Android Studio開發JNI工程

zdrn4631 8年前發布 | 17K 次閱讀 Android開發 移動開發

轉載來自:http://blog.csdn.net/sodino/article/details/41946607


使用Android Sutdio創建一個新的工程后,接下來記錄創建NDK工程的基本步驟。

本文將達到:
1. 創建NDK工程
2. 在JNI中輸出Log語句
3. 指定編譯的so庫的abi版本
4. 解決在創建NDK工程中的問題

Step: 1. 添加native接口
注意寫好native接口和System.loadLibrary()即可了,并無特別之處。
P.S:onCreate()中對R.id.txt執行setText(),所以這里需要對xml布局文件按正常的開發步驟進行修改即可。

直接給出代碼如下:
[java]  view plain copy 在CODE上查看代碼片 派生到我的代碼片
  1. public class MainActivity extends Activity{  
  2.     static {  
  3.         System.loadLibrary("JniTest");  
  4.     }  
  5.      
  6.     public native String getStringFromNative();  
  7.     @Override  
  8.     protected void onCreate(Bundle savedInstanceState) {  
  9.         super.onCreate(savedInstanceState);  
  10.         setContentView(R.layout.activity_main);  
  11.         TextView txtView = (TextView) findViewById(R.id.txt);  
  12.         txtView.setText(getStringFromNative());  
  13.     }  
  14. }  



Step: 2.執行Build->Make Project</span>


這一步驟執行一下,驗證工程中并無其它錯誤,并對工程進行了編譯,生成了.class文件.
.class文件的生成路徑是在 app_path/build/intermediates/classes/debug下的.如下圖:



Step: 3.javah生成c頭文件

點擊"View->Tool Windows->Terminal",即在Studio中進行終端命令行工具.執行如下命令生成c語言頭文件。
這里需要注意的是要進入 <Project>\app\src\main的目錄下執行javah命令,為的是生成的 .h 文件同樣是在<Project>\app\src\main路徑下,可以在Studio的工程結構中直接看到。

操作命令:
javah -d jni -classpath <SDK_android.jar>;<APP_classes> lab.sodino.jnitest.MainActivity
具體操作圖如下:


[java]  view plain copy 在CODE上查看代碼片 派生到我的代碼片

</div>

</div>

  1. javah -d jni -classpath c:\Users\sodinochen\AppData\Local\Android\sdk\platforms  
  2. \android-16\android.jar;..\..\build\intermediates\classes\debug lab.sodino.jnitest.MainActivity  

</div>



對于"主版本51比50新,此編譯器支持最新的主版本"則是由于電腦上安裝了兩個版本的jdk引起的,而當前使用的是舊的jdk。
把舊的jdk刪除,并執行java version命令后顯示當前jdk為最新的1.7時,則不會再有此提示了。如下圖:


最后的生成結果:




Step: 4.編輯c文件

在main.c文件中實現頭文件中的方法,具體功能為直接return回一個String,并且使用android_log打印出相關日志。
代碼如下:
[cpp]  view plain copy 在CODE上查看代碼片 派生到我的代碼片
</div>

</div>

  1. /* DO NOT EDIT THIS FILE - it is machine generated */  
  2. #include <jni.h>  
  3. #include <android/log.h>  
  4.   
  5. #ifndef LOG_TAG  
  6. #define LOG_TAG "ANDROID_LAB"  
  7. #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)  
  8. #endif  
  9.   
  10. /* Header for class lab_sodino_jnitest_MainActivity */  
  11.   
  12. #ifndef _Included_lab_sodino_jnitest_MainActivity  
  13. #define _Included_lab_sodino_jnitest_MainActivity  
  14. #ifdef __cplusplus  
  15. extern "C" {  
  16. #endif  
  17. /* 
  18.  * Class: lab_sodino_jnitest_MainActivity 
  19.  * Method: getStringFromNative 
  20.  * Signature: ()Ljava/lang/String; 
  21.  */  
  22. JNIEXPORT jstring JNICALL Java_lab_sodino_jnitest_MainActivity_getStringFromNative  
  23.   (JNIEnv * env, jobject jObj){  
  24.       LOGE("log string from ndk.");  
  25.       return (*env)->NewStringUTF(env,"Hello From JNI!");  
  26.   }  
  27.   
  28. #ifdef __cplusplus  
  29. }  
  30. #endif  
  31. #endif  

</div>

</div>


到這里后,我們再執行一個"Build->Make Project",發現"Messages Gradle Build"會給出提示如下:
[java]  view plain copy 在CODE上查看代碼片 派生到我的代碼片
</div>

</div>

  1. Error:Execution failed for task ':app:compileDebugNdk'.   
  2. > NDK not configured.   
  3. Download the NDK from http://developer.android.com/tools/sdk/ndk/.Then add ndk.dir=path/to/ndk in local.properties.   
  4. (On Windows, make sure you escape backslashes, e.g. C:\\ndk rather than C:\ndk)  

</div>

</div>

這里提示了NDK未配置,并且需要在工程中的local.properties文件中配置NDK路徑。好了,提示很清楚了,那我們就進入下一步吧。


Step: 5.配置NDK

這一步包括兩個動作:

1.指明ndk路徑

2. 修改build.gradle配置
    工程中共有兩個build.gradle配置文件,我們要修改的是在<Project>\app\build.gradle這個文件。為其在defaultConfig分支中增加上
[java]  view plain copy 在CODE上查看代碼片 派生到我的代碼片
 </div>

</div>

<ol start="1" class="dp-j" style="padding:0px;border:0px;list-style-position:initial;color:#5c5c5c;margin:0px 0px 1px 45px!important;background-color:#ffffff;"> 
 <li class="alt" style="border-width:0px 0px 0px 3px;border-left-style:solid;border-left-color:#6ce26c;list-style:decimal-leading-zero outside;color:inherit;line-height:18px;margin:0px!important;padding:0px 3px 0px 10px!important;"> <span style="margin:0px;padding:0px;border:0px;color:black;background-color:inherit;"><span style="margin:0px;padding:0px;border:0px;background-color:inherit;">ndk {  </span></span></li>
 <li style="border-width:0px 0px 0px 3px;border-left-style:solid;border-left-color:#6ce26c;list-style:decimal-leading-zero outside;line-height:18px;margin:0px!important;padding:0px 3px 0px 10px!important;background-color:#f8f8f8;"> <span style="margin:0px;padding:0px;border:0px;color:black;background-color:inherit;">    moduleName <span class="string" style="margin:0px;padding:0px;border:0px;color:blue;background-color:inherit;">"JniTest"</span><span style="margin:0px;padding:0px;border:0px;background-color:inherit;">  </span></span></li>
 <li class="alt" style="border-width:0px 0px 0px 3px;border-left-style:solid;border-left-color:#6ce26c;list-style:decimal-leading-zero outside;color:inherit;line-height:18px;margin:0px!important;padding:0px 3px 0px 10px!important;"> <span style="margin:0px;padding:0px;border:0px;color:black;background-color:inherit;">    ldLibs <span class="string" style="margin:0px;padding:0px;border:0px;color:blue;background-color:inherit;">"log"</span><span style="margin:0px;padding:0px;border:0px;background-color:inherit;">, </span><span class="string" style="margin:0px;padding:0px;border:0px;color:blue;background-color:inherit;">"z"</span><span style="margin:0px;padding:0px;border:0px;background-color:inherit;">, </span><span class="string" style="margin:0px;padding:0px;border:0px;color:blue;background-color:inherit;">"m"</span><span style="margin:0px;padding:0px;border:0px;background-color:inherit;">  </span></span></li>
 <li style="border-width:0px 0px 0px 3px;border-left-style:solid;border-left-color:#6ce26c;list-style:decimal-leading-zero outside;line-height:18px;margin:0px!important;padding:0px 3px 0px 10px!important;background-color:#f8f8f8;"> <span style="margin:0px;padding:0px;border:0px;color:black;background-color:inherit;">    abiFilters <span class="string" style="margin:0px;padding:0px;border:0px;color:blue;background-color:inherit;">"armeabi"</span><span style="margin:0px;padding:0px;border:0px;background-color:inherit;">, </span><span class="string" style="margin:0px;padding:0px;border:0px;color:blue;background-color:inherit;">"armeabi-v7a"</span><span style="margin:0px;padding:0px;border:0px;background-color:inherit;">, </span><span class="string" style="margin:0px;padding:0px;border:0px;color:blue;background-color:inherit;">"x86"</span><span style="margin:0px;padding:0px;border:0px;background-color:inherit;">  </span></span></li>
 <li class="alt" style="border-width:0px 0px 0px 3px;border-left-style:solid;border-left-color:#6ce26c;list-style:decimal-leading-zero outside;color:inherit;line-height:18px;margin:0px!important;padding:0px 3px 0px 10px!important;"> <span style="margin:0px;padding:0px;border:0px;color:black;background-color:inherit;">}  </span></li>
</ol>

</div>

</div>

    以上配置代碼指定的so庫名稱為JniTest,鏈接時使用到的庫,對應android.mk文件中的LOCAL_LDLIBS,及最終輸出指定三種abi體系結構下的so庫。
添加后如下圖:


</div>

這時,再執行"Build->Rebuild Project",就可以編譯出so文件了。
但在Window平臺上會出現一個問題:
[java]  view plain copy 在CODE上查看代碼片 派生到我的代碼片
</div>

</div>

  1. Error:Execution failed for task ':app:compileDebugNdk'.  
  2. > com.android.ide.common.internal.LoggedErrorException: Failed to run command:  
  3.  D:\Mission\adt-bundle-windows\ndk-r10b\ndk-build.cmd NDK_PROJECT_PATH=null APP_BUILD_SCRIPT=C:\Users\sodinochen\AndroidstudioProjects\JniTest2\app\build\intermediates\ndk\debug\Android.mk APP_PLATFORM=android-21 NDK_OUT=C:\Users\sodinochen\AndroidstudioProjects\JniTest2\app\build\intermediates\ndk\debug\obj NDK_LIBS_OUT=C:\Users\sodinochen\AndroidstudioProjects\JniTest2\app\build\intermediates\ndk\debug\lib APP_ABI=armeabi,armeabi-v7a,x86  
  4. Error Code:  
  5.  2  
  6. Output:  
  7.  make.exe: *** No rule to make target `C:\Users\sodinochen\AndroidstudioProjects\JniTest2\app\build\intermediates\ndk\debug\obj/local/armeabi/objs/JniTest/C_\Users\sodinochen\AndroidstudioProjects\JniTest2\app\src\main\jni', needed by `C:\Users\sodinochen\AndroidstudioProjects\JniTest2\app\build\intermediates\ndk\debug\obj/local/armeabi/objs/JniTest/C_\Users\sodinochen\AndroidstudioProjects\JniTest2\app\src\main\jni\main.o'. Stop.  

</div>

</div>

出現這個錯誤很莫名其妙..幾番折騰下,找到一個視頻出來了大概原因及解決方式:
出處見油Tube視頻 02:50分開始: https://www.油Tube.com/watch?v=okLKfxfbz40#t=362
在Windows下NDK一個bug,當僅僅編譯一個文件時出現會出現此問題,解決方法就是 再往jni文件夾加入一個空util.c文件即可。如下圖:


</div>

編譯出來的庫文件被Studio輸出到了下圖的路徑中




Step: 6.安裝運行

界面:


查看Log打印:


轉載來自:http://blog.csdn.net/sodino/article/details/41946607

使用Android Sutdio創建一個新的工程后,接下來記錄創建NDK工程的基本步驟。

本文將達到:
1. 創建NDK工程
2. 在JNI中輸出Log語句
3. 指定編譯的so庫的abi版本
4. 解決在創建NDK工程中的問題

Step: 1. 添加native接口
注意寫好native接口和System.loadLibrary()即可了,并無特別之處。
P.S:onCreate()中對R.id.txt執行setText(),所以這里需要對xml布局文件按正常的開發步驟進行修改即可。

直接給出代碼如下:
[java]  view plain copy 在CODE上查看代碼片 派生到我的代碼片
  1. public class MainActivity extends Activity{  
  2.     static {  
  3.         System.loadLibrary("JniTest");  
  4.     }  
  5.      
  6.     public native String getStringFromNative();  
  7.     @Override  
  8.     protected void onCreate(Bundle savedInstanceState) {  
  9.         super.onCreate(savedInstanceState);  
  10.         setContentView(R.layout.activity_main);  
  11.         TextView txtView = (TextView) findViewById(R.id.txt);  
  12.         txtView.setText(getStringFromNative());  
  13.     }  
  14. }  



Step: 2.執行Build->Make Project


這一步驟執行一下,驗證工程中并無其它錯誤,并對工程進行了編譯,生成了.class文件.
.class文件的生成路徑是在 app_path/build/intermediates/classes/debug下的.如下圖:


Step: 3.javah生成c頭文件

點擊"View->Tool Windows->Terminal",即在Studio中進行終端命令行工具.執行如下命令生成c語言頭文件。
這里需要注意的是要進入 <Project>\app\src\main的目錄下執行javah命令,為的是生成的 .h 文件同樣是在<Project>\app\src\main路徑下,可以在Studio的工程結構中直接看到。

操作命令:
javah -d jni -classpath <SDK_android.jar>;<APP_classes> lab.sodino.jnitest.MainActivity
具體操作圖如下:

[java]  view plain copy 在CODE上查看代碼片 派生到我的代碼片
  1. javah -d jni -classpath c:\Users\sodinochen\AppData\Local\Android\sdk\platforms  
  2. \android-16\android.jar;..\..\build\intermediates\classes\debug lab.sodino.jnitest.MainActivity  


對于"主版本51比50新,此編譯器支持最新的主版本"則是由于電腦上安裝了兩個版本的jdk引起的,而當前使用的是舊的jdk。
把舊的jdk刪除,并執行java version命令后顯示當前jdk為最新的1.7時,則不會再有此提示了。如下圖:

最后的生成結果:




Step: 4.編輯c文件

在main.c文件中實現頭文件中的方法,具體功能為直接return回一個String,并且使用android_log打印出相關日志。
代碼如下:
[cpp]  view plain copy 在CODE上查看代碼片 派生到我的代碼片
  1. /* DO NOT EDIT THIS FILE - it is machine generated */  
  2. #include <jni.h>  
  3. #include <android/log.h>  
  4.   
  5. #ifndef LOG_TAG  
  6. #define LOG_TAG "ANDROID_LAB"  
  7. #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)  
  8. #endif  
  9.   
  10. /* Header for class lab_sodino_jnitest_MainActivity */  
  11.   
  12. #ifndef _Included_lab_sodino_jnitest_MainActivity  
  13. #define _Included_lab_sodino_jnitest_MainActivity  
  14. #ifdef __cplusplus  
  15. extern "C" {  
  16. #endif  
  17. /* 
  18.  * Class: lab_sodino_jnitest_MainActivity 
  19.  * Method: getStringFromNative 
  20.  * Signature: ()Ljava/lang/String; 
  21.  */  
  22. JNIEXPORT jstring JNICALL Java_lab_sodino_jnitest_MainActivity_getStringFromNative  
  23.   (JNIEnv * env, jobject jObj){  
  24.       LOGE("log string from ndk.");  
  25.       return (*env)->NewStringUTF(env,"Hello From JNI!");  
  26.   }  
  27.   
  28. #ifdef __cplusplus  
  29. }  
  30. #endif  
  31. #endif  

到這里后,我們再執行一個"Build->Make Project",發現"Messages Gradle Build"會給出提示如下:
[java]  view plain copy 在CODE上查看代碼片 派生到我的代碼片
  1. Error:Execution failed for task ':app:compileDebugNdk'.   
  2. > NDK not configured.   
  3. Download the NDK from http://developer.android.com/tools/sdk/ndk/.Then add ndk.dir=path/to/ndk in local.properties.   
  4. (On Windows, make sure you escape backslashes, e.g. C:\\ndk rather than C:\ndk)  
這里提示了NDK未配置,并且需要在工程中的local.properties文件中配置NDK路徑。好了,提示很清楚了,那我們就進入下一步吧。


Step: 5.配置NDK
這一步包括兩個動作:
1.指明ndk路徑

2. 修改build.gradle配置
    工程中共有兩個build.gradle配置文件,我們要修改的是在<Project>\app\build.gradle這個文件。為其在defaultConfig分支中增加上
[java]  view plain copy 在CODE上查看代碼片 派生到我的代碼片
  1. ndk {  
  2.     moduleName "JniTest"  
  3.     ldLibs "log""z""m"  
  4.     abiFilters "armeabi""armeabi-v7a""x86"  
  5. }  
    以上配置代碼指定的so庫名稱為JniTest,鏈接時使用到的庫,對應android.mk文件中的LOCAL_LDLIBS,及最終輸出指定三種abi體系結構下的so庫。
添加后如下圖:

這時,再執行"Build->Rebuild Project",就可以編譯出so文件了。
但在Window平臺上會出現一個問題:
[java]  view plain copy 在CODE上查看代碼片 派生到我的代碼片
  1. Error:Execution failed for task ':app:compileDebugNdk'.  
  2. > com.android.ide.common.internal.LoggedErrorException: Failed to run command:  
  3.  D:\Mission\adt-bundle-windows\ndk-r10b\ndk-build.cmd NDK_PROJECT_PATH=null APP_BUILD_SCRIPT=C:\Users\sodinochen\AndroidstudioProjects\JniTest2\app\build\intermediates\ndk\debug\Android.mk APP_PLATFORM=android-21 NDK_OUT=C:\Users\sodinochen\AndroidstudioProjects\JniTest2\app\build\intermediates\ndk\debug\obj NDK_LIBS_OUT=C:\Users\sodinochen\AndroidstudioProjects\JniTest2\app\build\intermediates\ndk\debug\lib APP_ABI=armeabi,armeabi-v7a,x86  
  4. Error Code:  
  5.  2  
  6. Output:  
  7.  make.exe: *** No rule to make target `C:\Users\sodinochen\AndroidstudioProjects\JniTest2\app\build\intermediates\ndk\debug\obj/local/armeabi/objs/JniTest/C_\Users\sodinochen\AndroidstudioProjects\JniTest2\app\src\main\jni', needed by `C:\Users\sodinochen\AndroidstudioProjects\JniTest2\app\build\intermediates\ndk\debug\obj/local/armeabi/objs/JniTest/C_\Users\sodinochen\AndroidstudioProjects\JniTest2\app\src\main\jni\main.o'. Stop.  
出現這個錯誤很莫名其妙..幾番折騰下,找到一個視頻出來了大概原因及解決方式:
出處見油Tube視頻 02:50分開始: https://www.油Tube.com/watch?v=okLKfxfbz40#t=362
在Windows下NDK一個bug,當僅僅編譯一個文件時出現會出現此問題,解決方法就是 再往jni文件夾加入一個空util.c文件即可。如下圖:


編譯出來的庫文件被Studio輸出到了下圖的路徑中




Step: 6.安裝運行

界面:


查看Log打印:


 本文由用戶 zdrn4631 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!