Merge remote-tracking branch 'refs/remotes/origin/master'
This commit is contained in:
commit
0c395b1664
|
|
@ -164,6 +164,7 @@
|
|||
android:name=".fragment.recharge.BackupRechargeActivity"
|
||||
android:process=":background"
|
||||
android:screenOrientation="portrait" />
|
||||
<service android:name=".service.ConnectionService"/>
|
||||
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
|
|
|
|||
|
|
@ -12,8 +12,11 @@ import com.yingmao.clash.listener.AsyncCallBackListener
|
|||
import com.yingmao.clash.net.http.HttpApi
|
||||
import com.yingmao.clash.net.http.HttpReqType
|
||||
import com.yingmao.clash.net.http.NetService
|
||||
import okhttp3.MediaType.Companion.toMediaType
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import org.yaml.snakeyaml.Yaml
|
||||
import java.math.BigDecimal
|
||||
|
||||
|
|
@ -138,4 +141,61 @@ class AccelerateViewModel : PublicViewMode() {
|
|||
}
|
||||
}
|
||||
|
||||
fun appStartupStatus() {
|
||||
val httpApi = NetService.instances.createHttpsEncodeStr(HttpApi::class.java)
|
||||
val token = MMKV.defaultMMKV().decodeString(BZYConstants.MMKV_KEY_PH_TOKEN, "")!!
|
||||
val phoneNumber =
|
||||
MMKV.defaultMMKV().decodeString(BZYConstants.MMKV_KEY_REMEMBER_USERNAME, "")!!
|
||||
val params = mutableMapOf(
|
||||
"phToken" to token,
|
||||
"phoneNumber" to phoneNumber,
|
||||
)
|
||||
Log.d("appCheck==>$params")
|
||||
doAsync(HttpReqType.AppStartupStatus) {
|
||||
httpApi.appStartupStatus(params)
|
||||
}
|
||||
}
|
||||
|
||||
fun appStopStatus(addId:Int) {
|
||||
val httpApi = NetService.instances.createHttpsEncodeStr(HttpApi::class.java)
|
||||
val token = MMKV.defaultMMKV().decodeString(BZYConstants.MMKV_KEY_PH_TOKEN, "")!!
|
||||
val phoneNumber =
|
||||
MMKV.defaultMMKV().decodeString(BZYConstants.MMKV_KEY_REMEMBER_USERNAME, "")!!
|
||||
val paramsToken = mutableMapOf(
|
||||
"phToken" to token,
|
||||
"phoneNumber" to phoneNumber,
|
||||
)
|
||||
|
||||
val params = hashMapOf(
|
||||
"id" to addId
|
||||
)
|
||||
val gson = Gson()
|
||||
val jsonString = gson.toJson(params)
|
||||
val requestBody: RequestBody = jsonString.toRequestBody("application/json; charset=utf-8".toMediaType())
|
||||
doAsync(HttpReqType.AppStopStatus) {
|
||||
httpApi.appStopStatus(paramsToken,requestBody)
|
||||
}
|
||||
}
|
||||
|
||||
fun appUpStatus(addId:Int) {
|
||||
val httpApi = NetService.instances.createHttpsEncodeStr(HttpApi::class.java)
|
||||
val token = MMKV.defaultMMKV().decodeString(BZYConstants.MMKV_KEY_PH_TOKEN, "")!!
|
||||
val phoneNumber =
|
||||
MMKV.defaultMMKV().decodeString(BZYConstants.MMKV_KEY_REMEMBER_USERNAME, "")!!
|
||||
val paramsToken = mutableMapOf(
|
||||
"phToken" to token,
|
||||
"phoneNumber" to phoneNumber,
|
||||
)
|
||||
|
||||
val params = hashMapOf(
|
||||
"id" to addId
|
||||
)
|
||||
val gson = Gson()
|
||||
val jsonString = gson.toJson(params)
|
||||
val requestBody: RequestBody = jsonString.toRequestBody("application/json; charset=utf-8".toMediaType())
|
||||
doAsync(HttpReqType.AppUpStatus) {
|
||||
httpApi.appUpStatus(paramsToken,requestBody)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ import android.content.Intent
|
|||
import android.content.IntentFilter
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.ResultReceiver
|
||||
import android.text.TextUtils
|
||||
import android.view.View
|
||||
import android.widget.Button
|
||||
|
|
@ -20,6 +21,10 @@ import androidx.activity.result.contract.ActivityResultContracts
|
|||
import androidx.appcompat.app.AppCompatActivity.RESULT_OK
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.cncat.vpn.common.constants.Intents
|
||||
import com.cncat.vpn.common.log.Log
|
||||
import com.cncat.vpn.core.Clash
|
||||
import com.cncat.vpn.core.model.TunnelState
|
||||
import com.orhanobut.logger.Logger
|
||||
import com.tencent.mmkv.MMKV
|
||||
import com.yingmao.clash.R
|
||||
|
|
@ -28,14 +33,14 @@ import com.yingmao.clash.act.NewMainActivity
|
|||
import com.yingmao.clash.act.NewMainActivity.Companion.isSubed
|
||||
import com.yingmao.clash.act.NewMainActivity.Companion.newUuid
|
||||
import com.yingmao.clash.act.ProxyModeActivity
|
||||
import com.cncat.vpn.common.constants.Intents
|
||||
import com.cncat.vpn.common.log.Log
|
||||
import com.yingmao.clash.conf.BZYConstants
|
||||
import com.yingmao.clash.conf.Conf
|
||||
import com.cncat.vpn.core.Clash
|
||||
import com.cncat.vpn.core.model.TunnelState
|
||||
import com.yingmao.clash.entity.ClashNodebBean
|
||||
import com.yingmao.clash.listener.AsyncCallBackListener
|
||||
import com.yingmao.clash.net.http.HttpReqType
|
||||
import com.yingmao.clash.net.http.HttpStatus
|
||||
import com.yingmao.clash.net.http.entity.AppStartupStatus
|
||||
import com.yingmao.clash.service.ConnectionService
|
||||
import com.yingmao.clash.util.ActivityResultLifecycle
|
||||
import com.yingmao.clash.util.CommonUtils
|
||||
import com.yingmao.clash.util.startClashService
|
||||
|
|
@ -87,6 +92,7 @@ class NewAccFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatch
|
|||
|
||||
// var currentNode: Profile? = null
|
||||
private var reConnection = false
|
||||
private var connectId=-1
|
||||
|
||||
override fun init(
|
||||
titleBarRl: RelativeLayout,
|
||||
|
|
@ -112,7 +118,7 @@ class NewAccFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatch
|
|||
super.onActivityCreated(savedInstanceState)
|
||||
Logger.d("onActivityCreated")
|
||||
accelerateViewModel = ViewModelProvider(this).get(AccelerateViewModel::class.java)
|
||||
|
||||
observe(this, accelerateViewModel)
|
||||
initSS()
|
||||
// initSub()
|
||||
getNodesStatus()
|
||||
|
|
@ -245,6 +251,11 @@ class NewAccFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatch
|
|||
stopClash()
|
||||
rxDialogSureCancel.cancel()
|
||||
reConnection = false
|
||||
Log.d("NewAccFragment connectId:::${connectId}")
|
||||
if(connectId!=-1){
|
||||
accelerateViewModel.appStopStatus(connectId)
|
||||
}
|
||||
|
||||
}
|
||||
rxDialogSureCancel.show()
|
||||
|
||||
|
|
@ -311,21 +322,20 @@ class NewAccFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatch
|
|||
}
|
||||
|
||||
val vpnRequest = context?.startClashService()
|
||||
|
||||
try {
|
||||
start_u_timer()
|
||||
if (vpnRequest != null) {
|
||||
val result = startActivityForResult(
|
||||
ActivityResultContracts.StartActivityForResult(), vpnRequest
|
||||
)
|
||||
|
||||
if (result.resultCode == RESULT_OK) {
|
||||
stateChanged(Clash_Starting, true)
|
||||
context?.startClashService()
|
||||
|
||||
|
||||
accelerateViewModel.appStartupStatus()
|
||||
// clashRunning = true
|
||||
}
|
||||
}else{
|
||||
accelerateViewModel.appStartupStatus()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
stop_u_timer()
|
||||
|
|
@ -433,6 +443,7 @@ class NewAccFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatch
|
|||
}
|
||||
}
|
||||
// File("${Core.deviceStorage.noBackupFilesDir}/${BaseService.CONFIG_FILE}").delete()
|
||||
accelerateViewModel.appStartupStatus()
|
||||
}
|
||||
|
||||
Clash_Stop -> {
|
||||
|
|
@ -828,4 +839,54 @@ class NewAccFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatch
|
|||
}
|
||||
}
|
||||
}
|
||||
private val resultReceiver: ResultReceiver = object : ResultReceiver(null) {
|
||||
override fun onReceiveResult(resultCode: Int, resultData: Bundle) {
|
||||
val data = resultData.getString("data")
|
||||
Log.d("ping to from Service: $data")
|
||||
if(connectId!=-1){
|
||||
Log.d("activity connectId: $connectId")
|
||||
accelerateViewModel.appUpStatus(connectId)
|
||||
}
|
||||
}
|
||||
}
|
||||
override fun httpLoading(httpStatus: HttpStatus.Loading) {
|
||||
|
||||
}
|
||||
override fun httpSuccess(httpStatus: HttpStatus.Success) {
|
||||
when(httpStatus.reqType){
|
||||
HttpReqType.AppStartupStatus ->{
|
||||
Log.d("AppStartupStatus is Success ${httpStatus.rsp}")
|
||||
val dataInfo = httpStatus.rsp as AppStartupStatus
|
||||
if(dataInfo.data!=null){
|
||||
if(dataInfo.data.id!=null){
|
||||
connectId= dataInfo.data.id
|
||||
val serviceIntent= Intent(requireContext(), ConnectionService::class.java)
|
||||
serviceIntent.putExtra("receiver",resultReceiver)
|
||||
requireContext().startService(serviceIntent)
|
||||
}
|
||||
}
|
||||
}
|
||||
HttpReqType.AppStopStatus ->{
|
||||
Log.d("AppStopStatus is Success ${httpStatus.rsp}")
|
||||
val serviceIntent= Intent(requireContext(), ConnectionService::class.java)
|
||||
requireContext().stopService(serviceIntent)
|
||||
}
|
||||
else->{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
override fun httpFailure(httpStatus: HttpStatus.Failure) {
|
||||
when(httpStatus.reqType){
|
||||
HttpReqType.AppStartupStatus ->{
|
||||
Log.d("AppStartupStatus is Failure ${httpStatus.msg}")
|
||||
}
|
||||
HttpReqType.AppStopStatus ->{
|
||||
Log.d("AppStopStatus is Failure ${httpStatus.msg}")
|
||||
}
|
||||
else->{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -22,6 +22,8 @@ import com.yingmao.clash.net.http.entity.WXPayRsp
|
|||
import com.tencent.mmkv.MMKV
|
||||
import com.yingmao.clash.conf.BZYConstants
|
||||
import com.yingmao.clash.entity.PayUploadParamData
|
||||
import com.yingmao.clash.net.http.entity.AppStartupStatus
|
||||
import com.yingmao.clash.net.http.entity.AppStopStatus
|
||||
import com.yingmao.clash.net.http.entity.AppVersionCheckRsp
|
||||
import com.yingmao.clash.net.http.entity.GetActivityRsp
|
||||
import com.yingmao.clash.net.http.entity.LoginRsp2
|
||||
|
|
@ -523,4 +525,39 @@ interface HttpApi {
|
|||
BZYConstants.MMKV_KEY_TOKEN
|
||||
).toString()
|
||||
): PayUploadParamData
|
||||
|
||||
@Headers(
|
||||
"User-Agent: Octopus_Android"
|
||||
)
|
||||
@POST("netbarcloud/open/connection/add")
|
||||
suspend fun appStartupStatus(
|
||||
@QueryMap params: Map<String, String>,
|
||||
@Header("token") string: String = MMKV.defaultMMKV().decodeString(
|
||||
BZYConstants.MMKV_KEY_TOKEN
|
||||
).toString()
|
||||
): AppStartupStatus
|
||||
|
||||
@Headers(
|
||||
"User-Agent: Octopus_Android"
|
||||
)
|
||||
@POST("netbarcloud/open/connection/close")
|
||||
suspend fun appStopStatus(
|
||||
@QueryMap params: Map<String, String>,
|
||||
@Body requestBody: RequestBody,
|
||||
@Header("token") string: String = MMKV.defaultMMKV().decodeString(
|
||||
BZYConstants.MMKV_KEY_TOKEN
|
||||
).toString()
|
||||
): AppStopStatus
|
||||
|
||||
@Headers(
|
||||
"User-Agent: Octopus_Android"
|
||||
)
|
||||
@POST("netbarcloud/open/connection/update")
|
||||
suspend fun appUpStatus(
|
||||
@QueryMap params: Map<String, String>,
|
||||
@Body requestBody: RequestBody,
|
||||
@Header("token") string: String = MMKV.defaultMMKV().decodeString(
|
||||
BZYConstants.MMKV_KEY_TOKEN
|
||||
).toString()
|
||||
): AppStopStatus
|
||||
}
|
||||
|
|
@ -48,5 +48,8 @@ enum class HttpReqType(type: Int) {
|
|||
GetRuningNotice(44),
|
||||
unionPay(45),
|
||||
UploadParameters(46),
|
||||
StripeType(47)
|
||||
StripeType(47),
|
||||
AppStartupStatus(48),
|
||||
AppUpStatus(49),
|
||||
AppStopStatus(50),
|
||||
}
|
||||
|
|
@ -87,10 +87,10 @@ class NetService private constructor() : INetService {
|
|||
// .sslSocketFactory(getSSLSocketFactory(), CustomTrustManager())//信任所有证书
|
||||
.sslSocketFactory(getSSLSocketFactory(), trustAllCerts[0] as X509TrustManager)
|
||||
.hostnameVerifier(getHostnameVerifier()!!)
|
||||
// if (BuildConfig.DEBUG) {
|
||||
// builder.addInterceptor(loggingInterceptor)
|
||||
// }
|
||||
if (BuildConfig.DEBUG) {
|
||||
builder.addInterceptor(loggingInterceptor)
|
||||
}
|
||||
// builder.addInterceptor(loggingInterceptor)
|
||||
return builder.build()
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -210,5 +210,29 @@ data class VipSignRspData(
|
|||
@field:SerializedName("signGiftmins")
|
||||
val signGiftmins: Int? = null
|
||||
)
|
||||
data class AppStartupStatus(
|
||||
@field:SerializedName("code")
|
||||
val code: String? = null,
|
||||
|
||||
@field:SerializedName("data")
|
||||
val data: ConnectId? = null,
|
||||
|
||||
@field:SerializedName("message")
|
||||
val message: String? = null
|
||||
) : BaseRsp
|
||||
|
||||
data class ConnectId(
|
||||
@field:SerializedName("id")
|
||||
val id: Int? = -1,
|
||||
)
|
||||
|
||||
data class AppStopStatus(
|
||||
@field:SerializedName("code")
|
||||
val code: String? = null,
|
||||
|
||||
@field:SerializedName("data")
|
||||
val data: ConnectId? = null,
|
||||
|
||||
@field:SerializedName("message")
|
||||
val message: String? = null
|
||||
) : BaseRsp
|
||||
|
|
|
|||
|
|
@ -0,0 +1,61 @@
|
|||
package com.yingmao.clash.service;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.ResultReceiver;
|
||||
import android.util.Log;
|
||||
|
||||
import com.yingmao.clash.fragment.AccelerateViewModel;
|
||||
|
||||
public class ConnectionService extends Service {
|
||||
|
||||
private static final String TAG = "TimerService";
|
||||
private static final long INTERVAL_MILLIS = 10000; // 10 秒
|
||||
private Handler handler = new Handler();
|
||||
private Intent intent;
|
||||
private Runnable runnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if(intent!=null){
|
||||
ResultReceiver receiver = intent.getParcelableExtra("receiver");
|
||||
if (receiver != null) {
|
||||
Bundle resultData = new Bundle();
|
||||
resultData.putString("ping", "ping to Service!");
|
||||
receiver.send(1, resultData); // 1 是结果码
|
||||
}
|
||||
}
|
||||
|
||||
handler.postDelayed(this, INTERVAL_MILLIS);
|
||||
}
|
||||
};
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
Log.d(TAG, "Service onCreate");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
Log.d(TAG, "Service onStartCommand");
|
||||
this.intent=intent;
|
||||
handler.post(runnable); // 启动定时器
|
||||
return START_STICKY; // 服务被杀死后会自动重启
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
handler.removeCallbacks(runnable); // 停止定时器
|
||||
Log.d(TAG, "Service onDestroy");
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
Log.d(TAG, "Service onBind");
|
||||
return null; // 如果不支持绑定服务,返回 null
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,193 @@
|
|||
package com.yingmao.clash.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.Network;
|
||||
import android.net.NetworkCapabilities;
|
||||
import android.net.wifi.WifiInfo;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.util.Log;
|
||||
|
||||
import java.net.Inet4Address;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.SocketException;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
|
||||
public class IPAddrUtils {
|
||||
|
||||
/**
|
||||
* 获取本机IPv4地址
|
||||
*
|
||||
* @param context
|
||||
* @return 本机IPv4地址;null:无网络连接
|
||||
*/
|
||||
public static String getIpAddress(Context context) {
|
||||
if (null == context)
|
||||
return getIpAddress();
|
||||
|
||||
// 获取WiFi服务
|
||||
WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
|
||||
// 判断WiFi是否开启
|
||||
if (wifiManager.isWifiEnabled()) {
|
||||
// 已经开启了WiFi
|
||||
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
|
||||
int ipAddress = wifiInfo.getIpAddress();
|
||||
String ip = intToIp(ipAddress);
|
||||
return ip;
|
||||
} else {
|
||||
// 未开启WiFi
|
||||
return getIpAddress();
|
||||
}
|
||||
}
|
||||
|
||||
private static String intToIp(int ipAddress) {
|
||||
return (ipAddress & 0xFF) + "." +
|
||||
((ipAddress >> 8) & 0xFF) + "." +
|
||||
((ipAddress >> 16) & 0xFF) + "." +
|
||||
(ipAddress >> 24 & 0xFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取本机IPv4地址
|
||||
*
|
||||
* @return 本机IPv4地址;null:无网络连接
|
||||
*/
|
||||
public static String getIpAddress() {
|
||||
try {
|
||||
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
|
||||
NetworkInterface intf = en.nextElement();
|
||||
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
|
||||
InetAddress inetAddress = enumIpAddr.nextElement();
|
||||
if (!inetAddress.isLoopbackAddress()
|
||||
&& !inetAddress.isAnyLocalAddress()
|
||||
&& inetAddress instanceof Inet4Address) {
|
||||
return inetAddress.getHostAddress();
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String getIPv6Address() {
|
||||
try {
|
||||
// 获取所有网络接口
|
||||
Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
|
||||
for (NetworkInterface networkInterface : Collections.list(networkInterfaces)) {
|
||||
// 过滤掉回环接口和未启用的接口
|
||||
if (networkInterface.isLoopback() || !networkInterface.isUp()) {
|
||||
continue;
|
||||
}
|
||||
// 获取网络接口的 IP 地址
|
||||
Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses();
|
||||
Log.e("AAAAA","inetAddresses::"+inetAddresses.toString());
|
||||
for (InetAddress inetAddress : Collections.list(inetAddresses)) {
|
||||
// 检查是否是 IPv6 地址
|
||||
boolean bc = inetAddress instanceof Inet6Address;
|
||||
boolean linkLocalAddress = inetAddress.isLinkLocalAddress();
|
||||
Log.e("AAAAAqqqq","bc::"+bc);
|
||||
Log.e("AAAAAqqqq","linkLocalAddress::"+linkLocalAddress);
|
||||
if (inetAddress instanceof Inet6Address && !inetAddress.isLinkLocalAddress()) {
|
||||
return inetAddress.getHostAddress();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
} catch (SocketException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public static String getIPv6AddressAAA(Context context) {
|
||||
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
if (connectivityManager == null) {
|
||||
return null;
|
||||
}
|
||||
Network activeNetwork = null;
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
|
||||
activeNetwork = connectivityManager.getActiveNetwork();
|
||||
}
|
||||
if (activeNetwork != null) {
|
||||
NetworkCapabilities networkCapabilities = connectivityManager.getNetworkCapabilities(activeNetwork);
|
||||
if (networkCapabilities != null && networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
|
||||
// 当前网络是 Wi-Fi
|
||||
return getIPv6Address();
|
||||
} else if (networkCapabilities != null && networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
|
||||
// 当前网络是移动数据
|
||||
return getIPv6Address();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* 获取设备的 IPv4 地址
|
||||
*
|
||||
* @return IPv4 地址,如果未找到则返回 null
|
||||
*/
|
||||
public static String getIPv4Address() {
|
||||
try {
|
||||
// 获取所有网络接口
|
||||
Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
|
||||
for (NetworkInterface networkInterface : Collections.list(networkInterfaces)) {
|
||||
// 过滤掉回环接口和未启用的接口
|
||||
if (networkInterface.isLoopback() || !networkInterface.isUp()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 获取网络接口的 IP 地址
|
||||
Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses();
|
||||
for (InetAddress inetAddress : Collections.list(inetAddresses)) {
|
||||
// 检查是否是 IPv4 地址
|
||||
if (inetAddress instanceof Inet4Address) {
|
||||
return inetAddress.getHostAddress();
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (SocketException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* 获取当前活动网络的 IPv4 地址
|
||||
*
|
||||
* @param context 上下文
|
||||
* @return IPv4 地址,如果未找到则返回 null
|
||||
*/
|
||||
public static String getCurrentIPv4Address(Context context) {
|
||||
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
if (connectivityManager == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 获取当前活动网络
|
||||
Network activeNetwork = null;
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
|
||||
activeNetwork = connectivityManager.getActiveNetwork();
|
||||
}
|
||||
if (activeNetwork == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 获取网络能力
|
||||
NetworkCapabilities networkCapabilities = connectivityManager.getNetworkCapabilities(activeNetwork);
|
||||
if (networkCapabilities == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 检查网络类型(Wi-Fi 或移动数据)
|
||||
if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
|
||||
Log.d("NetworkHelper", "Current network is Wi-Fi");
|
||||
} else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
|
||||
Log.d("NetworkHelper", "Current network is Cellular");
|
||||
}
|
||||
|
||||
// 获取 IPv4 地址
|
||||
return getIPv4Address();
|
||||
}
|
||||
}
|
||||
|
|
@ -673,6 +673,27 @@ subprojects {
|
|||
)
|
||||
)
|
||||
}
|
||||
|
||||
create("3027") {
|
||||
isDefault = true
|
||||
dimension = flavorDimensionList[0]
|
||||
buildConfigField("boolean", "PREMIUM", "Boolean.parseBoolean(\"false\")")
|
||||
if (isApp) {
|
||||
// applicationIdSuffix = ".meta"
|
||||
}
|
||||
buildConfigField("boolean", "is_back_cn", "false")
|
||||
buildConfigField("boolean", "is_ym", "true")
|
||||
buildConfigField("boolean", "is_free", "false")
|
||||
buildConfigField("boolean", "is_tz", "false")
|
||||
buildConfigField("String", "applicationId", "\"com.yingmao.clash\"")
|
||||
buildConfigField("String", "service_url", "\"https://api.ymvpnpro.cc:8700\"")
|
||||
buildConfigField("String", "productId", "\"3027\"")
|
||||
manifestPlaceholders(
|
||||
mapOf(
|
||||
"APP_NAME" to "@string/app_name_gz", "APP_ICON" to "@mipmap/ic_logo_9972"
|
||||
)
|
||||
)
|
||||
}
|
||||
create("7595") {
|
||||
isDefault = true
|
||||
dimension = flavorDimensionList[0]
|
||||
|
|
|
|||
Loading…
Reference in New Issue