導航:首頁 > 文件教程 > apk中引入so文件

apk中引入so文件

發布時間:2023-06-11 17:13:35

安卓apk解壓後得到的.so文件能直接放項目裡面調用裡面的方法嗎

使用Androidstudio創建一個Android項目
打開Androidstudio創建一個項目,命名為tryndk
在項目中新創建一個類,在其中聲明native方法在src/main目錄下創建一個工具類,用來存放native方法
javautils類創建兩個方法,聲明為native
然後選中項目,點擊build->make project,在項目中的build->intermediates->classes->debug->com->example->tryndk下就能看見javautils.class文件了
在Androidstudio中打開終端(View->ToolWindows->Terminal)在terminal中進入到main目錄中,然後在鍵入javah -d jni -classpath ../../build/intermediates/classes/debug com.example.tryndk.javautils記得debug 後面有個空格。然後就能在src/main目錄下看到jni文件夾,裡面存放了一個頭文件com_example_tryndk_javautils.h,裡面生成了函數聲明,
Java_com_example_tryndk_javautils_getStringFromNative為方法名,其中getStringFromNative為在javautils文件中創建的getStringFromNative方法。
然後在jni目錄下創建一個c文件命名為MyJni.c,實現相應的方法
方法中就是返回了一個字元串。

② 如何動態載入android的so文件,如何壓縮apk尺寸

在Android中調用動態庫文件(*.so)都是通過jni的方式,而且往往在apk或jar包中調用so文件時,都要將對應so文件打包進apk或jar包,工程目錄下圖:

以上方式的存在的問題:
1、缺少靈活性比較類似靜態載入了(不是靜態載入),能載入的so文件綁定死了;
2、但so文件很多或很大時,會導致對應的apk和jar包很大;
3、不能動態的對so文件更新;

Android中載入so文件的提供的API:
void System.load(String pathName);

說明:
1、pathName:文件名+文件路勁;
2、該方法調用成功後so文件中的導出函數都將插入的系統提供的一個映射表(類型Map);

看到以上對System.load(String pathName);的函數說明可定有人會想到將so文件放到一個指定的目錄然後再通過參數pathName直接引用該目錄的路勁和對應的so文件問題不就解決了嗎?
這里有個問題被忽略了,那就是System.load只能載入兩個目錄路勁下的so文件:
1、/system/lib ;
2、安裝包的路勁,即:/data/data/<packagename>/…
而且這兩個路勁又是有許可權保護的不能直接訪問;

問題解決方法:
先從網路下載so文件到手機目錄(如:/test/device/test.so) –> 將test.so載入到內存(ByteArrayOutputStream) –> 然後保存到對用安裝包目錄;
具體代碼如下:

try {
String localPath = Environment.getExternalStorageDirectory() + path;
Log.v(TAG, "LazyBandingLib localPath:" + localPath);

String[] tokens = mPatterns.split(path);
if (null == tokens || tokens.length <= 0
|| tokens[tokens.length - 1] == "") {
Log.v(TAG, "非法的文件路徑!");
return -3;
}
// 開辟一個輸入流
File inFile = new File(localPath);
// 判斷需載入的文件是否存在
if (!inFile.exists()) {
// 下載遠程驅動文件
Log.v(TAG, inFile.getAbsolutePath() + " is not fond!");
return 1;
}
FileInputStream fis = new FileInputStream(inFile);

File dir = context.getDir("libs", Context.MODE_PRIVATE);
// 獲取驅動文件輸出流
File soFile = new File(dir, tokens[tokens.length - 1]);
if (!soFile.exists()) {
Log.v(TAG, "### " + soFile.getAbsolutePath() + " is not exists");
FileOutputStream fos = new FileOutputStream(soFile);
Log.v(TAG, "FileOutputStream:" + fos.toString() + ",tokens:"
+ tokens[tokens.length - 1]);

// 位元組數組輸出流,寫入到內存中(ram)
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = -1;
while ((len = fis.read(buffer)) != -1) {
baos.write(buffer, 0, len);
}
// 從內存到寫入到具體文件
fos.write(baos.toByteArray());
// 關閉文件流
baos.close();
fos.close();
}
fis.close();
Log.v(TAG, "### System.load start");
// 載入外設驅動
System.load(soFile.getAbsolutePath());
Log.v(TAG, "### System.load End");

return 0;

} catch (Exception e) {
Log.v(TAG, "Exception " + e.getMessage());
e.printStackTrace();
return -1;

}

③ 怎麼把so打包打包進apk

在apk里打包進.so文件的方法
有兩種方法,
1 是在Android.mk文件里增加
LOCAL_JNI_SHARED_LIBRARIES := libxxx
這樣在編譯的時候,NDK自動會把這個libxxx打包進apk;
放在youapk/lib/目錄下。

2 是在應用的目錄下手工建
libs/armeabi
目錄,然後把libxxx.so拷貝到這個目錄下,
這樣NDK就會自動把這個libxxx.so打包進apk,位置還是在
放在youapk/lib/目錄下。

在代碼里,使用
System.loadLibrary("xxx");
就可以載入這個動態庫了。
這里要注意,參數只寫xxx就可以了,不需要寫libxxx,也不需要寫libxxx.so。

還有一點要說明,System.loadLibrary這個函數會在如下路徑搜索libxxx.so文件:
/system/lib
/data/data/you apk package/lib

但,如果libxxx.so還依賴其它.so文件,比如libyyy.so,則System.loadLibrary只會
在/system/lib目錄下去找,如果沒找到,它不會自動到/data/data/you apk package/lib
下去找,這個時候就會報動態庫沒找到的錯;
解決方法是在load libxxx.so之前,先load libyyy.so,如下:
System.loadLibrary("yyy");
System.loadLibrary("xxx");

④ 怎麼把so打包打包進apk

打包這個動作免去了:將libxxx.so文件push到/system/lib/目錄下而需要取得/system/lib 目錄 的寫許可權實現步驟如回下:
1、項目根目答錄下建立libs/armeabi目錄;
2、將libxxx.so文件到 libs/armeabi/下;
3、編譯輸出的.apk文件中已經包括.so文件了;
4、安裝APK文件,即可直接使用JNI中的方法。

~如果你認可我的回答,請及時點擊【採納為滿意回答】按鈕
~~手機提問的朋友在客戶端右上角評價點【滿意】即可。
~你的採納是我前進的動力
~~O(∩_∩)O,記得好評和採納,互相幫助,謝謝。

⑤ 如何載入so文件 android

android中載入so文件:

在Android中調用動態庫文件(*.so)都是通過jni的方式,而且往往在apk或jar包中調用so文件時,都要將對應so文件打包進apk或jar包,工程目錄下圖:

Android中載入so文件的提供的API:

void System.load(String pathName);

說明:

1、pathName:文件名+文件路勁;

2、該方法調用成功後so文件中的導出函數都將插入的系統提供的一個映射表(類型Map);

3、具體代碼如下:

try {
String localPath = Environment.getExternalStorageDirectory() + path;
Log.v(TAG, "LazyBandingLib localPath:" + localPath);

String[] tokens = mPatterns.split(path);
if (null == tokens || tokens.length <= 0
|| tokens[tokens.length - 1] == "") {
Log.v(TAG, "非法的文件路徑!");
return -3;
}
// 開辟一個輸入流
File inFile = new File(localPath);
// 判斷需載入的文件是否存在
if (!inFile.exists()) {
// 下載遠程驅動文件
Log.v(TAG, inFile.getAbsolutePath() + " is not fond!");
return 1;
}
FileInputStream fis = new FileInputStream(inFile);

File dir = context.getDir("libs", Context.MODE_PRIVATE);
// 獲取驅動文件輸出流
File soFile = new File(dir, tokens[tokens.length - 1]);
if (!soFile.exists()) {
Log.v(TAG, "### " + soFile.getAbsolutePath() + " is not exists");
FileOutputStream fos = new FileOutputStream(soFile);
Log.v(TAG, "FileOutputStream:" + fos.toString() + ",tokens:"
+ tokens[tokens.length - 1]);

// 位元組數組輸出流,寫入到內存中(ram)
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = -1;
while ((len = fis.read(buffer)) != -1) {
baos.write(buffer, 0, len);
}
// 從內存到寫入到具體文件
fos.write(baos.toByteArray());
// 關閉文件流
baos.close();
fos.close();
}
fis.close();
Log.v(TAG, "### System.load start");
// 載入外設驅動
System.load(soFile.getAbsolutePath());
Log.v(TAG, "### System.load End");

return 0;

} catch (Exception e) {
Log.v(TAG, "Exception " + e.getMessage());
e.printStackTrace();
return -1;

}

閱讀全文

與apk中引入so文件相關的資料

熱點內容
魅族pro5自帶瀏覽器怎麼升級 瀏覽:342
為什麼用數據還是載入慢 瀏覽:171
監控下面有網路如何隔離 瀏覽:748
前台中jrequestjson 瀏覽:435
怎麼在word里粘貼xls文件 瀏覽:710
買火車票什麼網站 瀏覽:757
jsp的六大 瀏覽:216
圖文數據要如何導入資料庫 瀏覽:207
軟體數據刪了恢復怎麼弄 瀏覽:517
小米筆記本電腦共享文件 瀏覽:812
cad字體文件夾添加國標字體 瀏覽:938
電腦輸出pdf文件有什麼用 瀏覽:695
微信滿人 瀏覽:585
js點擊按鈕下載圖片 瀏覽:922
數據有效性哪裡設置的 瀏覽:171
orl刪除表的資料庫 瀏覽:353
cad文件0位元組可以修復么 瀏覽:675
瀏覽器下載的軟體在文件中怎麼找 瀏覽:906
怎麼把word圖片變小 瀏覽:278
cf的文件夾 瀏覽:556

友情鏈接