原本很早就想把這些東西寫文章保留下來锦针,但是只怪自己真的太懶啦仁堪,2年后的今天才開始整理當(dāng)時(shí)工作時(shí)的思路
背景
- 借助Android 4G 阶捆,WiFi 雙網(wǎng)絡(luò)模式可以互補(bǔ)倦卖,大大的提高應(yīng)用的穩(wěn)定性
- 作為一款工具類產(chǎn)品鸠匀,WiFi蕉斜,4G流量,使我們的業(yè)務(wù)重心,如何將4G & WiFi
徹底打通蛛勉,為用戶提供更沉浸式的服務(wù)體驗(yàn)鹿寻,使我們一直以來的最求
思路
- 非常感謝國外的一款產(chǎn)品,在實(shí)現(xiàn)上為我們提供了一個入門的思路 speedify
no bb show my code
如果有人感興趣這個實(shí)現(xiàn)過程诽凌,可以單獨(dú)來交流
具體實(shí)現(xiàn)方案
- 準(zhǔn)備工作:
- 此方案借助了VPN來實(shí)現(xiàn)本地流量的劫持毡熏,并控制發(fā)送網(wǎng)絡(luò)通道
- 因?yàn)锳ndroid版本的差異性,實(shí)現(xiàn)方案也將按照高低不同版本來設(shè)計(jì)
- 因?yàn)楝F(xiàn)在手上已經(jīng)沒有那么多資源侣诵,所以更多的是代碼和思路講解痢法,如果你感興趣可能需要自己做一部分前置工作
eg: VPN 搭建,后臺配套服務(wù)
基本實(shí)現(xiàn)思路
API < 6.0
- 啟動Android手機(jī)高速網(wǎng)卡杜顺,在啟動成功后將高速網(wǎng)卡 和 VPN出口IP綁定
public class SetupHIPRIEnableTask extends TimerTask {
private static final String TAG = "SetupHIPRIEnableTask\t";
private Context mContext;
public SetupHIPRIEnableTask(Context context) {
mContext = context;
}
@Override
public void run() {
try {
DLog.i(TAG + "Polling mobile network to make sure it stays up");
ConnectivityManager connectivityManager = (ConnectivityManager) mContext
.getSystemService(CONNECTIVITY_SERVICE);
if (connectivityManager == null) {
Log.e(TAG, "ConnectivityManager is null, cannot try to force a mobile connection");
} else if (connectivityManager.getNetworkInfo(5) == null) {
Log.e(TAG, "Mobile Interface Not Found.");
} else {
int startUsingNetworkFeature = connectivityManager.startUsingNetworkFeature(0, "enableHIPRI");
Log.d(TAG, "startUsingNetworkFeature for enableHIPRI result: " + startUsingNetworkFeature);
if (-1 == startUsingNetworkFeature) {
Log.e(TAG, "Wrong result of startUsingNetworkFeature, maybe problems");
}
if (connectivityManager.getNetworkInfo(5).getState().compareTo(NetworkInfo.State.CONNECTED) == 0) {
Log.d(TAG, "Mobile network is connected");
} else {
Log.d(TAG, "Mobile network is not connected");
}
}
requestRouteToHost();
} catch (Exception e) {
Log.e(TAG, "Hit error in KeepMobileAliveTask ", e);
}
}
/**
* 等待 : TYPE_MOBILE_HIPRI類型的網(wǎng)絡(luò)建立連接后
* <p/>
* deliver traffic to the specified host via the specified network interface
*/
private void requestRouteToHost() {
String ip = AuthDataManager.getInstance().getAuthData().getIp();
int i = AppUtil.convertIpToInt(ip);
ConnectivityManager connectivityManager = (ConnectivityManager) mContext.getSystemService(CONNECTIVITY_SERVICE);
if (connectivityManager == null) {
DLog.i(TAG + "ConnectivityManager is null, cannot try to force a mobile connection");
} else if (connectivityManager.getNetworkInfo(5) == null) {
DLog.i(TAG + "Mobile Interface Not Found.");
} else {
int i2 = 0;
while (i2 < 20) {
try {
if (connectivityManager.getNetworkInfo(5).getState().compareTo(NetworkInfo.State.CONNECTED) == 0) {
break;
}
Thread.sleep(1000);
i2++;
} catch (InterruptedException ignored) {
}
}
DLog.i(TAG + "requestRouteToHost result: " + connectivityManager.requestRouteToHost(5, i));
}
}
}
API >= 6.0
- 通過Android標(biāo)準(zhǔn)API在WiFi連接的情況下财搁,請求4G網(wǎng)絡(luò)通道,
- 當(dāng)4G網(wǎng)絡(luò)通道成功后躬络,Android會回調(diào)一個networkId 尖奔,
- 通過NDK將此networkId與VPN的上網(wǎng)了進(jìn)程綁定,從而實(shí)現(xiàn)走VPN的數(shù)據(jù)流量都通過4G 網(wǎng)絡(luò)
public void requestWorkNetForHigh(Context context) {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (cm == null) {
DLog.i("ConnectivityManager is null, cannot try to force a mobile connection");
return;
}
DLog.i("post50MobileEnable, requesting Cellular network");
NetworkRequest.Builder builder = new NetworkRequest.Builder();
builder.addTransportType(0);
builder.addCapability(12);
NetworkRequest build = builder.build();
unregisterNetworkCallback();
try {
if (mNetWorkCallBack == null) {
mNetWorkCallBack = new MNetWorkCallBack();
}
DLog.i("Requesting Connectivity Manager");
cm.requestNetwork(build, mNetWorkCallBack);
} catch (SecurityException e) {
DLog.i("com.speedify.speedifyAndroid.MobileController Cannot write settings. Requesting Permission");
} catch (Exception e2) {
DLog.e("Unknown Exception", e2);
e2.printStackTrace();
}
}
private class MNetWorkCallBack extends ConnectivityManager.NetworkCallback {
@Override
public void onAvailable(Network network) {
DLog.i(TAG + "NetWorkCallBack " + network);
super.onAvailable(network);
}
}
POC當(dāng)時(shí)的技術(shù)結(jié)論:
--未完待補(bǔ)充