Compare commits

...
10 Commits
Author SHA1 Message Date
Kr328 594949d3f0 format code & update core 2020-02-28 23:52:58 +08:00
Kr328 8fd34b5258 improve apk broken detect & fix udp crash 2020-02-28 14:00:38 +08:00
Kr328 1161482a5b fix udp crash 2020-02-28 11:19:06 +08:00
Kr328 8a123e7a0d improve network settings 2020-02-28 01:13:11 +08:00
Kr328 4ef3a20929 add vpn component detect 2020-02-28 00:32:49 +08:00
Kr328 16c2e9b694 increase refresh interval 2020-02-28 00:24:24 +08:00
Kr328 c9a9d310ef update version 2020-02-28 00:22:21 +08:00
Kr328 84996a5652 update apk broken detect 2020-02-27 16:30:57 +08:00
Kr328 115afc5735 update apk broken detect 2020-02-27 16:30:34 +08:00
Kr328 2ae75e876d fix uri case 2020-02-27 16:03:28 +08:00
12 changed files with 71 additions and 31 deletions

No files matched your search

@@ -35,8 +35,15 @@ class MainActivity : BaseActivity() {
stopClashService()
} else {
val vpnRequest = startClashService()
if (vpnRequest != null)
startActivityForResult(vpnRequest, REQUEST_CODE)
if (vpnRequest != null) {
val resolved = packageManager.resolveActivity(vpnRequest, 0)
if ( resolved != null ) {
startActivityForResult(vpnRequest, REQUEST_CODE)
}
else {
makeSnackbarException(getString(R.string.missing_vpn_component), null)
}
}
}
}
@@ -149,7 +149,10 @@ class ProfileEditActivity : BaseActivity() {
}
if (url == null || url == Uri.EMPTY ||
(url.scheme != "http" && url.scheme != "https" && url.scheme != "content")
(!url.scheme.equals("http", ignoreCase = true)
&& !url.scheme.equals("https", ignoreCase = true)
&& !url.scheme.equals("content", ignoreCase = true)
&& !url.scheme.equals("file", ignoreCase = true))
) {
Snackbar.make(rootView, R.string.invalid_url, Snackbar.LENGTH_LONG).show()
return@setOnClickListener
@@ -268,7 +268,7 @@ class ProxiesActivity : BaseActivity(), ScrollBinding.Callback {
scrollBinding.scrollMaster(selected)
}
delay(200)
delay(500)
refreshMutex.unlock()
}
@@ -19,6 +19,14 @@ class SettingsNetworkActivity : BaseActivity() {
Snackbar.make(rootView, R.string.options_unavailable, Snackbar.LENGTH_INDEFINITE).show()
}
override suspend fun onClashStopped(reason: String?) {
recreate()
}
override suspend fun onClashStarted() {
recreate()
}
override val activityLabel: CharSequence?
get() = getText(R.string.network)
}
}
@@ -72,8 +72,7 @@ suspend fun Pipeline<List<ProxyGroup>>.sort(): Pipeline<List<ProxyGroup>> {
suspend fun Pipeline<List<ProxyGroup>>.toAdapterElement(
prefixMerged: Map<ProxyEntry, ProxyMerged>,
general: General
):
List<ProxyAdapter.ProxyGroupInfo> {
): List<ProxyAdapter.ProxyGroupInfo> {
return input.map { group ->
val proxies = group.proxies.map { proxy ->
val merged = prefixMerged[ProxyEntry(group.name, proxy.name)]?.takeIf {
@@ -5,25 +5,24 @@ import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.os.Build
import android.os.Handler
import android.os.IBinder
import android.os.RemoteException
import androidx.core.content.edit
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ProcessLifecycleOwner
import com.github.kr328.clash.ApkBrokenActivity
import com.github.kr328.clash.Constants
import com.github.kr328.clash.dump.LogcatDumper
import com.github.kr328.clash.service.ClashManagerService
import com.github.kr328.clash.service.IClashManager
import com.github.kr328.clash.service.IProfileService
import com.github.kr328.clash.service.ProfileService
import com.github.kr328.clash.service.util.intent
import com.microsoft.appcenter.crashes.Crashes
import com.microsoft.appcenter.crashes.ingestion.models.ErrorAttachmentLog
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.Channel
import java.io.File
import java.util.zip.ZipFile
object Remote {
@@ -91,7 +90,11 @@ object Remote {
handler.removeMessages(0)
GlobalScope.launch {
if (!verifyApk(application)) {
val valid = withContext(Dispatchers.IO) {
verifyApk(application)
}
if (!valid) {
application.startActivity(
ApkBrokenActivity::class.intent
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
@@ -135,28 +138,45 @@ object Remote {
})
}
private suspend fun verifyApk(application: Application) = withContext(Dispatchers.IO) {
val sp = application.getSharedPreferences(
Constants.PREFERENCE_NAME_APP,
Context.MODE_PRIVATE
)
val pkg = application.packageManager.getPackageInfo(application.packageName, 0)
private fun verifyApk(application: Application): Boolean {
return try {
val sp = application.getSharedPreferences(
Constants.PREFERENCE_NAME_APP,
Context.MODE_PRIVATE
)
val pkg = application.packageManager.getPackageInfo(application.packageName, 0)
if (sp.getLong(Constants.PREFERENCE_KEY_LAST_INSTALL, 0) == pkg.lastUpdateTime)
return@withContext true
if (sp.getLong(Constants.PREFERENCE_KEY_LAST_INSTALL, 0) == pkg.lastUpdateTime)
return true
val info = application.applicationInfo
val sources =
info.splitSourceDirs ?: arrayOf(info.sourceDir) ?: return@withContext false
val info = application.applicationInfo
val sources =
info.splitSourceDirs ?: arrayOf(info.sourceDir) ?: return false
for (apk in sources) {
if (ZipFile(apk).entries().asSequence().any { it.name.endsWith("libgojni.so") }) {
val regexNativeLibrary = Regex("lib/(\\S+)/libgojni.so")
val availableAbi = Build.SUPPORTED_ABIS.toSet()
val apkAbi =
sources
.asSequence()
.filter { File(it).exists() }
.flatMap { ZipFile(it).entries().asSequence() }
.mapNotNull { regexNativeLibrary.matchEntire(it.name) }
.mapNotNull { it.groups[1]?.value }
.toSet()
if (availableAbi.intersect(apkAbi).isNotEmpty()) {
sp.edit {
putLong(Constants.PREFERENCE_KEY_LAST_INSTALL, pkg.lastUpdateTime)
}
return@withContext true
true
} else {
false
}
} catch (e: Exception) {
Crashes.trackError(e)
false
}
return@withContext false
}
}
+1
View File
@@ -130,4 +130,5 @@
<string name="learn_more_about_split_apks">了解更多关于分包机制</string>
<string name="reinstall_from_google_play">重新从 Google Play 安装</string>
<string name="download_from_github_releases">从 Github Release 下载</string>
<string name="missing_vpn_component">系统 VPN 组件缺失</string>
</resources>
+1
View File
@@ -172,4 +172,5 @@
<string name="github_releases_url" translatable="false">https://github.com/Kr328/ClashForAndroid/releases</string>
<string name="format_proxy_group_title" translatable="false">%s - %s</string>
<string name="missing_vpn_component">Missing VPN Components</string>
</resources>
+2 -2
View File
@@ -8,8 +8,8 @@ buildscript {
gMinSdkVersion = 24
gTargetSdkVersion = 29
gVersionCode = 10107
gVersionName = "1.1.7"
gVersionCode = 10110
gVersionName = "1.1.10"
gKotlinVersion = '1.3.61'
gKotlinCoroutineVersion = '1.3.3'
@@ -64,7 +64,8 @@ class ProfileProcessor(private val context: Context) {
target.parentFile?.mkdirs()
baseDir.mkdirs()
if (source.scheme == "content" || source.scheme == "file") {
if (source.scheme.equals("content", ignoreCase = true)
|| source.scheme.equals("file", ignoreCase = true)) {
val parcelFileDescriptor = context.contentResolver.openFileDescriptor(source, "r")
?: throw FileNotFoundException("Unable to open file $source")
@@ -186,7 +186,7 @@ class ProfileService : BaseService() {
ClashProfileEntity(
requireNotNull(request.name),
requireNotNull(request.type),
requireNotNull(request.url).toString().toLowerCase(Locale.getDefault()),
requireNotNull(request.url).toString(),
request.source?.toString(),
false,
0,