標籤:
一、前言
前段時間有個同事離職了,用C編譯的.SO檔案需要更改,結果C檔案是他寫的,無賴啊,自己又是一個小白,不會啊,所以自己又好好鑽研了一天,不會,看什麼都難啊,痛苦啊,網上找了好多,才找到的,而且感覺都不怎麼詳細,步驟說的不是很清楚,所以自己整理了一下,誰便記錄一下,好了,廢話不多說,開始正題。
二、編譯過程1、編譯環境的搭建
正所謂:“工欲善其事必先利其器”嘛,所以先把改準備工具準備一下,因為是在studio下編譯的,所以啊,什麼studio、什麼sdk、什麼jdk,這些都自己去弄吧,這裡說一下ndk這個編譯C檔案工具怎麼下載安裝;
下載連結:https://developer.android.com/ndk/downloads/index.html(一般需要翻牆,至於原因嘛,你懂得)進去之後下載自己相對應的ndk平台版本;
下載完了之後直接是一個zip的壓縮包,解壓即可;
然後如所示的配置ndk:
然後你會在local.properties檔案中看到:
不要急,還沒有完,ndk環境搭建還有最後一步,在gradle.properties的檔案末尾加上android.useDeprecatedNdk=true這段代碼,文字看不懂吧直接:
好了,到此處環境就搭建完畢了。
2、java代碼和C代碼的編寫步驟及過程
首先建立一個java類JNIUtils.java
public class JNIUtils { static { System.loadLibrary("huazict"); } //java調C中的方法都需要用native聲明且方法名必須和c的方法名一樣 public native String getString();}
然後如所示重新Make Project一下工程:
會在工程目錄E:\work\MyApplication\stujni\build\intermediates\classes\debug\com\huazi\stujni\jni中看到自己編譯後的class檔案JNIUtils.class如所示:
其次就是產生.h檔案了
在studio開啟Terminal命令列工具,開啟步驟是View->Tool Windows->Terminal (或直接按Alt+F12),如所示:
然後在命令列中先進入到工程的main目錄下
輸入命令:javah -d jni -classpath 自己編譯後的class檔案的絕對路徑
例如:javah -d jni -classpath E:\work\MyApplication\stujni\build\intermediates\classes\debug com.huazi.stujni.jni.JNIUtils(注意debug後的空格)
看到,圖中命令列中是直接進入到了工程的main目錄下(在哪個目錄下運行就會在哪個目錄下自動產生jni檔案夾),按斷行符號之後就會在main目錄下產生jni檔案夾,同時產生.h檔案,如:
這個檔案.h檔案不需要做任何修改,預設即可。
現在我們來寫一個test的C檔案huazict.c同.h檔案一樣放到jni檔案夾下,代碼如下:
#include "com_huazi_stujni_jni_JNIUtils.h"/** * 上邊的引用標籤一定是.h的檔案名稱家尾碼,方法名一定要和.h檔案中的方法名稱一樣 */JNIEXPORT jstring JNICALL Java_com_huazi_stujni_jni_JNIUtils_getString (JNIEnv *env, jobject obj) { return (*env)->NewStringUTF(env, "這是我測試的jni");}
:
最後在構建檔案中的預設配置中加上:
//ndk編譯產生.so檔案 ndk { moduleName "huazict" //產生的so名字 abiFilters "armeabi", "armeabi-v7a", "x86" //輸出指定三種abi體繫結構下的so庫。 }
到這裡,通過jni調C就完成了,現在我們來測試一下,寫個TextView顯示一下調用的C:
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView tv = (TextView)findViewById(R.id.tv); tv.setText(new JNIUtils().getString()); }}
看效果,直接:
ok,沒問題,可以調用,其實也沒有想象中的那麼難,是吧!
三、調用編譯過的.so庫
上邊編譯完成了,有人會問:我要的是編譯後的.so庫,別人用的時候直接拿來用就可以了,那編譯後的.so庫在哪呢?不要著急請看:
根據這個路徑就可以找到指定輸出的三種體繫結構下的.so庫檔案,然後把.so檔案複製出來,如所示的放到相應的檔案夾下就ok了:
再次運行,結果還是一樣的,跟上邊貼的那張圖的顯示效果是是一樣的,同樣能調用到,代碼我就不上傳了,都在上邊貼上去了,而且也上傳不了,公司的所有檔案都是加密的,想上傳都上傳不了。
到這裡,整個jni的調用過程就結束了,包括調用jni需要的環境以及調用的過程,最後.so檔案的匯出,都在上邊了,如果上邊的jni調用過程有什麼問題,歡迎留言,謝謝。
android studio 編譯C產生.so檔案