一键连

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.conf.Conf
import com.yingmao.clash.entity.CheckLoginRsp import com.yingmao.clash.entity.CheckLoginRsp
import com.yingmao.clash.entity.NodeGroupItem 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.home.HomeFragment
import com.yingmao.clash.fragment.setting.SettingFragment 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.HttpApi
import com.yingmao.clash.net.http.HttpReqType import com.yingmao.clash.net.http.HttpReqType
import com.yingmao.clash.net.http.HttpStatus import com.yingmao.clash.net.http.HttpStatus
@ -110,8 +110,6 @@ class MainActivity : BaseActivity() {
private var checkBindAccountDia: MaterialDialog? = null private var checkBindAccountDia: MaterialDialog? = null
private val mPageInfo = ExpensesRecordActivity.PageInfo() private val mPageInfo = ExpensesRecordActivity.PageInfo()
private var MainActCurrentNode: MutableList<NodeGroupItem> = mutableListOf()
companion object { companion object {
var isVip:Boolean=false var isVip:Boolean=false
//记录心跳失败次数 //记录心跳失败次数
@ -129,7 +127,7 @@ class MainActivity : BaseActivity() {
var clashBinder: IClashManager? = null var clashBinder: IClashManager? = null
private var mainBroadcastReceiver: BroadcastReceiver? = null private var mainBroadcastReceiver: BroadcastReceiver? = null
val trafficStatisticsData = MutableLiveData<String>() val trafficStatisticsData = MutableLiveData<String>()
var subLinkCode: Int=200
suspend fun setSub2(url: String) { suspend fun setSub2(url: String) {
profileBinder?.let { pm -> profileBinder?.let { pm ->
pm.queryAll().forEach { itemPro -> pm.queryAll().forEach { itemPro ->
@ -200,6 +198,7 @@ class MainActivity : BaseActivity() {
mainAtyVM.startHeartBeat() mainAtyVM.startHeartBeat()
mainAtyVM.getAirNodes() mainAtyVM.getAirNodes()
val intentFilter = IntentFilter(Intents.ACTION_NODE_LIST) val intentFilter = IntentFilter(Intents.ACTION_NODE_LIST)
intentFilter.addAction(Intents.ACTION_SUB_HTTP_STATUS)
mainBroadcastReceiver = NodeListBR() mainBroadcastReceiver = NodeListBR()
if (Build.VERSION.SDK_INT >= 34 && applicationInfo.targetSdkVersion >= 34) { if (Build.VERSION.SDK_INT >= 34 && applicationInfo.targetSdkVersion >= 34) {
registerReceiver( registerReceiver(
@ -228,6 +227,15 @@ class MainActivity : BaseActivity() {
val userTraffic=serStore.userTraffic val userTraffic=serStore.userTraffic
userTrafficMethod(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 -> { else -> {
} }
@ -782,22 +790,5 @@ class MainActivity : BaseActivity() {
aivHome.setImageResource(R.drawable.yjl_home_page) aivHome.setImageResource(R.drawable.yjl_home_page)
aivCenter.setImageResource(R.drawable.yjl_user_page) aivCenter.setImageResource(R.drawable.yjl_user_page)
aivVip.setImageResource(R.drawable.yjl_vip_page_choose) 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, "") cacheNodeStr = MMKV.defaultMMKV().decodeString(BZYConstants.NODE_All_ITEM_NAME_KEY, "")
val intentFilter = IntentFilter(Intents.ACTION_NODE_LIST) val intentFilter = IntentFilter(Intents.ACTION_NODE_LIST)
intentFilter.addAction(Intents.ACTION_SUB_HTTP_STATUS)
broadcastReceiver = NodeListBR() broadcastReceiver = NodeListBR()
if (Build.VERSION.SDK_INT >= 34 && applicationInfo.targetSdkVersion >= 34) { if (Build.VERSION.SDK_INT >= 34 && applicationInfo.targetSdkVersion >= 34) {
registerReceiver( registerReceiver(
@ -214,6 +215,16 @@ class NodeGroupActivity : BaseActivity(){
setNewData(currentNode) setNewData(currentNode)
swipeLayout.isRefreshing = false 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 -> { 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.newMainActGlo
import com.yingmao.clash.act.MainActivity.Companion.newUuid import com.yingmao.clash.act.MainActivity.Companion.newUuid
import com.yingmao.clash.act.MainActivity.Companion.profileBinder 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.MainActivity.Companion.subUrl
import com.yingmao.clash.act.NodeGroupActivity import com.yingmao.clash.act.NodeGroupActivity
import com.yingmao.clash.conf.BZYConstants import com.yingmao.clash.conf.BZYConstants
@ -229,6 +230,10 @@ open class HomeFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispa
clLinks= view.findViewById(R.id.clLinks) clLinks= view.findViewById(R.id.clLinks)
clNode.setOnClickListener { clNode.setOnClickListener {
if(subLinkCode!=200){
RxToast.info(resources.getString(R.string.SubscriptionlinkTop))
return@setOnClickListener
}
if (checkExpire()) { if (checkExpire()) {
RxToast.info(resources.getString(R.string.AccountExpired)) RxToast.info(resources.getString(R.string.AccountExpired))
return@setOnClickListener return@setOnClickListener

View File

@ -20,6 +20,11 @@ import java.util.Collections
import java.util.UUID import java.util.UUID
import java.util.regex.Matcher import java.util.regex.Matcher
import java.util.regex.Pattern 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 import kotlin.random.Random
@ -295,4 +300,23 @@ object Utils {
val hardware = Build.HARDWARE val hardware = Build.HARDWARE
return "androidVersion:$androidVersion,sdkInt:$sdkInt,manufacturer:$manufacturer,model:$model,brand:$brand,device:$device,hardware:$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="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="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="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> </resources>

View File

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

View File

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

View File

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