bug fix
This commit is contained in:
23 files changed
+59
-154
No files matched your search
@@ -26,6 +26,8 @@ class CreateProfileActivity : BaseActivity() {
|
||||
const val REQUEST_CODE = 20000
|
||||
}
|
||||
|
||||
private val self = this
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
@@ -43,7 +45,7 @@ class CreateProfileActivity : BaseActivity() {
|
||||
mainList.setOnItemClickListener { _, _, position, _ ->
|
||||
val item = providers[position]
|
||||
|
||||
launch {
|
||||
self.launch {
|
||||
val id = withProfile {
|
||||
acquireUnused(item.type)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.github.kr328.clash
|
||||
|
||||
import android.app.Activity
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
@@ -107,6 +108,10 @@ class ProfileEditActivity : BaseActivity() {
|
||||
updateMetadata(metadata.id, metadata)
|
||||
commitAsync(metadata.id).await()
|
||||
}
|
||||
|
||||
setResult(Activity.RESULT_OK)
|
||||
|
||||
finish()
|
||||
} catch (e: Exception) {
|
||||
showSnackbarException(getString(R.string.download_failure), e.message)
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import com.github.kr328.clash.common.ids.Intents
|
||||
import com.github.kr328.clash.common.util.componentName
|
||||
import com.github.kr328.clash.common.util.intent
|
||||
import com.github.kr328.clash.common.util.startForegroundServiceCompat
|
||||
import com.github.kr328.clash.common.utils.Log
|
||||
import com.github.kr328.clash.remote.withProfile
|
||||
import com.github.kr328.clash.service.ProfileBackgroundService
|
||||
import com.github.kr328.clash.service.ProfileProvider
|
||||
@@ -171,9 +172,7 @@ class ProfilesActivity : BaseActivity(), ProfileAdapter.Callback, ProfilesMenu.C
|
||||
override fun onDuplicate(entity: ProfileMetadata) {
|
||||
launch {
|
||||
withProfile {
|
||||
val newId = acquireCloned(entity.id)
|
||||
|
||||
openProperties(newId)
|
||||
openProperties(acquireCloned(entity.id))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ class TileService : TileService() {
|
||||
addAction(Intents.INTENT_ACTION_CLASH_STOPPED)
|
||||
addAction(Intents.INTENT_ACTION_PROFILE_LOADED)
|
||||
},
|
||||
Permissions.PERMISSION_ACCESS_CLASH,
|
||||
Permissions.PERMISSION_RECEIVE_BROADCASTS,
|
||||
null
|
||||
)
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ class ProfileEditFragment(
|
||||
icon = requireContext().getDrawable(R.drawable.ic_update),
|
||||
hint = getString(R.string.more_than_15_minutes),
|
||||
id = KEY_AUTO_UPDATE,
|
||||
content = (interval / 1000 / 60).toString()
|
||||
content = (interval / 1000 / 60).toStringIfNonZero()
|
||||
) {
|
||||
onDisplayContent {
|
||||
val interval = it.toString().toIntOrNull() ?: 0
|
||||
@@ -119,6 +119,9 @@ class ProfileEditFragment(
|
||||
|
||||
interval = content.toString().toLong() * 1000 * 60
|
||||
}
|
||||
|
||||
if ( type == Type.FILE )
|
||||
isHidden = true
|
||||
}
|
||||
|
||||
screen.restoreState(savedInstanceState)
|
||||
@@ -177,4 +180,8 @@ class ProfileEditFragment(
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private fun Long.toStringIfNonZero(): String {
|
||||
return if ( this == 0L ) "" else this.toString()
|
||||
}
|
||||
}
|
||||
@@ -71,7 +71,7 @@ object Broadcasts {
|
||||
addAction(Intents.INTENT_ACTION_CLASH_STOPPED)
|
||||
addAction(Intents.INTENT_ACTION_CLASH_STARTED)
|
||||
addAction(Intents.INTENT_ACTION_PROFILE_LOADED)
|
||||
}, Permissions.PERMISSION_ACCESS_CLASH, null)
|
||||
}, Permissions.PERMISSION_RECEIVE_BROADCASTS, null)
|
||||
|
||||
val current = RemoteUtils.detectClashRunning(application)
|
||||
if (current != clashRunning) {
|
||||
|
||||
@@ -62,7 +62,6 @@ class ProfileClient(private val service: IProfileService) {
|
||||
service.queryById(id)
|
||||
}
|
||||
|
||||
|
||||
suspend fun setActive(id: Long) = withContext(Dispatchers.IO) {
|
||||
service.setActive(id)
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<string name="append_system_dns_summary">自动追加系统 DNS 到 Clash</string>
|
||||
<string name="application_broken">应用损坏</string>
|
||||
<string name="application_name">Clash for Android</string>
|
||||
<string name="auto_update">自动更新 (秒)</string>
|
||||
<string name="auto_update">自动更新 (分钟)</string>
|
||||
<string name="behavior">行为</string>
|
||||
<string name="boot">启动</string>
|
||||
<string name="bypass_private_network">绕过私有网络</string>
|
||||
@@ -96,7 +96,7 @@
|
||||
<string name="sort_proxy">代理排序</string>
|
||||
<string name="start_clash_on_system_boot">在系统启动时启动 Clash</string>
|
||||
<string name="start_on_boot">开机时启动</string>
|
||||
<string name="start_url_provider_failure">打开 URL 提供商 失败</string>
|
||||
<string name="start_url_provider_failure">打开 URL 提供程序失败</string>
|
||||
<string name="stopped">已停止</string>
|
||||
<string name="support">支持</string>
|
||||
<string name="tap_to_start">点此启动</string>
|
||||
@@ -128,6 +128,6 @@
|
||||
<string name="profile_not_found">配置文件丢失</string>
|
||||
<string name="more_than_15_minutes">大于15分钟</string>
|
||||
<string name="loading">载入中</string>
|
||||
<string name="tips_support"><![CDATA[Clash for Android 是一个<strong>免费开源</strong>的项目, <strong>不提供</strong>任何代理服务<br />请务必<strong>不要</strong>反馈非应用自身引起的问题]]></string>
|
||||
<string name="tips_support"><![CDATA[Clash for Android 是一个<strong>免费开源</strong>的项目<br /> 我们<strong>不提供</strong>任何代理服务<br />请务必<strong>不要</strong>反馈非应用自身引起的问题]]></string>
|
||||
<string name="donate">捐赠</string>
|
||||
</resources>
|
||||
@@ -5,4 +5,5 @@
|
||||
android:label="@string/receive_clash_broadcasts"
|
||||
android:description="@string/receive_broadcasts_of_clash"
|
||||
android:protectionLevel="privileged|signature" />
|
||||
<uses-permission android:name="${applicationId}.permission.RECEIVE_BROADCASTS" />
|
||||
</manifest>
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.github.kr328.clash.common
|
||||
|
||||
object Permissions {
|
||||
val PERMISSION_ACCESS_CLASH: String
|
||||
val PERMISSION_RECEIVE_BROADCASTS: String
|
||||
get() = Global.application.packageName + ".permission.RECEIVE_BROADCASTS"
|
||||
}
|
||||
@@ -25,6 +25,10 @@ func InitCore(geoipDatabase[] byte, homeDir string, version string) {
|
||||
mmdb.LoadFromBytes(dataClone)
|
||||
C.SetHomeDir(homeDir)
|
||||
config.ApplicationVersion = version
|
||||
|
||||
Reset()
|
||||
|
||||
log.Infoln("Initialed")
|
||||
}
|
||||
|
||||
func Reset() {
|
||||
|
||||
@@ -5,36 +5,17 @@ import (
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/Dreamacro/clash/config"
|
||||
"github.com/Dreamacro/clash/constant"
|
||||
"github.com/Dreamacro/clash/hub/executor"
|
||||
"github.com/Dreamacro/clash/log"
|
||||
"github.com/kr328/cfa/tun"
|
||||
)
|
||||
|
||||
const defaultConfig = `
|
||||
log: debug
|
||||
mode: Direct
|
||||
Proxy:
|
||||
- name: "broadcast"
|
||||
type: socks5
|
||||
server: 255.255.255.255
|
||||
port: 1080
|
||||
|
||||
Proxy Group:
|
||||
- name: "select"
|
||||
type: select
|
||||
proxies: [DIRECT]
|
||||
|
||||
Rule:
|
||||
- 'MATCH,DIRECT'
|
||||
`
|
||||
|
||||
// LoadDefault - load default configure
|
||||
func LoadDefault() {
|
||||
DnsPatch = nil
|
||||
NameServersAppend = make([]string, 0)
|
||||
|
||||
defaultC, err := parseConfig([]byte(defaultConfig), constant.Path.HomeDir())
|
||||
defaultC, err := config.Parse([]byte{})
|
||||
if err != nil {
|
||||
log.Warnln("Load Default Failure " + err.Error())
|
||||
return
|
||||
|
||||
@@ -18,7 +18,7 @@ import java.io.InputStream
|
||||
object Clash {
|
||||
private val logReceivers = mutableMapOf<String, (LogEvent) -> Unit>()
|
||||
|
||||
fun init() {
|
||||
init {
|
||||
val context = Global.application
|
||||
|
||||
val bytes = context.assets.open("Country.mmdb")
|
||||
|
||||
@@ -22,6 +22,9 @@ abstract class Base(val screen: CommonUiScreen) {
|
||||
get() = field || (dependOn?.isHidden ?: false)
|
||||
set(value) {
|
||||
field = value
|
||||
|
||||
reapplyAttribute()
|
||||
|
||||
screen.postReapplyAttribute()
|
||||
}
|
||||
|
||||
|
||||
@@ -25,9 +25,9 @@ class CommonUiBuilder(val screen: CommonUiScreen) {
|
||||
textInput.id = id
|
||||
textInput.dependOn = dependOn?.run { screen.requireElement(this) }
|
||||
|
||||
setup(textInput)
|
||||
|
||||
screen.addElement(textInput)
|
||||
|
||||
textInput.setup()
|
||||
}
|
||||
|
||||
fun option(
|
||||
|
||||
@@ -91,6 +91,8 @@ class ProfileBackgroundService : BaseService() {
|
||||
requests.onReceive {
|
||||
ProfileReceiver.cancelNextUpdate(self, it)
|
||||
|
||||
queue.add(it)
|
||||
|
||||
service.commit(it, object : IStreamCallback.Stub() {
|
||||
override fun completeExceptionally(reason: String?) {
|
||||
responses.offer(it to RemoteException(reason))
|
||||
@@ -106,6 +108,8 @@ class ProfileBackgroundService : BaseService() {
|
||||
false
|
||||
}
|
||||
responses.onReceive {
|
||||
queue.remove(it.first)
|
||||
|
||||
if (it.second == null)
|
||||
sendUpdateCompleted(it.first)
|
||||
else
|
||||
|
||||
@@ -21,6 +21,9 @@ object ProfileProcessor {
|
||||
withContext(Dispatchers.IO) {
|
||||
metadata.enforceFieldValid()
|
||||
|
||||
context.resolveBaseDir(metadata.id).mkdirs()
|
||||
context.resolveProfileFile(metadata.id).parentFile?.mkdirs()
|
||||
|
||||
downloadProfile(
|
||||
context, metadata.uri,
|
||||
context.resolveProfileFile(metadata.id),
|
||||
|
||||
@@ -4,6 +4,7 @@ import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.IBinder
|
||||
import android.os.RemoteException
|
||||
import com.github.kr328.clash.common.utils.Log
|
||||
import com.github.kr328.clash.service.data.ProfileDao
|
||||
import com.github.kr328.clash.service.ipc.IStreamCallback
|
||||
import com.github.kr328.clash.service.model.ProfileMetadata
|
||||
@@ -82,7 +83,8 @@ class ProfileService : BaseService() {
|
||||
return runBlocking {
|
||||
val clonedId = generateNextId()
|
||||
|
||||
pending[clonedId] = queryMetadataById(id) ?: return@runBlocking -1L
|
||||
pending[clonedId] = queryMetadataById(id)?.copy(id = clonedId, active = false)
|
||||
?: return@runBlocking -1L
|
||||
|
||||
clonedId
|
||||
}
|
||||
@@ -117,6 +119,8 @@ class ProfileService : BaseService() {
|
||||
it.deleteRecursively()
|
||||
}
|
||||
}
|
||||
|
||||
service.broadcastProfileChanged()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,6 +151,8 @@ class ProfileService : BaseService() {
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
|
||||
ProfileReceiver.tryInitialize(this)
|
||||
|
||||
launch {
|
||||
process()
|
||||
}
|
||||
@@ -173,6 +179,8 @@ class ProfileService : BaseService() {
|
||||
ProfileProcessor.createOrUpdate(service, metadata)
|
||||
|
||||
ctx.value?.complete()
|
||||
|
||||
service.broadcastProfileChanged()
|
||||
} catch (e: Exception) {
|
||||
ctx.value?.completeExceptionally(e.message)
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ class ClashRuntime(private val context: Context) {
|
||||
modules.flatMap { it.receiveBroadcasts }.distinct().forEach {
|
||||
addAction(it)
|
||||
}
|
||||
}, Permissions.PERMISSION_ACCESS_CLASH, null)
|
||||
}, Permissions.PERMISSION_RECEIVE_BROADCASTS, null)
|
||||
|
||||
while (isActive) {
|
||||
tickerEnabled = modules.any { it.enableTicker }
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.github.kr328.clash.service.files
|
||||
import android.content.Context
|
||||
import android.os.ParcelFileDescriptor
|
||||
import android.provider.DocumentsContract
|
||||
import com.github.kr328.clash.common.utils.Log
|
||||
import com.github.kr328.clash.service.R
|
||||
import com.github.kr328.clash.service.data.ProfileDao
|
||||
import com.github.kr328.clash.service.util.resolveProfileFile
|
||||
|
||||
@@ -19,7 +19,7 @@ fun ProfileEntity.toProfileMetadata(context: Context): ProfileMetadata {
|
||||
name = name,
|
||||
type = type,
|
||||
uri = Uri.parse(uri),
|
||||
source = Uri.parse(source),
|
||||
source = source?.let { Uri.parse(it)},
|
||||
active = active,
|
||||
interval = interval,
|
||||
lastModified = lastModified
|
||||
@@ -38,7 +38,7 @@ fun ProfileMetadata.toProfileEntity(): ProfileEntity {
|
||||
name = name,
|
||||
type = type,
|
||||
uri = uri.toString(),
|
||||
source = source.toString(),
|
||||
source = source?.toString(),
|
||||
active = active,
|
||||
interval = interval,
|
||||
id = id
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
package com.github.kr328.clash.service.transact
|
||||
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
import com.github.kr328.clash.service.ipc.IStreamCallback
|
||||
|
||||
class ProfileRequest private constructor(private val bundle: Bundle) : Parcelable {
|
||||
constructor() : this(Bundle())
|
||||
constructor(parcel: Parcel) : this(
|
||||
parcel.readBundle(ProfileRequest::class.java.classLoader)
|
||||
?: throw NullPointerException("Empty bundle")
|
||||
)
|
||||
|
||||
enum class Action {
|
||||
UPDATE_OR_CREATE, REMOVE, CLEAR
|
||||
}
|
||||
|
||||
val action: Action
|
||||
get() = Action.valueOf(requireNotNull(bundle.getString(KEY_ACTION)))
|
||||
val type: Int
|
||||
get() = bundle.getInt(KEY_TYPE, -1)
|
||||
val id: Long
|
||||
get() = bundle.getLong(KEY_ID, -1)
|
||||
val name: String?
|
||||
get() = bundle.getString(KEY_NAME)
|
||||
val url: Uri?
|
||||
get() = bundle.getParcelable(KEY_URL)
|
||||
val source: Uri?
|
||||
get() = bundle.getParcelable(KEY_SOURCE)
|
||||
val interval: Long
|
||||
get() = bundle.getLong(KEY_UPDATE_INTERVAL, -1)
|
||||
val callback: IStreamCallback?
|
||||
get() = IStreamCallback.Stub.asInterface(bundle.getBinder(KEY_CALLBACK))
|
||||
|
||||
fun action(action: Action): ProfileRequest {
|
||||
return apply {
|
||||
bundle.putString(KEY_ACTION, action.toString())
|
||||
}
|
||||
}
|
||||
|
||||
fun withType(type: Int): ProfileRequest {
|
||||
return apply {
|
||||
bundle.putInt(KEY_TYPE, type)
|
||||
}
|
||||
}
|
||||
|
||||
fun withId(id: Long): ProfileRequest {
|
||||
return apply {
|
||||
bundle.putLong(KEY_ID, id)
|
||||
}
|
||||
}
|
||||
|
||||
fun withName(name: String): ProfileRequest {
|
||||
return apply {
|
||||
bundle.putString(KEY_NAME, name)
|
||||
}
|
||||
}
|
||||
|
||||
fun withURL(url: Uri): ProfileRequest {
|
||||
return apply {
|
||||
bundle.putParcelable(KEY_URL, url)
|
||||
}
|
||||
}
|
||||
|
||||
fun withSource(source: Uri?): ProfileRequest {
|
||||
return apply {
|
||||
bundle.putParcelable(KEY_SOURCE, source)
|
||||
}
|
||||
}
|
||||
|
||||
fun withUpdateInterval(interval: Long): ProfileRequest {
|
||||
return apply {
|
||||
bundle.putLong(KEY_UPDATE_INTERVAL, interval)
|
||||
}
|
||||
}
|
||||
|
||||
fun withCallback(callback: IStreamCallback.Stub): ProfileRequest {
|
||||
return apply {
|
||||
bundle.putBinder(KEY_CALLBACK, callback)
|
||||
}
|
||||
}
|
||||
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
parcel.writeBundle(bundle)
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val KEY_ACTION = "action"
|
||||
private const val KEY_ID = "id"
|
||||
private const val KEY_NAME = "name"
|
||||
private const val KEY_URL = "url"
|
||||
private const val KEY_SOURCE = "source"
|
||||
private const val KEY_TYPE = "type"
|
||||
private const val KEY_CALLBACK = "callback"
|
||||
private const val KEY_UPDATE_INTERVAL = "update_interval"
|
||||
|
||||
@JvmField
|
||||
val CREATOR = object : Parcelable.Creator<ProfileRequest> {
|
||||
override fun createFromParcel(parcel: Parcel): ProfileRequest {
|
||||
return ProfileRequest(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<ProfileRequest?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,10 +4,12 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import com.github.kr328.clash.common.Permissions
|
||||
import com.github.kr328.clash.common.ids.Intents
|
||||
import com.github.kr328.clash.common.utils.Log
|
||||
import java.lang.Exception
|
||||
|
||||
fun Context.sendBroadcastSelf(intent: Intent) {
|
||||
this.sendBroadcast(intent.setPackage(this.packageName),
|
||||
Permissions.PERMISSION_ACCESS_CLASH)
|
||||
Permissions.PERMISSION_RECEIVE_BROADCASTS)
|
||||
}
|
||||
|
||||
fun Context.broadcastProfileChanged() {
|
||||
|
||||
Reference in new issue
Block a user