动态加载so文件方案实现

This commit is contained in:
gongduoxiang
2024-07-30 13:39:37 +08:00
parent 3a12d848e1
commit 1f66204031
31 changed files with 1612 additions and 19 deletions

View File

@@ -0,0 +1,240 @@
package com.yunbao.common.utils;
import android.content.Context;
import android.content.res.AssetManager;
import android.util.Log;
import org.jetbrains.annotations.NotNull;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Cookie;
import okhttp3.CookieJar;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class LoadSoUtil {
public static void loadSo(Context context, onLoadSoListener listener) {
try {
String path = context.getFilesDir().getAbsolutePath() + "/dynamic_so";
File file = new File(path);
AssetManager assetManager = context.getAssets();
String[] files = assetManager.list("libso");
if (!file.exists()) {
boolean b = file.mkdir();
Log.i("mLog", "创建文件 " + b);
}
if (file.listFiles().length != files.length) {//说明之前已经保存了
file.delete();
file.mkdir();
Log.i("mLog", "需要拷贝so文件 ");
// 获取AssetManager对象
for (int i = 0; i < files.length; i++) {
loadLibrary(context, "libso/" + files[i], files[i]);
}
}
listener.ok();
Log.i("mLog", "拷贝so成功------------------------");
} catch (IOException e) {
Log.e("mLog", "拷贝so错误++++++++++++++++++++");
e.printStackTrace();
listener.error();
}
}
public static void loadSo2(Context context, onLoadSoListener listener) {
String path = context.getFilesDir().getAbsolutePath() + "/so_zip";
File file = new File(path);
if (!file.exists()) {
file.mkdir();
} else if (isLoadSo(context)) {
listener.ok();
return;
}
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10 * 5, TimeUnit.SECONDS)
.cookieJar(new CookieJar() {
private final HashMap<String, List<Cookie>> cookieStore = new HashMap<>();
@Override
public void saveFromResponse(@NotNull HttpUrl httpUrl, @NotNull List<Cookie> list) {
cookieStore.put(httpUrl.host(), list);
}
@NotNull
@Override
public List<Cookie> loadForRequest(@NotNull HttpUrl httpUrl) {
List<Cookie> cookies = cookieStore.get(httpUrl.host());
return cookies != null ? cookies : new ArrayList<>();
}
});
builder.hostnameVerifier((hostname, session) -> true);
//开始下载文件
downloadFile(builder.build(), "https://downs.yaoulive.com/x86.zip", new File(path + "/" + "libSo.zip"), new onLoadSoListener() {
@Override
public void ok() {
//下载完成开始解压 解压完成之后 区初始化声网数据
zip(context, path + "/" + "libSo.zip", listener);
}
@Override
public void error() {
listener.error();
}
});
}
private static void zip(Context context, String path, onLoadSoListener listener) {
ZipInputStream zis = null;
FileOutputStream fos = null;
try {
zis = new ZipInputStream(new FileInputStream(path));
ZipEntry ze;
String soPath = context.getFilesDir().getAbsolutePath() + "/dynamic_so";
File file = new File(soPath);
if (!file.exists()) {
file.mkdir();
}
while ((ze = zis.getNextEntry()) != null) {
String fileName = ze.getName();
File newFile = new File(soPath + File.separator + fileName);
fos = new FileOutputStream(newFile);
byte[] buffer = new byte[1024];
int len;
while ((len = zis.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
fos.close();
zis.closeEntry();
}
listener.ok();
} catch (IOException e) {
e.printStackTrace();
listener.error();
} finally {
try {
if (zis != null) zis.close();
if (fos != null) fos.close();
} catch (Exception e) {
}
}
}
private static void downloadFile(OkHttpClient mOkHttpClient, String url, File file, onLoadSoListener listener) {
Request request = new Request.Builder()
.get()
.url(url)
.build();
mOkHttpClient.newCall(request)
.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
if (listener != null) listener.error();
}
@Override
public void onResponse(Call call, Response response) {
if (response.isSuccessful()) {
InputStream is = null;
BufferedOutputStream bos = null;
try {
is = response.body().byteStream();
bos = new BufferedOutputStream(new FileOutputStream(file));
byte[] bytes = new byte[10240];
int len;
while ((len = is.read(bytes)) != -1) {
bos.write(bytes, 0, len);
}
bos.flush();
if (listener != null) listener.ok();
} catch (Exception e) {
e.printStackTrace();
if (listener != null) listener.error();
} finally {
try {
if (bos != null) bos.close();
if (is != null) is.close();
} catch (Exception e) {
}
}
}
}
});
}
public static boolean isLoadSo(Context context) {
String pathSo = context.getFilesDir().getAbsolutePath() + "/dynamic_so";
File fileSo = new File(pathSo);
if (fileSo.listFiles().length == 22) {//说明之前已经保存了
Log.i("mLog", "已经下载了so 所有直接加载就行 ");
return true;
}
return false;
}
public static boolean loadLibrary(Context context, String oldFileName, String libName) throws IOException {
// 获取应用的私有模式的libs目录真实的目录是app-libs
String path = context.getFilesDir().getAbsolutePath() + "/dynamic_so/";
// 可以获取到assets资源文件的数据流
InputStream open = context.getAssets().open(oldFileName);
String new_file_name = path + libName;
// 把资源文件的数据流写入到app-libs目录下
if (!copyLibrary(open, new_file_name)) {
return false;
}
return true;
}
//从assets资源目录下复制到app-libs目录下
public static boolean copyLibrary(InputStream fileInputStream, String new_file) {
FileOutputStream fos = null;
try {
File file = new File(new_file);
fos = new FileOutputStream(file);
int dataSize;
byte[] dataBuffer = new byte[2048];
while ((dataSize = fileInputStream.read(dataBuffer)) != -1) {
fos.write(dataBuffer, 0, dataSize);
}
fos.flush();
return true;
} catch (Exception e) {
e.printStackTrace();
Log.e("mLog", e.getMessage());
} finally {
try {
if (fos != null) fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return false;
}
public interface onLoadSoListener {
void ok();
void error();
}
}