bug fix & cleanup code

This commit is contained in:
Kr328 committed 2020-02-20 13:43:38 +08:00
1 parent 121108c416
commit eba2869c1b
38 files changed
+57 -228

No files matched your search

@@ -63,8 +63,8 @@ abstract class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope()
var menu: Menu? = null
lateinit var uiSettings: UiSettings
private set
lateinit var language: String
lateinit var darkMode: String
private lateinit var language: String
private lateinit var darkMode: String
open suspend fun onClashStarted() {}
open suspend fun onClashStopped(reason: String?) {}
@@ -6,8 +6,6 @@ object Constants {
const val LOG_DIR_NAME = "logs"
const val FILE_PROVIDER_AUTH = BuildConfig.APPLICATION_ID + ".files"
const val URL_PROVIDER_TYPE_FILE = "file"
const val URL_PROVIDER_TYPE_URL = "url"
const val URL_PROVIDER_TYPE_EXTERNAL = "external"
@@ -12,7 +12,6 @@ import android.os.Binder
import android.os.Build
import android.os.IBinder
import android.os.IInterface
import android.text.format.DateFormat
import androidx.collection.CircularArray
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
@@ -24,13 +23,14 @@ import com.github.kr328.clash.service.IClashManager
import com.github.kr328.clash.service.ipc.IStreamCallback
import com.github.kr328.clash.service.ipc.ParcelableContainer
import com.github.kr328.clash.service.util.intent
import com.github.kr328.clash.utils.format
import com.github.kr328.clash.utils.logsDir
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.selects.select
import java.io.FileWriter
import java.io.IOException
import java.lang.Exception
import java.util.*
import kotlin.math.max
class LogcatService : Service(), CoroutineScope by MainScope(), IInterface {
@@ -184,10 +184,9 @@ class LogcatService : Service(), CoroutineScope by MainScope(), IInterface {
logsDir.mkdirs()
try {
FileWriter(logsDir.resolve(entity.fileName)).buffered().use { output ->
val dateFormat = DateFormat.getDateFormat(this@LogcatService)
var offset = 0L
output.write("# Logcat on ${dateFormat.format(entity.date)}")
output.write("# Logcat on ${Date(entity.date).format(this@LogcatService)}")
output.newLine()
while (isActive) {
@@ -4,7 +4,6 @@ import android.app.Activity
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.text.format.DateFormat
import android.util.TypedValue
import android.view.ViewGroup
import androidx.annotation.ColorInt
@@ -17,6 +16,7 @@ import com.github.kr328.clash.design.view.CommonUiLayout
import com.github.kr328.clash.model.LogFile
import com.github.kr328.clash.service.util.intent
import com.github.kr328.clash.service.util.startForegroundServiceCompat
import com.github.kr328.clash.utils.format
import com.github.kr328.clash.utils.logsDir
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.snackbar.Snackbar
@@ -228,10 +228,8 @@ class LogsActivity : BaseActivity() {
return
val d = Date(file.date)
val date = DateFormat.getDateFormat(this)
val time = DateFormat.getTimeFormat(this)
val exportName = getString(R.string.format_export_log_name, date.format(d), time.format(d))
val exportName = getString(R.string.format_export_log_name, d.format(this))
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT)
.setType("text/plain")
@@ -2,16 +2,12 @@ package com.github.kr328.clash
import android.app.Application
import android.content.Context
import android.content.res.Configuration
import com.github.kr328.clash.core.Global
import com.github.kr328.clash.core.utils.Log
import com.github.kr328.clash.preference.UiSettings
import com.github.kr328.clash.remote.Broadcasts
import com.github.kr328.clash.remote.Remote
import com.microsoft.appcenter.AppCenter
import com.microsoft.appcenter.analytics.Analytics
import com.microsoft.appcenter.crashes.Crashes
import java.util.*
@Suppress("unused")
class MainApplication : Application() {
@@ -8,7 +8,6 @@ import android.view.View
import androidx.appcompat.widget.SearchView
import androidx.recyclerview.widget.LinearLayoutManager
import com.github.kr328.clash.adapter.PackagesAdapter
import com.github.kr328.clash.preference.UiSettings
import com.github.kr328.clash.service.settings.ServiceSettings
import kotlinx.android.synthetic.main.activity_access_control_packages.*
import kotlinx.coroutines.*
@@ -1,7 +1,6 @@
package com.github.kr328.clash.adapter
import android.content.Context
import android.text.format.DateFormat
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@@ -9,6 +8,7 @@ import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.github.kr328.clash.R
import com.github.kr328.clash.core.event.LogEvent
import com.github.kr328.clash.utils.format
import java.util.*
class LogAdapter(
@@ -19,11 +19,10 @@ class LogAdapter(
private val level: TextView = view.findViewById(R.id.level)
private val time: TextView = view.findViewById(R.id.time)
private val payload: TextView = view.findViewById(R.id.payload)
private val timeFormat = DateFormat.getTimeFormat(view.context)
fun bind(logEvent: LogEvent) {
level.text = logEvent.level.toString()
time.text = timeFormat.format(Date(logEvent.time))
time.text = Date(logEvent.time).format(itemView.context, includeDate = false)
payload.text = logEvent.message
}
}
@@ -1,7 +1,6 @@
package com.github.kr328.clash.adapter
import android.content.Context
import android.text.format.DateFormat
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@@ -9,6 +8,7 @@ import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.github.kr328.clash.R
import com.github.kr328.clash.model.LogFile
import com.github.kr328.clash.utils.format
import java.util.*
class LogFileAdapter(
@@ -18,9 +18,6 @@ class LogFileAdapter(
) : RecyclerView.Adapter<LogFileAdapter.Holder>() {
var fileList: List<LogFile> = emptyList()
private val dateFormat = DateFormat.getDateFormat(context)
private val timeFormat = DateFormat.getTimeFormat(context)
class Holder(view: View) : RecyclerView.ViewHolder(view) {
val root: View = view.findViewById(R.id.root)
val fileName: TextView = view.findViewById(R.id.fileName)
@@ -47,8 +44,7 @@ class LogFileAdapter(
val date = Date(current.date)
holder.fileName.text = current.fileName
holder.date.text = context.getString(R.string.format_date_time,
dateFormat.format(date), timeFormat.format(date))
holder.date.text = date.format(context)
holder.menu.setOnClickListener {
onMenuClicked(current)
}
@@ -10,7 +10,6 @@ import android.widget.TextView
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import com.github.kr328.clash.R
import com.github.kr328.clash.core.utils.Log
import com.google.android.material.checkbox.MaterialCheckBox
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@@ -20,7 +20,7 @@ class UiSettings(context: Context):
val PROXY_GROUP_SORT = StringEntry("proxy_group_sort", PROXY_SORT_DEFAULT)
val PROXY_PROXY_SORT = StringEntry("proxy_proxy_sort", PROXY_SORT_DEFAULT)
val PROXY_LAST_SELECT_GROUP = StringEntry("proxy_last_select_group", "")
val PROXY_MERGE_PREFIX = BooleanEntry("proxy_merge_prefix", true)
val PROXY_MERGE_PREFIX = BooleanEntry("proxy_merge_prefix", false)
val LANGUAGE = StringEntry("language", "")
val DARK_MODE = StringEntry("dark_mode", DARK_MODE_AUTO)
}
@@ -5,13 +5,10 @@ import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.net.Uri
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ProcessLifecycleOwner
import com.github.kr328.clash.service.Constants
import com.github.kr328.clash.service.Intents
import com.github.kr328.clash.service.ServiceStatusProvider
import com.github.kr328.clash.service.data.ClashProfileEntity
object Broadcasts {
@@ -1,29 +0,0 @@
package com.github.kr328.clash.remote
import android.os.RemoteException
import com.github.kr328.clash.core.event.LogEvent
import com.github.kr328.clash.service.ipc.IStreamCallback
import com.github.kr328.clash.service.ipc.ParcelableContainer
import kotlinx.coroutines.channels.Channel
class LogChannel : Channel<LogEvent> by Channel(Channel.CONFLATED) {
fun createCallback(): IStreamCallback {
return object : IStreamCallback.Stub() {
override fun complete() {
close()
}
override fun completeExceptionally(reason: String?) {
close(RemoteException(reason))
}
override fun send(data: ParcelableContainer?) {
try {
offer(data!!.data!! as LogEvent)
} catch (e: Exception) {
throw RemoteException(e.message)
}
}
}
}
}
@@ -2,7 +2,6 @@ package com.github.kr328.clash.settings
import android.content.pm.PackageManager
import android.os.Bundle
import com.github.kr328.clash.BaseActivity
import com.github.kr328.clash.OnBootReceiver
import com.github.kr328.clash.R
import com.github.kr328.clash.remote.Broadcasts
@@ -0,0 +1,25 @@
package com.github.kr328.clash.utils
import android.content.Context
import java.text.SimpleDateFormat
import java.util.*
const val DATE_DATE_ONLY = "yyyy-MM-dd"
const val DATE_TIME_ONLY = "HH:mm:ss"
const val DATE_ALL = "$DATE_DATE_ONLY $DATE_TIME_ONLY"
fun Date.format(context: Context, includeDate: Boolean = true, includeTime: Boolean = true, custom: String = ""): String {
val locale = context.resources.configuration.locales[0]
return when {
custom.isNotEmpty() ->
SimpleDateFormat(custom, locale).format(this)
includeDate && includeTime ->
SimpleDateFormat(DATE_ALL, locale).format(this)
includeDate ->
SimpleDateFormat(DATE_DATE_ONLY, locale).format(this)
includeTime ->
SimpleDateFormat(DATE_TIME_ONLY, locale).format(this)
else -> ""
}
}
@@ -2,7 +2,6 @@ package com.github.kr328.clash.utils
import android.content.Context
import com.github.kr328.clash.R
import com.github.kr328.clash.core.Global
object IntervalUtils {
private const val MILLIS_SECOND = 1000L
@@ -38,8 +38,9 @@ object PrefixMerger {
for (group in groups) {
var diffIndex = 0
val size = group.map { it.first.length }.min() ?: 0
diff@ for (charIndex in group[0].first.indices) {
diff@ for (charIndex in 0 until size) {
for (stringIndex in 0 until (group.size - 1)) {
if (group[stringIndex].first[charIndex] != group[stringIndex + 1].first[charIndex])
break@diff
@@ -5,7 +5,7 @@ import com.github.kr328.clash.core.model.ProxyGroup
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
class ProxySorter(val groupOrder: Order, val proxyOrder: Order) {
class ProxySorter(private val groupOrder: Order, private val proxyOrder: Order) {
enum class Order {
DEFAULT, DELAY_INCREASE, DELAY_DECREASE, NAME_INCREASE, NAME_DECREASE
}
+1 -2
View File
@@ -46,9 +46,8 @@
<string name="external">外部</string>
<string name="file">文件</string>
<string name="file_exported">文件已导出</string>
<string name="format_date_time">%s %s</string>
<string name="format_days">%d 天</string>
<string name="format_export_log_name">%s %s.log</string>
<string name="format_export_log_name">%s.log</string>
<string name="format_hours">%d 小时</string>
<string name="format_minutes">%d 分钟</string>
<string name="format_months">%d 月</string>
+3 -3
View File
@@ -1,4 +1,4 @@
<resources>
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="PluralsCandidate">
<string name="launch_name">Clash</string>
<string name="application_name">Clash for Android</string>
@@ -24,6 +24,7 @@
<string name="unknown">Unknown</string>
<string name="recently">Recently</string>
<string name="format_seconds">%d seconds</string>
<string name="format_minutes">%d minutes</string>
<string name="format_hours">%d hours</string>
@@ -93,8 +94,7 @@
<string name="clash_logcat">Clash Logcat</string>
<string name="history">History</string>
<string name="log_viewer">Log Viewer</string>
<string name="format_date_time">%s %s</string>
<string name="format_export_log_name">%s %s.log</string>
<string name="format_export_log_name">%s.log</string>
<string name="delete_all_logs">Delete All Logs</string>
<string name="delete_all_logs_warn">All historical logs will *LOST*</string>
+1 -1
View File
@@ -14,7 +14,7 @@ buildscript {
gKotlinVersion = '1.3.61'
gKotlinCoroutineVersion = '1.3.3'
gKotlinSerializationVersion = '0.14.0'
gRoomVersion = '2.2.3'
gRoomVersion = '2.2.4'
gAppCenterVersion = '2.5.1'
gAndroidKtxVersion = "1.2.0"
gLifecycleVersion = "2.2.0"
+5 -5
View File
@@ -75,14 +75,14 @@ open class GolangBindTask : DefaultTask() {
@TaskAction
fun process() {
environment.put("GOPATH", goPath.absolutePath)
environment.put("ANDROID_HOME", findAndroidSdkPath().absolutePath)
environment.put("ANDROID_NDK_HOME", findAndroidNdkPath().absolutePath)
environment["GOPATH"] = goPath.absolutePath
environment["ANDROID_HOME"] = findAndroidSdkPath().absolutePath
environment["ANDROID_NDK_HOME"] = findAndroidNdkPath().absolutePath
if (Os.isFamily(Os.FAMILY_WINDOWS))
environment.put("Path", System.getenv("Path") + ";" + goPath.resolve("bin"))
environment["Path"] = System.getenv("Path") + ";" + goPath.resolve("bin")
else
environment.put("PATH", System.getenv("PATH") + ":" + goPath.resolve("bin"))
environment["PATH"] = System.getenv("PATH") + ":" + goPath.resolve("bin")
goPath.resolve("src/github.com/kr328").deleteRecursively()
goBindPath.deleteRecursively()
@@ -1,11 +1,9 @@
package com.github.kr328.clash.core
import android.app.Application
import android.content.res.Configuration
object Global {
lateinit var application: Application
val overrideConfiguration = Configuration()
fun init(application: Application) {
this.application = application
@@ -1,34 +0,0 @@
package com.github.kr328.clash.core.event
import android.os.Parcel
import android.os.Parcelable
import com.github.kr328.clash.core.serialization.Parcels
import kotlinx.serialization.Serializable
@Serializable
data class ErrorEvent(val type: Type, val message: String) : Event, Parcelable {
enum class Type {
PROFILE_LOAD,
START_FAILURE,
QUERY_PROXY_FAILURE,
SET_PROXY_SELECTED
}
override fun writeToParcel(parcel: Parcel, flags: Int) {
Parcels.dump(serializer(), this, parcel)
}
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<ErrorEvent> {
override fun createFromParcel(parcel: Parcel): ErrorEvent {
return Parcels.load(serializer(), parcel)
}
override fun newArray(size: Int): Array<ErrorEvent?> {
return arrayOfNulls(size)
}
}
}
@@ -2,10 +2,4 @@ package com.github.kr328.clash.core.event
import android.os.Parcelable
interface Event : Parcelable {
companion object {
const val EVENT_LOG = 1
const val EVENT_TRAFFIC = 3
const val EVENT_BANDWIDTH = 4
}
}
interface Event : Parcelable
@@ -10,14 +10,12 @@ data class LogEvent(
val level: Level,
val message: String,
val time: Long = System.currentTimeMillis()
) :
Event {
): Event {
companion object {
const val DEBUG_VALUE = "debug"
const val INFO_VALUE = "info"
const val WARN_VALUE = "warning"
const val ERROR_VALUE = "error"
const val UNKNOWN_VALUE = "unknown"
@JvmField
val CREATOR = object : Parcelable.Creator<LogEvent> {
@@ -1,32 +0,0 @@
package com.github.kr328.clash.core.event
import android.os.Parcel
import android.os.Parcelable
import androidx.annotation.Keep
import com.github.kr328.clash.core.serialization.Parcels
import kotlinx.serialization.Serializable
@Serializable
data class TrafficEvent(val down: Long, val up: Long) : Event, Parcelable {
override fun writeToParcel(parcel: Parcel, flags: Int) {
Parcels.dump(serializer(), this, parcel)
}
override fun describeContents(): Int {
return 0
}
companion object {
@JvmField
@Keep
val CREATOR = object : Parcelable.Creator<TrafficEvent> {
override fun createFromParcel(parcel: Parcel): TrafficEvent {
return Parcels.load(serializer(), parcel)
}
override fun newArray(size: Int): Array<TrafficEvent?> {
return arrayOfNulls(size)
}
}
}
}
@@ -17,7 +17,4 @@ object Log {
fun v(message: String, throwable: Throwable? = null) =
android.util.Log.v(TAG, message, throwable)
fun wtf(message: String, throwable: Throwable? = null) =
android.util.Log.wtf(TAG, message, throwable)
}
@@ -2,7 +2,6 @@ package com.github.kr328.clash.design.common
import android.content.Context
import android.graphics.drawable.Drawable
import android.view.View
class CommonUiBuilder(val screen: CommonUiScreen) {
val context: Context
@@ -84,15 +83,4 @@ class CommonUiBuilder(val screen: CommonUiScreen) {
screen.addElement(tips)
}
fun custom(
view: View,
setup: Custom.() -> Unit
) {
val custom = Custom(screen, view)
setup(custom)
screen.addElement(custom)
}
}
@@ -1,31 +0,0 @@
package com.github.kr328.clash.design.common
import android.os.Bundle
import android.view.View
class Custom(screen: CommonUiScreen, override val view: View): Base(screen) {
private var saveStateHandler: (Bundle) -> Unit = {}
private var restoreStateHandler: (Bundle) -> Unit = {}
private var applyAttributeHandler: (Boolean, Boolean) -> Unit =
{ enable, hidden -> super.applyAttribute(enable, hidden) }
fun onSaveState(handler: (Bundle) -> Unit) {
this.saveStateHandler = handler
}
fun onRestoreState(handler: (Bundle) -> Unit) {
this.restoreStateHandler = handler
}
fun onApplyAttribute(handler: (Boolean, Boolean) -> Unit) {
this.applyAttributeHandler = handler
}
override fun saveState(bundle: Bundle) {
saveStateHandler(bundle)
}
override fun restoreState(bundle: Bundle) {
restoreStateHandler(bundle)
}
}
@@ -2,7 +2,6 @@ package com.github.kr328.clash.design.common
import android.graphics.drawable.Drawable
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.widget.EditText
-5
View File
@@ -7,12 +7,10 @@
<application>
<service
android:name="ClashService"
android:label="@string/clash_service_label"
android:exported="false"
android:process=":background" />
<service
android:name="TunService"
android:label="@string/tun_service_label"
android:exported="false"
android:process=":background"
android:permission="android.permission.BIND_VPN_SERVICE">
@@ -22,17 +20,14 @@
</service>
<service
android:name=".ClashManagerService"
android:label="@string/clash_manager_service_label"
android:exported="false"
android:process=":background" />
<service
android:name=".ProfileService"
android:label="@string/clash_profile_service_label"
android:exported="false"
android:process=":background" />
<service
android:name=".ProfileBackgroundService"
android:label="@string/clash_profile_service_label"
android:exported="false"
android:process=":background" />
@@ -1,9 +1,7 @@
package com.github.kr328.clash.service
import android.app.AlarmManager
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.ComponentName
import android.content.Context
import android.content.Intent
@@ -20,10 +18,8 @@ import com.github.kr328.clash.service.ipc.ParcelableContainer
import com.github.kr328.clash.service.transact.ProfileRequest
import com.github.kr328.clash.service.util.RandomUtils
import com.github.kr328.clash.service.util.UpdateUtils
import com.github.kr328.clash.service.util.componentName
import com.github.kr328.clash.service.util.intent
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.selects.select
@@ -3,10 +3,8 @@ package com.github.kr328.clash.service
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.os.Build
import com.github.kr328.clash.service.transact.ProfileRequest
import com.github.kr328.clash.service.util.componentName
import com.github.kr328.clash.service.util.intent
import com.github.kr328.clash.service.util.startForegroundServiceCompat
class ProfileRequestReceiver : BroadcastReceiver() {
@@ -1,7 +1,5 @@
package com.github.kr328.clash.service
import android.app.AlarmManager
import android.app.PendingIntent
import android.content.Intent
import android.net.Uri
import android.os.IBinder
@@ -9,7 +9,6 @@ import com.github.kr328.clash.service.settings.ServiceSettings
import com.github.kr328.clash.service.util.broadcastNetworkChanged
import kotlinx.coroutines.*
import java.net.Inet6Address
import java.net.InetAddress
class TunService : VpnService(), CoroutineScope by MainScope() {
companion object {
@@ -2,9 +2,12 @@ package com.github.kr328.clash.service.net
import android.content.Context
import android.net.*
import kotlinx.coroutines.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.withContext
import java.net.InetAddress
class DefaultNetworkChannel(val context: Context, scope: CoroutineScope) :
@@ -1,13 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="clash_manager_service_label">Clash 管理器服务</string>
<string name="clash_profile_service_label">Clash 配置管理服务</string>
<string name="clash_service_label">Clash 核心服务</string>
<string name="clash_service_status_channel">Clash 状态</string>
<string name="profile_service_status_channel">配置服务状态</string>
<string name="profile_status_channel">配置处理状态</string>
<string name="running">正在运行</string>
<string name="tun_service_label">Tun 设备服务</string>
<string name="format_in_queue">%d 个项目在队列中</string>
<string name="format_update_complete">更新 %s 完成</string>
<string name="format_update_failure">更新 %s 失败\\n%s</string>
+1 -9
View File
@@ -1,22 +1,14 @@
<resources>
<string name="clash_service_status_channel">Clash Status</string>
<!-- from https://github.com/shadowsocks/shadowsocks-android/blob/master/core/src/main/res/values/strings.xml -->
<string name="clash_notification_content" translatable="false">"%1$s↑\t%2$s↓"</string>
<string name="clash_service_status_channel">Clash Status</string>
<string name="profile_service_status_channel">Profile Service Status</string>
<string name="processing_profiles">Processing Profiles</string>
<string name="format_in_queue">%d items in Queue</string>
<string name="process_result">Process Result</string>
<string name="format_update_complete">Update %s Completed</string>
<string name="format_update_failure">Update %s Failure\n%s</string>
<string name="profile_status_channel">Profile Processing Status</string>
<string name="clash_service_label">Clash Core Service</string>
<string name="tun_service_label">Tun Device Service</string>
<string name="clash_manager_service_label">Clash Manager Service</string>
<string name="clash_profile_service_label">Clash Profile Manager Service</string>
<string name="running">Running</string>
</resources>