一键连

1.订阅链接出错时提示用户进行 源切换
This commit is contained in:
level 2025-12-11 16:24:16 +08:00
parent 97efcdcff7
commit 81b7fcdb49
11 changed files with 72 additions and 21 deletions

View File

@ -44,9 +44,9 @@ import com.yingmao.clash.conf.BZYConstants
import com.yingmao.clash.conf.Conf
import com.yingmao.clash.entity.CheckLoginRsp
import com.yingmao.clash.entity.NodeGroupItem
import com.yingmao.clash.fragment.vip.vipFragment
import com.yingmao.clash.fragment.home.HomeFragment
import com.yingmao.clash.fragment.setting.SettingFragment
import com.yingmao.clash.fragment.vip.vipFragment
import com.yingmao.clash.net.http.HttpApi
import com.yingmao.clash.net.http.HttpReqType
import com.yingmao.clash.net.http.HttpStatus
@ -110,8 +110,6 @@ class MainActivity : BaseActivity() {
private var checkBindAccountDia: MaterialDialog? = null
private val mPageInfo = ExpensesRecordActivity.PageInfo()
private var MainActCurrentNode: MutableList<NodeGroupItem> = mutableListOf()
companion object {
var isVip:Boolean=false
//记录心跳失败次数
@ -129,7 +127,7 @@ class MainActivity : BaseActivity() {
var clashBinder: IClashManager? = null
private var mainBroadcastReceiver: BroadcastReceiver? = null
val trafficStatisticsData = MutableLiveData<String>()
var subLinkCode: Int=200
suspend fun setSub2(url: String) {
profileBinder?.let { pm ->
pm.queryAll().forEach { itemPro ->
@ -200,6 +198,7 @@ class MainActivity : BaseActivity() {
mainAtyVM.startHeartBeat()
mainAtyVM.getAirNodes()
val intentFilter = IntentFilter(Intents.ACTION_NODE_LIST)
intentFilter.addAction(Intents.ACTION_SUB_HTTP_STATUS)
mainBroadcastReceiver = NodeListBR()
if (Build.VERSION.SDK_INT >= 34 && applicationInfo.targetSdkVersion >= 34) {
registerReceiver(
@ -228,6 +227,15 @@ class MainActivity : BaseActivity() {
val userTraffic=serStore.userTraffic
userTrafficMethod(userTraffic)
}
Intents.ACTION_SUB_HTTP_STATUS->{
val codeMsg= intent.getIntExtra("code",200)
val exceptionStr = intent.getSerializableExtra("exception")
Log.i("ACTION_SUB_HTTP_STATUS codeMsg::${codeMsg} exceptionStr::${exceptionStr}")
subLinkCode=codeMsg
if(codeMsg!=200){
RxToast.info(resources.getString(R.string.SubscriptionlinkTop))
}
}
else -> {
}
@ -782,22 +790,5 @@ class MainActivity : BaseActivity() {
aivHome.setImageResource(R.drawable.yjl_home_page)
aivCenter.setImageResource(R.drawable.yjl_user_page)
aivVip.setImageResource(R.drawable.yjl_vip_page_choose)
// startActivityForResult(
// Intent(this@MainActivity, MemberRechargeActivity::class.java),
// REQUEST_CODE_PAY_WEB_VIEW_ACTIVITY
// )
}
private fun getNodesInfo(json: String): MutableList<NodeGroupItem> {
val mList: MutableList<NodeGroupItem> = mutableListOf()
if (TextUtils.isEmpty(json)) {
return mList
}
val gson = Gson()
val jsonArray = JsonParser.parseString(json).asJsonArray
for (i in 0 until jsonArray.size()) {
val bean = gson.fromJson(jsonArray.get(i).asString, NodeGroupItem::class.java)
mList.add(bean)
}
return mList
}
}

View File

@ -91,6 +91,7 @@ class NodeGroupActivity : BaseActivity(){
cacheNodeStr = MMKV.defaultMMKV().decodeString(BZYConstants.NODE_All_ITEM_NAME_KEY, "")
val intentFilter = IntentFilter(Intents.ACTION_NODE_LIST)
intentFilter.addAction(Intents.ACTION_SUB_HTTP_STATUS)
broadcastReceiver = NodeListBR()
if (Build.VERSION.SDK_INT >= 34 && applicationInfo.targetSdkVersion >= 34) {
registerReceiver(
@ -214,6 +215,16 @@ class NodeGroupActivity : BaseActivity(){
setNewData(currentNode)
swipeLayout.isRefreshing = false
}
Intents.ACTION_SUB_HTTP_STATUS->{
val codeMsg= intent.getIntExtra("code",200)
val exceptionStr = intent.getSerializableExtra("exception")
Log.i("NODEPage ACTION_SUB_HTTP_STATUS codeMsg::${codeMsg} exceptionStr::${exceptionStr}")
if(codeMsg!=200){
RxToast.info(resources.getString(R.string.SubscriptionlinkTop))
}
timerJob?.cancel()
hideLoading()
}
else -> {

View File

@ -48,6 +48,7 @@ import com.yingmao.clash.act.MainActivity.Companion.isSubbed
import com.yingmao.clash.act.MainActivity.Companion.newMainActGlo
import com.yingmao.clash.act.MainActivity.Companion.newUuid
import com.yingmao.clash.act.MainActivity.Companion.profileBinder
import com.yingmao.clash.act.MainActivity.Companion.subLinkCode
import com.yingmao.clash.act.MainActivity.Companion.subUrl
import com.yingmao.clash.act.NodeGroupActivity
import com.yingmao.clash.conf.BZYConstants
@ -229,6 +230,10 @@ open class HomeFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispa
clLinks= view.findViewById(R.id.clLinks)
clNode.setOnClickListener {
if(subLinkCode!=200){
RxToast.info(resources.getString(R.string.SubscriptionlinkTop))
return@setOnClickListener
}
if (checkExpire()) {
RxToast.info(resources.getString(R.string.AccountExpired))
return@setOnClickListener

View File

@ -20,6 +20,11 @@ import java.util.Collections
import java.util.UUID
import java.util.regex.Matcher
import java.util.regex.Pattern
import javax.crypto.Cipher
import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.SecretKeySpec
import kotlin.io.encoding.Base64
import kotlin.io.encoding.ExperimentalEncodingApi
import kotlin.random.Random
@ -295,4 +300,23 @@ object Utils {
val hardware = Build.HARDWARE
return "androidVersion:$androidVersion,sdkInt:$sdkInt,manufacturer:$manufacturer,model:$model,brand:$brand,device:$device,hardware:$hardware"
}
@OptIn(ExperimentalEncodingApi::class)
fun aesDecryptCBC_PKCS5(
base64CipherText: String,
key: String, //注册时候的密钥cb.getRegisterKey(si)
iv: String//注册时候的密钥
): String {
// Base64 解码
val cipherBytes = Base64.decode(base64CipherText)
val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
val keySpec = SecretKeySpec(key.toByteArray(Charsets.UTF_8), "AES")
val ivSpec = IvParameterSpec(iv.toByteArray(Charsets.UTF_8))
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec)
val decrypted = cipher.doFinal(cipherBytes)
return String(decrypted, Charsets.UTF_8)
}
}

Binary file not shown.

Binary file not shown.

View File

@ -425,4 +425,5 @@ In order to implement and strengthen awareness of personal information security
<string name="OpenSwitchingSourceModel">Please enable acceleration before switching to global mode</string>
<string name="GolbalModeNoChoose">Switching nodes is not currently supported in global acceleration mode. Please switch to smart mode!</string>
<string name="GetNodesAgined">Getting nodes, please click to speed up later</string>
<string name="SubscriptionlinkTop">Error retrieving node information, please manually click [Source Switch] or contact customer service for assistance!</string>
</resources>

View File

@ -417,4 +417,5 @@
<string name="OpenSwitchingSourceModel">請開啟加速後在進行全域模式切換</string>
<string name="GolbalModeNoChoose">全域模式加速下暫不支援切換節點,請切換至智慧模式!</string>
<string name="GetNodesAgined">取得節點中,請稍後點選加速</string>
<string name="SubscriptionlinkTop">取得節點資訊出錯,請手動點選 [源切換] 或聯絡客服處理!</string>
</resources>

View File

@ -415,4 +415,5 @@
<string name="OpenSwitchingSourceModel">請開啟加速後在進行全域模式切換</string>
<string name="GolbalModeNoChoose">全域模式加速下暫不支援切換節點,請切換至智慧模式!</string>
<string name="GetNodesAgined">取得節點中,請稍後點選加速</string>
<string name="SubscriptionlinkTop">取得節點資訊出錯,請手動點選 [源切換] 或聯絡客服處理!</string>
</resources>

View File

@ -482,4 +482,5 @@
<string name="OpenSwitchingSourceModel">请开启加速后在进行全局模式切换</string>
<string name="GolbalModeNoChoose">全局模式加速下暂不支持切换节点,请切换至智能模式!</string>
<string name="GetNodesAgined">获取节点中,请稍后点击加速</string>
<string name="SubscriptionlinkTop">获取节点信息出错,请手动点击 [源切换] 或联系客服处理!</string>
</resources>

View File

@ -109,6 +109,22 @@ subprojects {
)
)
}
create("1111") {
isDefault = true
dimension = flavorDimensionList[0]
buildConfigField("boolean", "PREMIUM", "Boolean.parseBoolean(\"false\")")
buildConfigField("boolean", "is_free", "false")
buildConfigField("boolean", "is_back_cn", "false")
buildConfigField("String", "applicationId", "\"com.jsq.wufu\"")
buildConfigField("String", "service_url", "\"https://api.yijianlianjsq.com/\"")
buildConfigField("String", "productId", "\"1111\"")
manifestPlaceholders(
mapOf(
"APP_NAME" to "@string/wf",
"APP_ICON" to "@mipmap/oneclickconnection"
)
)
}
}
sourceSets {
getByName("2211") {