




下載本文檔
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
【移動(dòng)應(yīng)用開發(fā)技術(shù)】Android中怎么利用Robolectric加載運(yùn)行本地So動(dòng)態(tài)庫
這篇文章將為大家詳細(xì)講解有關(guān)Android中怎么利用Robolectric加載運(yùn)行本地So動(dòng)態(tài)庫,文章內(nèi)容質(zhì)量較高,因此在下分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。前言Robolectric是Android的單元測(cè)試框架,運(yùn)行無需Android真機(jī)環(huán)境直接運(yùn)行在JVM之上,所以在testcase
運(yùn)行速度效率上有了很大提升,接近于JavaJUnittest(JUnittest>Robolectric?
androidTest)。不過框架本身并不支持so本地庫的加載使用,加載時(shí)會(huì)直接報(bào)錯(cuò),因?yàn)閷?shí)際上運(yùn)行環(huán)境是電腦機(jī)器,而我們打出的so
文件是給手機(jī)上用的所以當(dāng)然會(huì)報(bào)錯(cuò)。雖然在GitHub上很多人問過關(guān)于使用so
的問題但基本都建議說不要在單元測(cè)試中去加載本地庫,這在原則上是要這么做,但可能有些項(xiàng)目中做起來就有些困難了,比如在代碼結(jié)構(gòu)不夠好、依賴耦合較大或者本身就對(duì)so
庫依賴很大的情況下。所以下面說說在項(xiàng)目中Robolectric要怎么解決需要加載運(yùn)行本地so庫這個(gè)問題。動(dòng)態(tài)庫動(dòng)態(tài)庫又稱動(dòng)態(tài)鏈接庫(Dynamic-linklibrary縮寫DLL),是一個(gè)包含可由多個(gè)程序同時(shí)使用的代碼和數(shù)據(jù)的庫,DLL
不是可執(zhí)行文件。動(dòng)態(tài)鏈接提供了一種方法,使進(jìn)程可以調(diào)用不屬于其可執(zhí)行代碼的函數(shù)。函數(shù)的可執(zhí)行代碼位于一個(gè)DLL中,該DLL
包含一個(gè)或多個(gè)已被編譯、鏈接并與使用它們的進(jìn)程分開存儲(chǔ)的函數(shù)。DLL還有助于共享數(shù)據(jù)和資源。多個(gè)應(yīng)用程序可同時(shí)訪問內(nèi)存中單個(gè)DLL副本的內(nèi)容。DLL
是一個(gè)包含可由多個(gè)程序同時(shí)使用的代碼和數(shù)據(jù)的庫。Windows下動(dòng)態(tài)庫為.dll后綴(一般為PE格式),在Linux在為.so后綴(一般為
ELF格式),macOS下為.dylib后綴(一般為Mach-O格式)。由于CPU
架構(gòu)和動(dòng)態(tài)庫文件格式的不同因而在不同平臺(tái)下不能通用。其它細(xì)節(jié)的東西就不展開了因?yàn)橐膊粫?huì):-)而Android本身是Linux系統(tǒng),所以用的動(dòng)態(tài)庫也是.so的文件,因而運(yùn)行與JVM的Robolectric
是不能直接加載使用的(Linux某些情況下可用,下面提到)。Robolectric中使用動(dòng)態(tài)庫我們知道動(dòng)態(tài)庫一般都是打給特定平臺(tái)、特定CPU架構(gòu)用的,所以要解決在Robolectric下加載運(yùn)行so動(dòng)態(tài)庫的問題的思路就是在不同
Robolectric運(yùn)行平臺(tái)下去處理加載不同的動(dòng)態(tài)庫,所以你要在Ronbolectriv中使用的so動(dòng)態(tài)庫***要有源碼不然在macOS和
Windows下就不就好處理了。Note:注意動(dòng)態(tài)庫名稱已lib開頭。Linux下Robolectric中使用動(dòng)態(tài)庫Android與Linux同氣連枝,所以底層的東西很多是通用的,動(dòng)態(tài)庫也一樣。我們Android使用so時(shí)一般也要對(duì)不同CPU
架構(gòu)的手機(jī)下使用不同的so文件,譬如:armeabi-v7a、mips、x86。而我們使用的LInux發(fā)行版一般都是64
位的,所以原理上我們使用x86-64的動(dòng)態(tài)庫是可以的,不過可能需要處理依賴庫問題如果你的本地代碼里有include其它依賴的話。如果沒加進(jìn)來
Robolectric運(yùn)行就會(huì)報(bào)如下的錯(cuò)誤:java.lang.UnsatisfiedLinkError:
xxx/xxx.so
xxx
動(dòng)態(tài)庫找不到。xxx.so就是你所使用so的依賴,比如把新浪微博SDK的x86-64的libweibosdkcore.so加載進(jìn)來的話就會(huì)報(bào)
liblog.so等找不到,因?yàn)閘ibweibosdkcore中有對(duì)Androidliblog等so庫的依賴。那這個(gè)問題怎么解決呢。我們想想打包
so庫時(shí)用的是ndk,需要使用ndk-bundle工具,我們想想,跟編譯apk差不多,apk打包需要sdk工具,compileSdk
里就是我們編譯的依賴,里面有android.jar。所以我們可以到ndk-bundle里找找,***我們發(fā)現(xiàn)不同CPU架構(gòu)下的so
依賴庫都是有的,像我們一般的電腦64位CPU即可使用arch-x86_64下的so動(dòng)態(tài)庫,所以我們只需要在加載我們程序的so
庫之前加載這些必須的依賴即可。處理代碼后面貼出。注意ndk-bundle里的so也是只能在Linux下用的,如果用于其它平臺(tái)會(huì)報(bào)錯(cuò),原因前面已說明。java.lang.UnsatisfiedLinkError:
xxx.so:
unknown
file
type,
first
eight
bytes:
0x7F
0x45
0x4C
0x46
0x02
0x01
0x01
0x00macOS下Robolectric中使用動(dòng)態(tài)庫前面已提到,不同平臺(tái)下動(dòng)態(tài)鏈接庫是不通用的,所以必須對(duì)源碼重新編譯打包以移植到不同平臺(tái)下,如果你的so沒有源碼的話那在macOS和Windows
下就行不通了。重新打包我們可以按如下兩步進(jìn)行:#
先生成
.o
,-I
后加進(jìn)
Java
jni
的編譯依賴
cc
-c
-I/System/Library/Frameworks/JavaVM.framework/Headers
*.cpp
#
打包成
.dylib
g++
-dynamiclib
-undefined
suppress
-flat_namespace
*.o
-o
something.dylib某些依賴庫可以到/usr/lib下找找,比如libc和libstdc++。Windows下Robolectric中使用動(dòng)態(tài)庫本人沒有在Windows下開發(fā)所以這部分就略過了,思路是一樣的。Sample下面是簡單的處理代碼示例。首先新建一個(gè)包含jni的工程,里面寫個(gè)基本的本地庫,如下:正常流程//
native-lib.cpp
#include
<jni.h>
#include
<string>
extern
"C"
jstring
Java_xyz_rocko_rsnl_nativeinterface_NativeSample_stringFromJNI(
JNIEnv
*env,
jobject
/*
this
*/)
{
//
簡單返回個(gè)字符串
std::string
hello
=
"Hello
from
Native.";
return
env->NewStringUTF(hello.c_str());
}然后在Application啟動(dòng)時(shí)會(huì)加載這個(gè)本地庫://NativeLibsApplication.javapublic
class
NativeLibsApplication
extends
Application
{
//
Used
to
load
the
'native-lib'
library
on
application
startup.
static
{
System.loadLibrary("native-lib");
}
}此時(shí)運(yùn)行Robolectric的testcase就發(fā)生如下報(bào)錯(cuò):java.lang.UnsatisfiedLinkError:
no
native-lib
in
java.library.path處理后的流程首先流程應(yīng)該在我們的代碼里避免可以直接加載so動(dòng)態(tài)庫,然后Robolectric在啟動(dòng)時(shí)自己去加載需要的動(dòng)態(tài)庫。//NativeLibsApplication.javapublic
class
NativeLibsApplication
extends
Application
{
@Override
public
void
onCreate()
{
super.onCreate();
loadNativeLibraries();
}
/**
*
簡單讓子類可自己實(shí)現(xiàn)
*/
protected
void
loadNativeLibraries()
{
//
代碼里真正加載本地庫的地方,當(dāng)然你自己的可以處理地更解耦一點(diǎn)。
NativeLibrariesManager.loadNativeLibraries();
}
}然后我們的Robolectric里自定義自己的Application,里面根據(jù)需要在不同運(yùn)行平臺(tái)下自己加載需要的本地動(dòng)態(tài)庫,首先復(fù)制我們給
Robolectric用的本地庫到test的libs文件夾里,按不同平臺(tái)分類,如下圖:Linux下的我們從ndk-bundle里復(fù)制我們需要的.so,然后我們自己的本地庫打一個(gè)x86-64的即可,注意
compileSdkVersion選上高一點(diǎn)支持x86-64的版本。然后重新移植打出macOS下的動(dòng)態(tài)庫,簡單寫個(gè)打包腳本如下://make_macOS_dylib.sh#!/usr/bin/env
bash
OUTPUT=../../../build/intermediates/dylibs
mkdir
-p
${OUTPUT}
#
.o
file
cc
-c
-I/System/Library/Frameworks/JavaVM.framework/Headers
*.cpp
-o
${OUTPUT}/libnative-lib.o
#
.dylib
file
g++
-dynamiclib
-undefined
suppress
-flat_namespace
${OUTPUT}/*.o
-o
${OUTPUT}/libnative-lib.dyliblibnative-lib.dylib就是我們要的。然后我們自定義Application處理加載這些動(dòng)態(tài)庫://RobolectricApplication.javapublic
class
RobolectricApplication
extends
NativeLibsApplication
{
static
{
ShadowLog.stream
=
System.out;
//Android
logcat
output.
}
@Override
protected
void
loadNativeLibraries()
{
//Disable
super
class
load
so
file.
//super.loadNativeLibraries();
Log.d(TAG,
"=====>>
Robolectric
start
native
libraries.");
String
libsBasePath
=
new
File(new
File("").getAbsolutePath()
+
"/src/test/libs").getAbsolutePath();
String
os
=
System.getProperty("");
os
=
!TextUtils.isEmpty(os)
?
os
:
"";
List<File>
soFileList
=
new
ArrayList<>();
String
systemArchPath
=
libsBasePath
+
"/framework/";
//!!!
64
位機(jī)器下處理
if
(os.contains("Mac"))
{
//load
system
library
if
need
String
macSysSoBasePath
=
systemArchPath
+
"macOS/";
soFileList.addAll(addLibs(macSysSoBasePath));
//
App
so...
String
macAppSoPath
=
libsBasePath
+
"/macOS_x86-64/";
//
mac下so要使用macOS專用庫
soFileList.addAll(addLibs(macAppSoPath));
}
else
if
(os.contains("Linux"))
{
//load
system
library
if
need
String
linuxSysSoBasePath
=
systemArchPath
+
"arch_x86-64/";
soFileList.addAll(addLibs(linuxSysSoBasePath));
//
App
so...
String
linuxAppSoPath
=
libsBasePath
+
"/linux_x86-64/";
soFileList.addAll(addLibs(linuxAppSoPath));
}
else
if
(os.contains("Windows"))
{
//
ignore
}
for
(File
soFie
:
soFileList)
{
System.load(soFie.getAbsolutePath());
}
}
private
List<File>
addLibs(@NonNull
String
path)
{
File[]
basePathFiles
=
new
File(path).listFiles();
List<File>
pathFilesList
=
new
ArrayList<>();
if
(basePathFiles
!=
null
&&
basePathFiles.length
>
0)
{
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 大型游樂設(shè)施租賃合同樣本
- 商業(yè)綜合體地簧門改造合同
- 國內(nèi)海運(yùn)貨物保險(xiǎn)合同樣本
- 擔(dān)架使用培訓(xùn)課件
- 壓力容器安全管理考核試卷
- 動(dòng)物用藥品店面的環(huán)境設(shè)計(jì)與氛圍營造考核試卷
- 有機(jī)合成原料在綠色涂料技術(shù)的創(chuàng)新考核試卷
- 木材產(chǎn)品環(huán)保性能提升考核試卷
- 整流器在數(shù)據(jù)中心能源效率優(yōu)化考核試卷
- 智慧城市和自然資源的合理利用考核試卷
- 2025年湖南鐵路科技職業(yè)技術(shù)學(xué)院單招職業(yè)技能測(cè)試題庫參考答案
- 十一種正方體展開平面圖(僅打?。?/a>
- 2022年四川省綿陽市中考化學(xué)試卷
- (完整版)微生物檢驗(yàn)技術(shù)練習(xí)題(含答案)
- 佛山市內(nèi)戶口遷移申請(qǐng)表
- 《工程制圖完整》課件
- 常見焊接缺陷以及其處理方法PPT
- 《子宮脫垂護(hù)理查房》
- 關(guān)于對(duì)項(xiàng)目管理的獎(jiǎng)懲制度
- A320主起落架收放原理分析及運(yùn)動(dòng)仿真
- 2. SHT 3543-2017施工過程文件表格
評(píng)論
0/150
提交評(píng)論