Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[so升级优化] #21

Open
wants to merge 3 commits into
base: egame_multi
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 64 additions & 20 deletions libp2pimpl/src/main/java/cn/vbyte/p2p/VbyteP2PModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,11 @@
import android.os.Message;
import android.os.Handler;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;

import java.lang.ref.WeakReference;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

Expand All @@ -22,7 +20,17 @@
* Created by passion on 15-11-5.
*/
public final class VbyteP2PModule {
private static final String DYNAMIC_LIB_NAME = "libp2pmodule";
private static final String LIB_P2PMODULE_SO = "libp2pmodule";

/**
* libp2pmodule的jni接口版本
*/
private final String P2PMODULE_JNI_VERSION = "v3";

/**
* 无JNI接口的JNI版(这是检查so升级必须的参数)
*/
public final String OTHTER_JNI_VERSION = "v0";

public static class Event {
/**
Expand Down Expand Up @@ -159,8 +167,8 @@ public static VbyteP2PModule getInstance() {
}

/**
* 获取native应用的版本号
* @return P2PModule SDK的版本号
* 获取p2p-sdk so库的版本号
* @return p2p-sdk so库的版本号
*/
public static String getVersion() {
if (SDK_VERSION == null) {
Expand All @@ -182,7 +190,7 @@ private static boolean isArchValid(String arch) {
* 返回5种架构中的一个获取null
*/
public static String getArchABI() {
if(archCpuAbi.isEmpty()) {
if(TextUtils.isEmpty(archCpuAbi)) {
archCpuAbi = VbyteP2PModule._targetArchABI();
}
return isArchValid(archCpuAbi) ? archCpuAbi : "";
Expand Down Expand Up @@ -247,40 +255,76 @@ public static void setLoggerCallback(LoggerCallback logger) {
private long _pointer;
private WeakReference<Context> _context;

private VbyteP2PModule(Context context, String appId, String appKey, String appSecretKey)
throws Exception {
if (context == null || appId == null || appKey == null || appSecretKey == null) {
throw new NullPointerException("context or appId or appKey or appSecretKey can't be null when init p2p live stream!");
/**
* 加载so
* @param context
* @param soNameWithoutSuffix so名称(不带后缀)
* @param jniVersion JNI版本(目前仅p2p的so才有jni接口),若该值为空则默认为 OTHTER_JNI_VERSION = 'v0'
*/
public void loadSo(Context context, String soNameWithoutSuffix, String jniVersion) {

if (TextUtils.isEmpty(soNameWithoutSuffix)) {
return;
}

System.loadLibrary("stun");
System.loadLibrary("event");
if (dynamicLibManager == null) {
dynamicLibManager = new DynamicLibManager(context);
}

if (TextUtils.isEmpty(jniVersion)) {
jniVersion = OTHTER_JNI_VERSION;
}

dynamicLibManager.ensureLibDir(jniVersion);

doLoadSo(soNameWithoutSuffix);
}

private void doLoadSo(String soNameWithoutSuffix) {
/**
*
* 能从jni里面获取到arch, 就进行下面的升级、加载,否则加载lib/ 下的libp2pmodule
* android.os.Build.CPU_ABI、android.os.Build.SUPPORT_ABIS不靠谱,很多机型获取不到,不能用这个。因此,不用这个获取。
* archCpuAbi再次验证一下
*/

String soFilePath = null;
dynamicLibManager = new DynamicLibManager(context);

try {
//这里加一个check libp2pmodule文件的md5值,因为应用目录/files目录下 很可能被别的应用扫描到给破坏了就load错误了
soFilePath = dynamicLibManager.locate(DYNAMIC_LIB_NAME);
soFilePath = dynamicLibManager.locate(soNameWithoutSuffix);
} catch (Exception e) {
// 因获取不到程序版本号而导致的自动升级失败,默认使用安装时自带的
}
if (soFilePath == null) {
System.loadLibrary("p2pmodule");
if (soNameWithoutSuffix.startsWith("lib")) {
String libNameWithoutPreffix = soNameWithoutSuffix.substring(3);
System.loadLibrary(libNameWithoutPreffix);
}
} else {
System.load(soFilePath);
}
}

if(!getArchABI().isEmpty()) {
private void checkUpdate(String soNameWithoutSuffix, String nativeVersion, String jniVersion) {
if(!TextUtils.isEmpty(getArchABI())) {
//得到了arch, 开始check升级用false即可
dynamicLibManager.checkUpdateV2(false, "libp2pmodule_" + VbyteP2PModule.getVersion() + "_20170928.so", getArchABI());
dynamicLibManager.checkUpdateV2(false, soNameWithoutSuffix, nativeVersion, jniVersion, getArchABI());
}
}

private VbyteP2PModule(Context context, String appId, String appKey, String appSecretKey)
throws Exception {
if (context == null || appId == null || appKey == null || appSecretKey == null) {
throw new NullPointerException("context or appId or appKey or appSecretKey can't be null when init p2p live stream!");
}

System.loadLibrary("stun");
System.loadLibrary("event");

//加载 libp2pmodule.so
loadSo(context, LIB_P2PMODULE_SO, P2PMODULE_JNI_VERSION);

//检查升级 libp2pmodule.so
checkUpdate(LIB_P2PMODULE_SO, VbyteP2PModule.getVersion(), P2PMODULE_JNI_VERSION);

_pointer = this._construct();
if (_pointer == 0) {
Expand Down
61 changes: 39 additions & 22 deletions libp2pimpl/src/main/java/com/vbyte/update/DynamicLibManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.text.TextUtils;
import android.util.Log;

import org.json.JSONObject;
import java.io.BufferedInputStream;
Expand Down Expand Up @@ -31,22 +32,18 @@ public class DynamicLibManager {
private String libDirPath;
private String currentLibDirPath;

//jni接口版本
private String jniVersion = "v3";
//非https要下载的so
private String[] soNameArr = new String[]{"libp2pmodule", "libstun", "libevent"};
private boolean supportHttps = false;
//https情况下要下载的so
private String[] soNameArrSupportHttps = new String[]{"libp2pmodule", "libstun", "libevent", "libevent_openssl", "libcrypto", "libssl"};
private static String archCpuAbi = "";

/**
* cpuArch为传进来的,让这个类可以不依赖外面的类,cpuArch为 armeabi、armeabi-v7a、armeabi-v8a、x86、x86_64中的一个
* @param context
*/
public DynamicLibManager(Context context) {
this.context = context;
libDirPath = this.context.getFilesDir().getAbsolutePath() + File.separator + "vlib";
public void ensureLibDir(String jniVersion) {

if (!TextUtils.isEmpty(currentLibDirPath)) {
return;
}

StringBuilder tmpCurrentLibDirPath = new StringBuilder();
tmpCurrentLibDirPath.append(context.getFilesDir().getAbsolutePath())
Expand Down Expand Up @@ -121,6 +118,16 @@ public boolean accept(File file) {
}
}


/**
* cpuArch为传进来的,让这个类可以不依赖外面的类,cpuArch为 armeabi、armeabi-v7a、armeabi-v8a、x86、x86_64中的一个
* @param context
*/
public DynamicLibManager(Context context) {
this.context = context;
libDirPath = this.context.getFilesDir().getAbsolutePath() + File.separator + "vlib";
}

public boolean isSoReady() {
//如果ready存在, files/vlib/当前jniVersion/当前armeabi/ready 那么hasAllJniSo = true
File currentLibDir = new File(currentLibDirPath);
Expand All @@ -134,8 +141,19 @@ public boolean isSoReady() {
}
}

//第一次升级, true "", 第二次只检查libp2pmodule的升级
public void checkUpdateV2(final boolean firstDownload, final String soName, final String arch) {
/**
* 检查升级,目前在两种场景下使用
* 1.南瓜首次运行下载所有的so.(南瓜对size有要求)
* 2.p2p-sdk的so升级
* @param downloadAllSo true 下载所有的so
* false 升级soNameWithoutSubffix指定的so
* @param soNameWithoutSuffix 不带后缀名的so名称
* @param nativeVersion so的版本
* @param jniVersion JNI接口版本,当前仅对libp2pmodule这个so有效(只有它有jni接口)
* @param arch 架构名称,例如armeabi|armeabi-v7a|arm64-v8a|x86|x86_64
*/
public void checkUpdateV2(final boolean downloadAllSo, final String soNameWithoutSuffix, final String nativeVersion, final String jniVersion, final String arch) {

/**
* 只有第一次下载的情况下,currentPath没有 endWith /armeabi-v7a
* 此时currentLibDirPath为
Expand Down Expand Up @@ -172,18 +190,18 @@ public void run() {
sb.append("&supportHttps=true");
soNameArr = soNameArrSupportHttps;
}
if (firstDownload) {
if (downloadAllSo) {
sb.append("&fileId=").append(TextUtils.join(",", soNameArr));
} else {
String[] tmpArr = soName.split("_");

if (tmpArr.length == 3) {
sb.append("&fileId=").append("libp2pmodule")
.append("&fifoVersion=").append(tmpArr[1]);
} else {
if (TextUtils.isEmpty(soNameWithoutSuffix) || TextUtils.isEmpty(nativeVersion)) {
return;
} else {
sb.append("&fileId=").append(soNameWithoutSuffix)
.append("&fifoVersion=").append(nativeVersion);
}
}

URL url = new URL(sb.toString());

HttpURLConnection conn = (HttpURLConnection) url.openConnection();
Expand All @@ -202,21 +220,20 @@ public void run() {

if (jsonObj.has("downloadUrl")) {
String[] downloadSoArr;
if (firstDownload) {
if (downloadAllSo) {
downloadSoArr = soNameArr;
} else {
downloadSoArr = new String[]{"libp2pmodule"};
downloadSoArr = new String[]{soNameWithoutSuffix};
}

Map<String, JSONObject> soJsonMap = new HashMap<>();

JSONObject jsonObjDownload = jsonObj.getJSONObject("downloadUrl");


for (String soName : downloadSoArr) {
if (jsonObjDownload.has(soName)) {
JSONObject jsonObjTmp = jsonObjDownload.getJSONObject(soName);
if (soName.equals("libp2pmodule")) {
if (soName.equals(soNameWithoutSuffix)) {
//如果是libp2pmodule还检查jniVersion字段
if (jsonObjTmp.has("jniVersion")
&& !TextUtils.isEmpty(jsonObjTmp.getString("jniVersion"))
Expand Down Expand Up @@ -249,7 +266,7 @@ public void run() {
JSONObject jsonObject = entry.getValue();
writeReady = (writeReady && updateDynamicLib(entry.getKey(), jsonObject.getString("url"), jsonObject.getString("version"), jsonObject.getString("md5token")));
}
if (firstDownload && writeReady) {
if (downloadAllSo && writeReady) {
//第一次下载且都下载成功创建文件标识符
new File(currentLibDirPath + File.separator + "ready").createNewFile();
}
Expand Down