From 39e847335c16d47884244ee99f10acf4e0b9dc1a Mon Sep 17 00:00:00 2001 From: 11111 <1364007522@qq.com> Date: Tue, 30 Dec 2025 20:35:41 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=80=E9=94=AE=E8=BF=9E=20=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E4=B8=8A=E4=BC=A0=E6=9B=B4=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yingmao/clash/act/MainActivity.kt | 23 +++-- .../clash/fragment/home/HomeFragment.kt | 30 ++++++- .../clash/fragment/setting/SettingFragment.kt | 72 +++++----------- .../java/com/yingmao/clash/levellog/AppLog.kt | 2 +- .../yingmao/clash/levellog/LogcatService.kt | 83 +------------------ .../main/java/com/yingmao/clash/util/Utils.kt | 4 + app/src/main/res/values/strings.xml | 4 +- 7 files changed, 74 insertions(+), 144 deletions(-) diff --git a/app/src/main/java/com/yingmao/clash/act/MainActivity.kt b/app/src/main/java/com/yingmao/clash/act/MainActivity.kt index 9800686..5045069 100644 --- a/app/src/main/java/com/yingmao/clash/act/MainActivity.kt +++ b/app/src/main/java/com/yingmao/clash/act/MainActivity.kt @@ -46,7 +46,6 @@ import com.yingmao.clash.base.BaseActivity 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.home.HomeFragment import com.yingmao.clash.fragment.setting.SettingFragment import com.yingmao.clash.fragment.vip.vipFragment @@ -130,6 +129,7 @@ class MainActivity : BaseActivity() { private var mainBroadcastReceiver: BroadcastReceiver? = null val trafficStatisticsData = MutableLiveData() suspend fun setSub2(url: String) { + try { profileBinder?.let { pm -> pm.queryAll().forEach { itemPro -> if (itemPro.name != Conf.getClashConfName(MainApplication.getApp()?.applicationContext)) { @@ -186,6 +186,9 @@ class MainActivity : BaseActivity() { } } } + }catch (e: Exception){ + AppLog.e("HomeFragment", "setSub2() Error===>",e) + } } } @@ -233,8 +236,6 @@ class MainActivity : BaseActivity() { requestPermissionLauncher.launch(android.Manifest.permission.POST_NOTIFICATIONS) } } - //初始进入 将日志采集开关变为不开启 - MMKV.defaultMMKV().encode(BZYConstants.BehaviorLogSwitch, false) } inner class NodeListBR : BroadcastReceiver() { @@ -285,7 +286,10 @@ class MainActivity : BaseActivity() { aivHome.setImageResource(R.drawable.yjl_home_page_choose) aivCenter.setImageResource(R.drawable.yjl_user_page) aivVip.setImageResource(R.drawable.yjl_vip_page) - checkVPN() + if(clashRunning){ + checkVPN() + } + } aivCenter.setOnClickListener { @@ -294,7 +298,9 @@ class MainActivity : BaseActivity() { aivHome.setImageResource(R.drawable.yjl_home_page) aivCenter.setImageResource(R.drawable.yjl_user_page_choose) aivVip.setImageResource(R.drawable.yjl_vip_page) - checkVPN() + if(clashRunning){ + checkVPN() + } } aivVip.setOnClickListener { @@ -338,6 +344,7 @@ class MainActivity : BaseActivity() { val data = httpStatus.rsp as SubscriptionRsp if (data.code != "1000") { RxToast.error(resources.getString(R.string.NodeAcquisitionFailed) + "${data.msg}") + AppLog.i("MainActivity", "httpSuccess GET_AIRNODES===>${data.msg}") } data.data.let { netSubUrl -> if (netSubUrl.isNotEmpty()) { @@ -515,6 +522,7 @@ class MainActivity : BaseActivity() { when (httpStatus.reqType) { HttpReqType.HEARTBEAT -> { Logger.d("心跳失败") + AppLog.i("HomeFragment", " httpFailure HEARTBEAT===>${httpStatus.msg}") if (5 <= HEART_BEAT_FAILURE_FREQUENCY) { HEART_BEAT_FAILURE_FREQUENCY = 0 Logger.d("心跳失败次数超过10次,退出登录") @@ -524,15 +532,18 @@ class MainActivity : BaseActivity() { } HttpReqType.CHECK_LOGIN -> { + AppLog.i("HomeFragment", " httpFailure CHECK_LOGIN===>${httpStatus.msg}") payResultLoading?.dismiss() RxToast.error(resources.getString(R.string.QueryFailed)+ httpStatus.msg) } HttpReqType.GET_AIRNODES -> { + AppLog.i("HomeFragment", " httpFailure GET_AIRNODES===>${httpStatus.msg}") Logger.e("获取节点异常:${httpStatus.msg}") } HttpReqType.VIPSIGN -> { + AppLog.i("HomeFragment", " httpFailure VIPSIGN===>${httpStatus.msg}") RxToast.error(resources.getString(R.string.CheckFailed) + httpStatus.msg) } @@ -806,7 +817,7 @@ class MainActivity : BaseActivity() { } fun checkVPN(){ val behaviorLogSwitch = - MMKV.defaultMMKV().decodeBool(BZYConstants.BehaviorLogSwitch, false) + MMKV.defaultMMKV().decodeBool(BZYConstants.BehaviorLogSwitch, true) if(behaviorLogSwitch){ launch(Dispatchers.IO) { val isVPN =Utils.isVpnActive(this@MainActivity) diff --git a/app/src/main/java/com/yingmao/clash/fragment/home/HomeFragment.kt b/app/src/main/java/com/yingmao/clash/fragment/home/HomeFragment.kt index 90788a9..83530a5 100644 --- a/app/src/main/java/com/yingmao/clash/fragment/home/HomeFragment.kt +++ b/app/src/main/java/com/yingmao/clash/fragment/home/HomeFragment.kt @@ -12,7 +12,6 @@ import android.os.Build import android.os.Bundle import android.text.TextUtils import android.view.View -import android.view.WindowManager import android.widget.FrameLayout import android.widget.ImageView import android.widget.LinearLayout @@ -30,8 +29,10 @@ import androidx.lifecycle.lifecycleScope import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.customview.customView import com.afollestad.materialdialogs.customview.getCustomView +import com.cncat.vpn.common.compat.startForegroundServiceCompat import com.cncat.vpn.common.constants.Intents import com.cncat.vpn.common.log.Log +import com.cncat.vpn.common.util.intent import com.cncat.vpn.core.Clash import com.cncat.vpn.core.model.TunnelState import com.cncat.vpn.service.model.Profile @@ -50,12 +51,15 @@ import com.yingmao.clash.act.MainActivity.Companion.newUuid import com.yingmao.clash.act.MainActivity.Companion.profileBinder import com.yingmao.clash.act.MainActivity.Companion.subUrl import com.yingmao.clash.act.NodeGroupActivity +import com.yingmao.clash.app.MainApplication import com.yingmao.clash.conf.BZYConstants +import com.yingmao.clash.conf.BZYConstants.Companion.MMKV_KEY_REMEMBER_USERNAME import com.yingmao.clash.conf.Conf import com.yingmao.clash.entity.NodeGroupItem import com.yingmao.clash.fragment.AccelerateViewModel import com.yingmao.clash.fragment.BaseFragment import com.yingmao.clash.levellog.AppLog +import com.yingmao.clash.levellog.LogcatService import com.yingmao.clash.net.http.HttpReqType import com.yingmao.clash.net.http.HttpStatus import com.yingmao.clash.net.http.entity.AppStartupStatus @@ -77,6 +81,7 @@ import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import java.net.URL import java.text.SimpleDateFormat import java.util.Locale import java.util.concurrent.atomic.AtomicInteger @@ -298,7 +303,8 @@ open class HomeFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispa if (connectId != -1) { accelerateViewModel.appStopStatus(connectId) } - + //关闭内核日志采集Service + requireActivity().stopService(LogcatService::class.intent) } rxDialogSureCancel.show() @@ -333,7 +339,8 @@ open class HomeFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispa if(networkAvailable){ showLoading(resources.getString(R.string.Starting), requireContext()) startClash(true) - //开启完毕之后开启定时器, + //开启完成之后开始采集日志 + behaviorLog() }else{ RxToast.error("网络不可用,请打开网络!") AppLog.i("NewAccFragment", "networkAvailable ${networkAvailable}") @@ -913,10 +920,12 @@ open class HomeFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispa when (httpStatus.reqType) { HttpReqType.AppStartupStatus -> { Log.d("AppStartupStatus is Failure ${httpStatus.msg}") + AppLog.i("HomeFragment", " httpFailure AppStartupStatus===>${httpStatus.msg}") } HttpReqType.AppStopStatus -> { Log.d("AppStopStatus is Failure ${httpStatus.msg}") + AppLog.i("HomeFragment", " httpFailure AppStopStatus===>${httpStatus.msg}") } else -> { @@ -1107,4 +1116,19 @@ open class HomeFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispa } return mList } + fun behaviorLog(){ + //开启采集之后点击采集 + MMKV.defaultMMKV().encode(BZYConstants.BehaviorLogSwitch, true) + val selectedName = + MMKV.defaultMMKV().decodeString(MMKV_KEY_REMEMBER_USERNAME, "") + val equipmentModel = Utils.getEquipmentModel() + val validPeriod = MMKV.defaultMMKV().decodeLong(BZYConstants.MMKV_KEY_VPN_VALID_PERIOD) + AppLog.i("HomeFragment", "selectedName===>${selectedName}") + AppLog.i("HomeFragment", "用户有效时长===>${validPeriod}") + AppLog.i("HomeFragment", "用户是否过期===>${checkExpire()}") + AppLog.i("HomeFragment", "机型数据===>${equipmentModel}") + AppLog.i("HomeFragment", "订阅连接地址===>${subUrl}") + AppLog.i("HomeFragment", "OAID===>${MainApplication.Companion.OAID}") + requireContext().startService(LogcatService::class.intent) + } } \ No newline at end of file diff --git a/app/src/main/java/com/yingmao/clash/fragment/setting/SettingFragment.kt b/app/src/main/java/com/yingmao/clash/fragment/setting/SettingFragment.kt index a8927fe..693163e 100644 --- a/app/src/main/java/com/yingmao/clash/fragment/setting/SettingFragment.kt +++ b/app/src/main/java/com/yingmao/clash/fragment/setting/SettingFragment.kt @@ -8,8 +8,6 @@ import android.content.Context import android.content.Intent import android.os.Build import android.os.Bundle -import android.os.Environment -import android.provider.Settings import android.text.TextUtils import android.view.View import android.widget.FrameLayout @@ -22,8 +20,6 @@ import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.RecyclerView -import com.afollestad.materialdialogs.MaterialDialog -import com.afollestad.materialdialogs.customview.customView import com.alibaba.sdk.android.oss.ClientException import com.alibaba.sdk.android.oss.OSSClient import com.alibaba.sdk.android.oss.ServiceException @@ -33,7 +29,6 @@ import com.alibaba.sdk.android.oss.common.auth.OSSStsTokenCredentialProvider import com.alibaba.sdk.android.oss.internal.OSSAsyncTask import com.alibaba.sdk.android.oss.model.PutObjectRequest import com.alibaba.sdk.android.oss.model.PutObjectResult -import com.cncat.vpn.common.compat.startForegroundServiceCompat import com.cncat.vpn.common.log.Log import com.cncat.vpn.common.util.intent import com.hjq.permissions.OnPermissionCallback @@ -47,21 +42,19 @@ import com.yingmao.clash.act.ActivityActivity import com.yingmao.clash.act.AgreementAndPrivacyActivity import com.yingmao.clash.act.BandPhoneActivity import com.yingmao.clash.act.MainActivity -import com.yingmao.clash.act.MainActivity.Companion.newUuid import com.yingmao.clash.act.MainActivity.Companion.profileBinder import com.yingmao.clash.act.MainActivity.Companion.setSub2 import com.yingmao.clash.act.MainActivity.Companion.subUrl -import com.yingmao.clash.act.MainActivity.Companion.trafficStatisticsData import com.yingmao.clash.act.SettingActivity import com.yingmao.clash.act.ShareActivity import com.yingmao.clash.act.SplashHelper import com.yingmao.clash.app.MainApplication -import com.yingmao.clash.levellog.LogcatService import com.yingmao.clash.conf.BZYConstants import com.yingmao.clash.entity.SettingPageBean import com.yingmao.clash.fragment.BaseFragment import com.yingmao.clash.fragment.home.HomeFragment.Companion.clashRunning import com.yingmao.clash.levellog.AppLog +import com.yingmao.clash.levellog.LogcatService import com.yingmao.clash.net.http.HttpReqType import com.yingmao.clash.net.http.HttpStatus import com.yingmao.clash.net.http.entity.ParamData @@ -184,24 +177,11 @@ class SettingFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatc R.drawable.switching_item_tag, ) - val logDirParent = "applogs" - val logDir = File(requireActivity().filesDir, logDirParent) - val processName =getProcessName() - val logFile = File(logDir, "$processName.log") - val upLoadData = if(logFile.exists()){ - SettingPageBean( - 7, - "上传日志", - R.drawable.user_uplog_icon, - ) - }else{ - SettingPageBean( - 7, - "采集日志", - R.drawable.user_uplog_icon, - ) - } - + val upLoadData =SettingPageBean( + 7, + "上传日志", + R.drawable.user_uplog_icon, + ) val privacyPolicyItem= SettingPageBean( 8, resources.getString(R.string.PrivacyPolicy), @@ -226,7 +206,7 @@ class SettingFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatc settingPageList.add(singItem) settingPageList.add(serviceTermsItem) settingPageList.add(sourceSwitchItem) -// settingPageList.add(upLoadData) + settingPageList.add(upLoadData) settingPageList.add(privacyPolicyItem) settingPageList.add(initializationItem) settingPageList.add(customItem) @@ -294,30 +274,21 @@ class SettingFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatc } 7->{ - if(itemData.name=="上传日志"){ - showLoading(resources.getString(R.string.UploadingInProgress), requireActivity()) - mainAtyVM.getUploadParameters() - settingPageList[itemData.type-1].name="采集日志" - settingAdapter.notifyItemChanged(itemData.type-1) - MMKV.defaultMMKV().encode(BZYConstants.BehaviorLogSwitch, false) - requireActivity().stopService(LogcatService::class.intent) + val getIsGlo= MMKV.defaultMMKV().decodeBool(BZYConstants.MMKV_KEY_GLOBAL_MODEL, false) + if(clashRunning&&getIsGlo){ + RxToast.info("全局模式暂不支持上传日志,请切换到全局模式或关闭加速!") }else{ - MaterialDialog(requireActivity()).show { - this.cancelable(true) - cornerRadius(res = R.dimen.dp_15) - customView( - R.layout.logsings_dialog_layout, - scrollable = false, - noVerticalPadding = true, - horizontalPadding = false - ) - val tvSure = findViewById(R.id.tvSure) - tvSure.setOnClickListener { - settingPageList[itemData.type-1].name="上传日志" - settingAdapter.notifyItemChanged(itemData.type-1) - requireActivity().startForegroundServiceCompat(LogcatService::class.intent) - dismiss() - } + + val logDirParent = "applogs" + val logDir = File(requireActivity().filesDir, logDirParent) + val processName =getProcessName() + val logFile = File(logDir, "$processName.log") + if(logFile.exists()){ + showLoading(resources.getString(R.string.UploadingInProgress), requireActivity()) + mainAtyVM.getUploadParameters() + requireActivity().stopService(LogcatService::class.intent) + }else{ + RxToast.info("暂时未采集到相关日志数据") } } } @@ -873,7 +844,6 @@ class SettingFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatc hideLoading() val deleteFile = DataUtils.deleteFile(filePath) Log.i("PutObjectRequest deleteFile ${deleteFile}") - AppLog.i("LogcatService", "删除删除成功deleteFile::${deleteFile}") MMKV.defaultMMKV().encode(BZYConstants.BehaviorLogSwitch, false) RxToast.info(resources.getString(R.string.BehaviorLogSuccessfully)) } diff --git a/app/src/main/java/com/yingmao/clash/levellog/AppLog.kt b/app/src/main/java/com/yingmao/clash/levellog/AppLog.kt index f59a154..c4467f6 100644 --- a/app/src/main/java/com/yingmao/clash/levellog/AppLog.kt +++ b/app/src/main/java/com/yingmao/clash/levellog/AppLog.kt @@ -28,7 +28,7 @@ object AppLog { tr: Throwable? ) { val behaviorLogSwitch = - MMKV.defaultMMKV().decodeBool(BZYConstants.BehaviorLogSwitch, false) + MMKV.defaultMMKV().decodeBool(BZYConstants.BehaviorLogSwitch, true) if(behaviorLogSwitch){ LogDispatcher.enqueue( LogEvent( diff --git a/app/src/main/java/com/yingmao/clash/levellog/LogcatService.kt b/app/src/main/java/com/yingmao/clash/levellog/LogcatService.kt index b604a6f..f782d47 100644 --- a/app/src/main/java/com/yingmao/clash/levellog/LogcatService.kt +++ b/app/src/main/java/com/yingmao/clash/levellog/LogcatService.kt @@ -1,6 +1,5 @@ package com.yingmao.clash.levellog -import android.app.PendingIntent import android.app.Service import android.content.ComponentName import android.content.Intent @@ -11,25 +10,12 @@ import android.os.IBinder import android.os.IInterface import android.util.Log import androidx.annotation.RequiresApi -import androidx.core.app.NotificationChannelCompat -import androidx.core.app.NotificationCompat -import androidx.core.app.NotificationManagerCompat -import com.cncat.vpn.common.compat.getColorCompat -import com.cncat.vpn.common.compat.pendingIntentFlags -import com.cncat.vpn.common.compat.startForegroundCompat import com.cncat.vpn.common.util.intent import com.cncat.vpn.core.model.LogMessage import com.cncat.vpn.service.RemoteService import com.cncat.vpn.service.remote.ILogObserver import com.cncat.vpn.service.remote.IRemoteService import com.cncat.vpn.service.remote.unwrap -import com.tencent.mmkv.MMKV -import com.yingmao.clash.R -import com.yingmao.clash.act.MainActivity -import com.yingmao.clash.act.SettingActivity -import com.yingmao.clash.app.MainApplication -import com.yingmao.clash.conf.BZYConstants -import com.yingmao.clash.util.Utils import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.NonCancellable @@ -46,7 +32,6 @@ class LogcatService : Service(), CoroutineScope by CoroutineScope(Dispatchers.De Log.i("LogcatServiceClose","onServiceDisconnected::${name}") stopSelf() } - @RequiresApi(Build.VERSION_CODES.KITKAT) override fun onServiceConnected(name: ComponentName?, service: IBinder?) { Log.i("LogcatServiceConnect","onServiceConnected::${name}") @@ -56,25 +41,13 @@ class LogcatService : Service(), CoroutineScope by CoroutineScope(Dispatchers.De override fun onCreate() { super.onCreate() - - running = true - - createNotificationChannel() - - showNotification() - bindService(RemoteService::class.intent, connection, BIND_AUTO_CREATE) } override fun onDestroy() { cancel() - unbindService(connection) - - stopForeground(true) - - running = false - + stopSelf() super.onDestroy() } @@ -100,14 +73,6 @@ class LogcatService : Service(), CoroutineScope by CoroutineScope(Dispatchers.De val channel = Channel(CACHE_CAPACITY) try { - MMKV.defaultMMKV().encode(BZYConstants.Companion.BehaviorLogSwitch, true) - val selectedName = - MMKV.defaultMMKV().decodeString(BZYConstants.Companion.NODE_SELECTED_NAME_KEY, "") - val equipmentModel = Utils.getEquipmentModel() - AppLog.i("LogcatService", "selectedName===>${selectedName}") - AppLog.i("LogcatService", "用户是否过期===>${checkExpire()}") - AppLog.i("LogcatService", "机型数据===>${equipmentModel}") - AppLog.i("LogcatService", "OAID===>${MainApplication.Companion.OAID}") val observer = object : ILogObserver { override fun newItem(log: LogMessage) { channel.trySend(log) @@ -117,6 +82,7 @@ class LogcatService : Service(), CoroutineScope by CoroutineScope(Dispatchers.De while (isActive) { val msg = channel.receive() AppLog.i("LogcatServiceMsg", "core msg===>${msg}") + Log.i("LogcatServiceMsg","core msg===>${msg}") } } catch (e: IOException) { Log.e("Write log file: $e", e.toString()) @@ -131,52 +97,7 @@ class LogcatService : Service(), CoroutineScope by CoroutineScope(Dispatchers.De } } - private fun createNotificationChannel() { - NotificationManagerCompat.from(this) - .createNotificationChannel( - NotificationChannelCompat.Builder( - CHANNEL_ID, - NotificationManagerCompat.IMPORTANCE_DEFAULT - ).setName(getString(R.string.clash_logcat)).build() - ) - } - - private fun showNotification() { - val notification = NotificationCompat - .Builder(this, CHANNEL_ID) - .setSmallIcon(R.mipmap.oneclickconnection) - .setColor(getColorCompat(R.color.color_clash)) - .setContentTitle(getString(R.string.clash_logcat)) - .setContentText("采集中") - .setContentIntent( - PendingIntent.getActivity( - this, - R.id.nf_logcat_status, - MainActivity::class.intent - .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP), - pendingIntentFlags(PendingIntent.FLAG_UPDATE_CURRENT) - ) - ) - .build() - - startForegroundCompat(R.id.nf_logcat_status, notification) - } - companion object { - private const val CHANNEL_ID = "clash_logcat_channel_id" private const val CACHE_CAPACITY = 129 - - var running: Boolean = false - } - private fun checkExpire(): Boolean { - val validPeriod = MMKV.defaultMMKV().decodeLong(BZYConstants.Companion.MMKV_KEY_VPN_VALID_PERIOD) - if (validPeriod > 0) { - val nowTime = System.currentTimeMillis(); - com.cncat.vpn.common.log.Log.d("validPeriod==>$validPeriod, nowTime==>$nowTime") - if (validPeriod >= nowTime) { - return false - } - } - return true } } \ No newline at end of file diff --git a/app/src/main/java/com/yingmao/clash/util/Utils.kt b/app/src/main/java/com/yingmao/clash/util/Utils.kt index a1b546e..6c46531 100644 --- a/app/src/main/java/com/yingmao/clash/util/Utils.kt +++ b/app/src/main/java/com/yingmao/clash/util/Utils.kt @@ -15,8 +15,12 @@ import android.view.View import android.view.ViewGroup import androidx.annotation.RequiresApi import com.yingmao.clash.levellog.AppLog +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext import okhttp3.OkHttpClient import okhttp3.Request +import org.json.JSONObject +import java.net.Inet4Address import java.net.NetworkInterface import java.nio.charset.StandardCharsets import java.security.MessageDigest diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 530b960..94ae3be 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -492,8 +492,8 @@ 模式切换中 模式切换成功 - 行为日志上传成功! - 行为日志上传失败! + 日志上传成功! + 日志上传失败! VPN权限未允许 请设置允许! 请关闭加速后在切换节点 \ No newline at end of file