你好,我現在能夠用NDK的如下方式寫幾個簡單的文件,然後打包為SO,再用另外的一個.C文件調用SO,然後生成最終的供Android使用的SO文件,具體方式如下:
下載一個從android模擬器里取system lib的工具busybox,然後調用命令
$adb push busybox /dev/sample/busybox
$adb shell chmod 777 /dev/sample/busybox
$adb shell ./dev/sample/busybox tar -cf /dev/sample/libs.tar /system/lib
$adb pull /dev/sample/libs.tar libs.tar
這樣就將模擬器下的 /system/lib 目錄的所有庫(so)文件打包並下載下來了,解壓libs.tar就得到了我們所需要的所有庫文件。
接著將所有的文件 到 $(NDK)\build\prebuilt\windows\arm-eabi-4.2.1\lib\gcc\arm-eabi\4.2.1,這個時候基本的配置工作就結束了。
然後建立tutorial01.c調用tutorial02.c中的方法,通過寫makefile文件將之打包為SO
CC = /cygdrive/e/android-ndk-1.5_r1/build/prebuilt/windows/arm-eabi-4.2.1/bin/arm-eabi-gcc
CFLAGS = -g -O2 -fPIC -DANDROID -I ./ -I ../ -I /cygdrive/e/android-ndk-1.5_r1/build/platforms/android-1.5/arch-arm/usr/include
SDFLAGS = -nostdlib -Wl,-T,armelf.xsc -Wl,-soname,$@ -Wl,-shared,-Bsymbolic -lc
CRT_OBJS= -lz -lm
# source files:
SRCS= tutorial01.c tutorial02.c tutorial02.h
all: libtutorial.so
libtutorial.so: tutorial01.o tutorial02.o
$(CC) $(SDFLAGS) -o $@ tutorial01.o tutorial02.o $(CRT_OBJS)
tutorial01.o: tutorial02.h
tutorial02.o: tutorial02.h
clean:
rm -f libtutorial.so *.o
然後make,這個時候會報錯 can't find "armelf.xsc", 在ndk的目錄里搜索一下,搜到之後 到$(NDK)\build\prebuilt\windows\arm-eabi-4.2.1\lib\gcc\arm-eabi\4.2.1,然後make,成功。
接著建立一個文件test01.c,動態載入so文件,然後寫一個makefile文件,最後make成功。
建立一個Android工程 testapp來測試其運行情況,實驗表明是能夠正確運行的。
⑵ 如何動態載入android的so文件,如何壓縮apk尺寸,androidapk
在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;
}
⑶ 如何獲取android 系統的so庫
android ndk調用第三方的so庫文件的步驟如下:
1.將SO文件直接放到libs/armeabi下,然後代碼中System.loadLibrary("xxx");再public native static int xxx_xxx_xxx();接下來就可以直接調用xxx_xxx_xxx()方法;
2.第二種方案,創建自己的SO文件,在自己的SO文件里調用第三方SO,再在程序中調用自己的SO,這種比較復雜,需要建java類文件,生成.h文件,編寫C源文件include之前生成的.h文件並實現相應方法,最後用android NDK開發包中的ndk-build腳本生成對應的.so共享庫;
⑷ 如何動態載入android的so文件,如何壓縮apk尺寸
您好,很高興為您解答。
一、 工具集介紹 (項目地址: https://github.com/liyuming1978/NativeLibCompression)
安卓壓縮工具集提供了一個極為簡潔的方法,能夠比安卓原有的Zip提供更高壓縮比的存儲應用內的so文件 (後期版本還可以支持壓縮動態載入的jar包,以及游戲資源文件),同時提供了應用內網路更新下載壓縮文件的方法,使得應用可以將部分so存儲到雲端,減小應用的尺寸。
壓縮原理: 壓縮工具會把所有的so使用LZMA演算法壓縮到assert目錄,應用在第一次啟動的時候,會解壓到應用的私有目錄下
二、 工具集組成
工具集為一個安裝程序,建議安裝在默認路徑下,安裝在program files下在win7可能有讀寫許可權的問題導致一些異常
安裝後,你可以看見4個目錄,此目錄內都含有源碼。
安裝後的四個目錄如下
其中 ApkLibComrepss 為java命令行程序的源碼,在此目錄的bin子目錄中,你可以找到ApkCompress.jar ,使用這個文件可以把一個普通的apk文件轉換為壓縮的apk文件
CompressDemo為一個樣例代碼,你可以參考這個代碼知道如何整合壓縮的SDK。
DecRawso是壓縮的SDK,你的開發工程需要引用這個SDK,並進行一些源碼上的修改,才能整合壓縮的功能
RawsoCreator為windows下的轉換工具, 這個工具一般無需使用, 僅僅在調試和二次開發壓縮SDK的時候使用。
三、 如何整合壓縮SDK
打開CompressDemo,我們以這個工程為例子講解如何整合壓縮SDK
1. 首先需要引入DecRawso工程
2. 然後需要在你的工程內最初始的地方調用DecRawso.NewInstance。在此demo工程內,是在MainActivity.java的OnCreate內調用了此方法, 此方法是創建了一個解壓的唯一實例。注意:此方法是非同步的,所以你可以傳入一個handler接受非同步解碼完成的消息,如果同時傳入參數showProgress=true,SDK內會產生一個進度對話框以阻塞主進程。不推薦使用DecRawso.NewInstance(mContext,null,false);的方式,此方式不接受任何消息,且無進度對話框,解壓會在後台自動完成,並且在應用第一次load so的時候阻塞直到後台解壓完成。所以如果阻塞時間過長,可能會導致應用無響應。
3. 修改load so文件的方法:所有的System.loadlibrary(***)改為 System.load(DecRawso.GetInstance().GetPath(「***"));
新版本, 這步可以省略了,sdk會修改system的libaray載入路徑,一般情況下,系統升級不會出問題 (非正規代碼,小概率會隨android升級修改新的代碼),如果方便的話,還是採用System.load(DecRawso.GetInstance().GetPath(「***"))
經過這幾個簡單的步驟,壓縮的SDK已經整合到工程內了。
四、 如何壓縮發布APK
使用ApkCompress.jar壓縮發布APK。 此工具為命令行工具。一般的此命令使用方式為:在命令行運行ComPressApk.jar-a C:/my/test.apk -k c:/key *** ### alias -x86http://www.test.com (也可以運行 java –jarComPressApk.jar )
-a 後面跟apk路徑名, 可以不是全路徑
-k 後面是簽名文件[key storepasskeypass alias name] ,key可以不是全路徑名 (name 如果不寫, 默認就是CERT)
-x86 表示需要存儲x86庫文件在雲端, 後面跟以http://開頭的鏈接,最後實際的存儲位置應該為 http://www.test.com/cloudrawso_x86
命令執行完以後, 會生成test_CompressAlign.apk. 這個apk就是壓縮後的apk
五、 開發模式和壓縮模式
為了方便開發,在實現開發的過程中(修改了源碼支持壓縮後),也可以不壓縮so,apk也可以正常運行,壓縮的SDK內部會自動判斷是否有壓縮包, 如果沒有壓縮包,則載入的路徑恢復成android默認的路徑。所以最方便的開發是,先整合代碼,在開發過程中和原來一樣開發(不壓縮),在發布的時候才壓縮apk
六、 X86和ARM庫混合調用
在實現開發過程中,可能會有某些第三方庫確實沒有x86版本,通常情況下ISV並不在x86目錄下放置arm的第三方庫,那麼在實際運行過程中會導致缺庫現象的發生。在缺庫的情況下,壓縮的SDK會在x86設備上自動解壓arm的壓縮包,避免缺庫現象的發生。(只有真正載入了缺失的庫才是缺庫,庫文件不一致並不一定就是缺庫)
但是顯然這樣會導致運行的低效率,如果在第三方so和x86的庫完全沒有相互引用的情況下(也就是說這些庫都是java層使用JNI調用的,在native層沒有相互調用),可以拷貝arm的第三方庫到x86目錄下,這樣就不會出現缺庫的情況。當然這種情況會導致arm庫多餘的拷貝,在以前的zip壓縮情況下,會使得壓縮包變大,但是在新的LZMA壓縮情況下,庫大小完全不會增大,因為LZMA壓縮由於字典比較大,能夠盡可能的壓縮關聯的幾個文件,如果文件完全相同,LZMA的壓縮會和單個文件基本一致。
如若滿意,請點擊右側【採納答案】,如若還有問題,請點擊【追問】
希望我的回答對您有所幫助,望採納!
~ O(∩_∩)O~
⑸ AndroidStudio如何配置NDK/JNIAndroidStudio怎麼調用so動態鏈接庫
AndroidStudio怎麼調用so動態鏈接庫?在我們日常開發中,經常會用到一些復雜的加密的演算法以保證通信的安全。通常這些演算法會用C或C++實現後打包成.so動態鏈接庫並向Java層開發介面方便調用。
以AndroidStudio為例
1 . 首先去下載NDK包,下載路徑如下可根據自己系統定點下載
https://developer.android.google.cn/ndk/downloads/index.html
static{
System.loadLibrary("jnitext");
}
publicnativeStringget_1111CLang_1String();