插件化無法獲取或找到.so文件

java.lang.UnsatisfiedLinkError:?dalvik.system.DexClassLoader[DexPathList[[zip?file?"/data/user/0/com.xxx.xxx/myfile/sdkjar.apk"],nativeLibraryDirectories=[/data/user/0/com.xxx.xxx/myfile/lib,?/system/lib64,?/system/product/lib64]]]?couldn't?find?"libtobEncrypt.so"

問題的所在因為插件化的時候沒有吧so文件拷貝到/data/user/0/com.xxx.xxx/myfile/lib 文件夾下 ,注意不是/data/user/0/com.xxx.xxx/lib、而是/data/user/0/com.xxx.xxx/myfile/lib 第一個的區(qū)別在自己的lib/jinLibs目錄下忘記添加so 文件了

第二個是因為插件化問題 類加載器加載的緣故導致so讀取的路徑變了 變成/myfile/lib下

這里做法都是大同小異

直接將所缺的so文件放進assets文件夾中

然后安轉(zhuǎn)的時候?qū)o文件拷貝到data/user/0/com.xxx.xxx/myfile/lib 目錄下

這個操作要打開應(yīng)用之后判斷這個目錄是否存在 里面是否有對應(yīng)系統(tǒng)架構(gòu)的so文件即可

如果遇到是拷貝文件進去 遇到?jīng)]有讀寫權(quán)限 需要操作之前申請權(quán)限,是強制性的,

拿到權(quán)限之后 拷貝還是失敗晨仑,那是拷貝的姿勢有問題了?

```

123

```

```

解析代碼如下

ApplicationInfo info = context.getApplicationInfo();

//1.如果解壓之后有對應(yīng)的包名/lib之下有so文件 先拷貝到/myfile/lib下面 改操作的好處是系統(tǒng)直接默認選好是使用哪個系統(tǒng)架構(gòu)的so文件,不需要我們再另行判斷哪個系統(tǒng)架構(gòu)

? ? ? ? String PathOne ="/data/user/0/"+getPackageName(context)+"/lib";

String PathA ="/data/data/"+info.packageName+"/lib";

//上面的成功之后可以不執(zhí)行下面第二部 可以判斷data/user/0/com.xxx.xxx/myfile/lib/xxx.so文件是否存在 存在則不執(zhí)行第二部

//? 2.如果解壓之后有對應(yīng)的包名/lib之下沒有so文件 則再從Assets/lib對應(yīng)系統(tǒng)架構(gòu)的so文件拷貝到/myfile/lib下面 該處需要我們另行判斷系統(tǒng)架構(gòu)

? ? ? ? String PathTwo ="/data/user/0/"+getPackageName(context)+"/myfile/lib";

String PathB ="/data/data/"+info.packageName+"/myfile/lib";

Log.e("info.packageName","info.packageName=====" +info.packageName);

Log.e("PathOne","PathOnee=====" +PathOne);

Log.e("PathTwo","PathTwo=====" +PathTwo);

Log.e("PathA","PathA=====" +PathA);

Log.e("PathB","PathB=====" +PathB);

//從assets拷貝文件到包名,米辐,,书释。/data/user/0/com.gzzwyx.bzfgx.zhiwan/myfile/lib之下

? ? ? ? String systemArchitecture =DriverTypeUtils.getCPUABI();

Log.d("copylibFile","2isLibc64()=======查詢當前的系統(tǒng)架構(gòu)是======="+systemArchitecture);//查詢是x64還是x86

? ? ? ? Log.e("allPathC"," 當前拷貝的so文件的路徑為:=====" +"lib/"+systemArchitecture+"/libEncryptorP.so");

CopySoFileToLib.copyFilesFromAssets(context,"lib/"+systemArchitecture,PathTwo);

CopySoFileToLib.copyFilesFromAssets(context,"lib/"+systemArchitecture,PathB);


// 獲取acitivty所在的應(yīng)用包名

public static String getPackageName(Context context) {

ApplicationInfo appInfo = context.getApplicationInfo();

String packageName = appInfo.packageName;// 獲取當前游戲安裝包名

? ? return packageName;

}

```

```

//拷貝工具類

import android.content.Context;

import android.util.Log;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

public class CopySoFileToLib {

/**

? ? * 復(fù)制文件夾及其中的文件 該作用主要是 /data/user/0/com.gzzwyx.bzfgx.zhiwan/huosdkv8/lib為空時 從/data/user/0/com.gzzwyx.bzfgx.zhiwan/lib處拷貝過去

? ? *

? ? * @param oldPath String 原文件夾路徑 如:data/user/0/com.test/files

? ? * @param newPath String 復(fù)制后的路徑 如:data/user/0/com.test/cache

? ? * @return <code>true</code>if and only if the directory and files were copied;

? ? * <code>false</code>otherwise

*/

? ? public static boolean copyFolder(String oldPath, String newPath) {

try {

File newFile =new File(newPath);

if (!newFile.exists()) {

if (!newFile.mkdirs()) {

Log.e("--Method--","copyFolder: cannot create directory.");

return false;

}

}

File oldFile =new File(oldPath);

String[] files = oldFile.list();

File temp;

for (String file : files) {

if (oldPath.endsWith(File.separator)) {

temp =new File(oldPath + file);

}else {

temp =new File(oldPath + File.separator + file);

}

if (temp.isDirectory()) {//如果是子文件夾

? ? ? ? ? ? ? ? ? ? copyFolder(oldPath +"/" + file, newPath +"/" + file);

}else if (!temp.exists()) {

Log.e("--Method--","copyFolder:? oldFile not exist.");

return false;

}else if (!temp.isFile()) {

Log.e("--Method--","copyFolder:? oldFile not file.");

return false;

}else if (!temp.canRead()) {

Log.e("--Method--","copyFolder:? oldFile cannot read.");

return false;

}else {

FileInputStream fileInputStream =new FileInputStream(temp);

FileOutputStream fileOutputStream =new FileOutputStream(newPath +"/" + temp.getName());

byte[] buffer =new byte[1024];

int byteRead;

while ((byteRead = fileInputStream.read(buffer)) != -1) {

fileOutputStream.write(buffer,0, byteRead);

}

fileInputStream.close();

fileOutputStream.flush();

fileOutputStream.close();

}

}

return true;

}catch (Exception e) {

e.printStackTrace();

return false;

}

}

/**

? ? *? 從assets目錄中復(fù)制整個文件夾內(nèi)容到新的路徑下

? ? *? @param? context? Context 使用CopyFiles類的Activity

? ? *? @param? oldPath? String? 原文件路徑? 如:Data(assets文件夾下文件夾名稱)

? ? *? @param? newPath? String? 復(fù)制后路徑? 如:data/data/(手機內(nèi)部存儲路徑名稱)

? ? */

? ? public static Boolean copyFilesFromAssets(Context context, String oldPath, String newPath) {

try {

String fileNames[] = context.getAssets().list(oldPath);//獲取assets目錄下的所有文件及目錄名

? ? ? ? ? ? if (fileNames.length >0) {//如果是目錄

? ? ? ? ? ? ? ? File file =new File(newPath);

file.mkdirs();//如果文件夾不存在翘贮,則遞歸

? ? ? ? ? ? ? ? for (String fileName : fileNames) {

copyFilesFromAssets(context,oldPath +"/" + fileName,newPath+"/"+fileName);

}

}else {//如果是文件

? ? ? ? ? ? ? ? InputStream is = context.getAssets().open(oldPath);

FileOutputStream fos =new FileOutputStream(new File(newPath));

byte[] buffer =new byte[1024];

int byteCount=0;

while((byteCount=is.read(buffer))!=-1) {//循環(huán)從輸入流讀取 buffer字節(jié)

? ? ? ? ? ? ? ? ? ? fos.write(buffer,0, byteCount);//將讀取的輸入流寫入到輸出流

? ? ? ? ? ? ? ? }

fos.flush();//刷新緩沖區(qū)

? ? ? ? ? ? ? ? is.close();

fos.close();

}

return true;

}catch (Exception e) {

// TODO Auto-generated catch block

? ? ? ? ? ? e.printStackTrace();

return? false;

////如果捕捉到錯誤則通知UI線程

//MainActivity.handler.sendEmptyMessage(COPY_FALSE);

? ? ? ? }

}

? ? //拷貝整個文件夾到某個路徑上

? ? public static void CopyAssets(Context context, String assetDir, String dir) {

String[] files;

try {

files = context.getResources().getAssets().list(assetDir);

}catch (IOException e1) {

return;

}

File mWorkingPath =new File(dir);

// if this directory does not exists, make one.

? ? ? ? if (!mWorkingPath.exists()) {

if (!mWorkingPath.mkdirs()) {

}

}

for (int i =0; i < files.length; i++) {

try {

String fileName = files[i];

// we make sure file name not contains '.' to be a folder.

? ? ? ? ? ? ? ? if (!fileName.contains(".")) {

if (0 == assetDir.length()) {

CopyAssets(context, fileName, dir + fileName +"/");

}else {

CopyAssets(context, assetDir +"/" + fileName, dir+ fileName +"/");

}

continue;

}

File outFile =new File(mWorkingPath, fileName);

if (outFile.exists())

outFile.delete();

InputStream in =null;

if (0 != assetDir.length())

in = context.getAssets().open(assetDir +"/" + fileName);

else

? ? ? ? ? ? ? ? ? ? in = context.getAssets().open(fileName);

OutputStream out =new FileOutputStream(outFile);

// Transfer bytes from in to out

? ? ? ? ? ? ? ? byte[] buf =new byte[1024];

int len;

while ((len = in.read(buf)) >0) {

out.write(buf,0, len);

}

in.close();

out.close();

}catch (FileNotFoundException e) {

e.printStackTrace();

}catch (IOException e) {

e.printStackTrace();

}

}

}

}

```

```

//手機系統(tǒng)架構(gòu)判斷工具類

import android.text.TextUtils;

import android.util.Log;

import java.io.BufferedReader;

import java.io.File;

import java.io.FileInputStream;

import java.io.InputStreamReader;

/*

*該工具類主要作用是查詢設(shè)備是x64還是x86

*/

public class DriverTypeUtils {

public static final StringCPU_ARCHITECTURE_TYPE_32 ="32";

public static final StringCPU_ARCHITECTURE_TYPE_64 ="64";

/** ELF文件頭 e_indent[]數(shù)組文件類標識索引 */

? ? private static final int EI_CLASS =4;

/** ELF文件頭 e_indent[EI_CLASS]的取值:ELFCLASS32表示32位目標 */

? ? private static final int ELFCLASS32 =1;

/** ELF文件頭 e_indent[EI_CLASS]的取值:ELFCLASS64表示64位目標 */

? ? private static final int ELFCLASS64 =2;

/** The system property key of CPU arch type */

? ? private static final StringCPU_ARCHITECTURE_KEY_64 ="ro.product.cpu.abilist64";

/** The system libc.so file path */

? ? private static final StringSYSTEM_LIB_C_PATH ="/system/lib/libc.so";

private static final StringSYSTEM_LIB_C_PATH_64 ="/system/lib64/libc.so";

private static final StringPROC_CPU_INFO_PATH ="/proc/cpuinfo";

private static boolean LOGENABLE =false;

/**

* Check if system libc.so is 32 bit or 64 bit

*/

? ? public static boolean isLibc64() {

File libcFile =new File(SYSTEM_LIB_C_PATH);

if (libcFile !=null && libcFile.exists()) {

byte[] header =readELFHeadrIndentArray(libcFile);

if (header !=null && header[EI_CLASS] ==ELFCLASS64) {

if (LOGENABLE) {

Log.d("#####isLibc64()",SYSTEM_LIB_C_PATH +" is 64bit");

}

return true;

}

}

File libcFile64 =new File(SYSTEM_LIB_C_PATH_64);

if (libcFile64 !=null && libcFile64.exists()) {

byte[] header =readELFHeadrIndentArray(libcFile64);

if (header !=null && header[EI_CLASS] ==ELFCLASS64) {

if (LOGENABLE) {

Log.d("####isLibc64()",SYSTEM_LIB_C_PATH_64 +" is 64bit");

}

return true;

}

}

return false;

}

/**

? ? * ELF文件頭格式是固定的:文件開始是一個16字節(jié)的byte數(shù)組e_indent[16]

? ? * e_indent[4]的值可以判斷ELF是32位還是64位

? ? */

? ? private static byte[] readELFHeadrIndentArray(File libFile) {

if (libFile !=null && libFile.exists()) {

FileInputStream inputStream =null;

try {

inputStream =new FileInputStream(libFile);

if (inputStream !=null) {

byte[] tempBuffer =new byte[16];

int count = inputStream.read(tempBuffer,0,16);

if (count ==16) {

return tempBuffer;

}else {

if (LOGENABLE) {

Log.e("readELFHeadrIndentArray","Error: e_indent lenght should be 16, but actual is " + count);

}

}

}

}catch (Throwable t) {

if (LOGENABLE) {

Log.e("readELFHeadrIndentArray","Error:" + t.toString());

}

}finally {

if (inputStream !=null) {

try {

inputStream.close();

}catch (Exception e) {

e.printStackTrace();

}

}

}

}

return null;

}

/*

? ? * 該方法的作用是判斷手機使用哪種架構(gòu)的 、Android獲取CPU架構(gòu)* */

? ? public static StringCPUABI =null;

public static String getCPUABI() {

if (CPUABI ==null) {

try {

String os_cpuabi =new BufferedReader(new InputStreamReader(Runtime.getRuntime().exec("getprop ro.product.cpu.abi").getInputStream())).readLine();

if (os_cpuabi.contains("x86")) {

CPUABI ="x86";

return "x86";

}else if (os_cpuabi.contains("armeabi-v7a") || os_cpuabi.contains("arm64-v8a")) {

CPUABI ="armeabi-v7a";

return "armeabi-v7a";

}else {

CPUABI ="armeabi";

return "armeabi";

}

}catch (Exception e) {

CPUABI ="armeabi";

return "armeabi";

}

}

if (CPUABI ==null || TextUtils.isEmpty(CPUABI)) {

Boolean isLib64CPU =isLibc64();

if (isLib64CPU){

CPUABI="armeabi";

}else {

CPUABI="x86";

}

}

return CPUABI;

}

}

```

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末爆惧,一起剝皮案震驚了整個濱河市狸页,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌扯再,老刑警劉巖芍耘,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件址遇,死亡現(xiàn)場離奇詭異,居然都是意外死亡斋竞,警方通過查閱死者的電腦和手機倔约,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來坝初,“玉大人跺株,你說我怎么就攤上這事〔甭簦” “怎么了乒省?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長畦木。 經(jīng)常有香客問我袖扛,道長,這世上最難降的妖魔是什么十籍? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任蛆封,我火速辦了婚禮,結(jié)果婚禮上勾栗,老公的妹妹穿的比我還像新娘惨篱。我一直安慰自己,他們只是感情好围俘,可當我...
    茶點故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布砸讳。 她就那樣靜靜地躺著,像睡著了一般界牡。 火紅的嫁衣襯著肌膚如雪簿寂。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天宿亡,我揣著相機與錄音常遂,去河邊找鬼。 笑死挽荠,一個胖子當著我的面吹牛克胳,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播圈匆,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼漠另,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了臭脓?” 一聲冷哼從身側(cè)響起酗钞,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后砚作,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體窘奏,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年葫录,在試婚紗的時候發(fā)現(xiàn)自己被綠了着裹。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡米同,死狀恐怖骇扇,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情面粮,我是刑警寧澤少孝,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站熬苍,受9級特大地震影響稍走,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜柴底,卻給世界環(huán)境...
    茶點故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一婿脸、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧柄驻,春花似錦狐树、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至答憔,卻和暖如春味赃,著一層夾襖步出監(jiān)牢的瞬間掀抹,已是汗流浹背虐拓。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留傲武,地道東北人蓉驹。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像揪利,于是被迫代替她去往敵國和親态兴。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,452評論 2 348

推薦閱讀更多精彩內(nèi)容