一键连

日志上传更改
This commit is contained in:
11111 2025-12-30 20:35:41 +08:00
parent 2a81375282
commit 39e847335c
7 changed files with 74 additions and 144 deletions

View File

@ -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<String>()
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)

View File

@ -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)
}
}

View File

@ -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<TextView>(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))
}

View File

@ -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(

View File

@ -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<LogMessage>(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
}
}

View File

@ -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

View File

@ -492,8 +492,8 @@
</string>
<string name="modelchanging">模式切换中</string>
<string name="modelchangSuccess">模式切换成功</string>
<string name="BehaviorLogSuccessfully">行为日志上传成功!</string>
<string name="BehaviorLogError">行为日志上传失败!</string>
<string name="BehaviorLogSuccessfully">日志上传成功!</string>
<string name="BehaviorLogError">日志上传失败!</string>
<string name="vpnStartingError">VPN权限未允许 请设置允许!</string>
<string name="CloseChooseNode">请关闭加速后在切换节点</string>
</resources>