Compare commits

..

19 Commits

Author SHA1 Message Date
Kr328
e958e7f675 Update 03-bug-report-zh-cn.md 2020-03-22 20:45:20 +08:00
Kr328
68113e694e update issue template 2020-03-22 13:04:50 +08:00
Kr328
f500596621 update README.md 2020-03-21 16:11:03 +08:00
Kr328
df5bafd0bb update README.md 2020-03-21 16:01:35 +08:00
Kr328
01fe9deb20 update issue template 2020-03-20 13:16:43 +08:00
Kr328
4e44298e98 sorted github issue 2020-03-19 19:46:12 +08:00
Kr328
a7c3a05c23 add application info request 2020-03-19 19:09:20 +08:00
Kr328
05fa36497b rename issues template file 2020-03-19 18:56:41 +08:00
Kr328
e6f8ae265e Add issue templates 2020-03-19 18:53:05 +08:00
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
18 changed files with 197 additions and 39 deletions

View File

@@ -0,0 +1,43 @@
---
name: "[English] Bug report"
about: Create a report to help us improve
title: "[BUG] "
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Logs**
if applicable, add logs to help detect problem
**Device Info (please complete the following information):**
- Device: [e.g. Pixel 4]
- ROM: [e.g: AOSP]
- ROM Version:
- Android Version [e.g. Oreo]
**Application Info (please complete the following information):**
- Version: [e.g. 1.1.10]
- Apk File Name: [e.g. app-release-arm64-v8a.apk]
- Distribution Channel: [e.g. Google Play]
**Additional context**
Add any other context about the problem here.

View File

@@ -0,0 +1,20 @@
---
name: "[English] Feature request"
about: Suggest an idea for this app
title: "[Feature Request] "
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@@ -0,0 +1,41 @@
---
name: "[简体中文] 创建错误报告"
about: 创建错误报告以帮助我们改进应用
title: "[BUG] "
labels: ''
assignees: ''
---
**描述出现的错误**
请简洁的描述你遇到的错误
**如何复现该错误**
复现步骤:
1. ...
2. ...
3. ...
4. ...
**预期行为**
清晰简单的描述你预期的应用应该表现的行为
**屏幕截图**
如果适用, 上传屏幕截图以帮助描述错误
**日志**
如果适用, 上传日志以帮助侦测错误
**设备信息 (请完成一下信息):**
- 机型: [例如: Pixel 4]
- 系统/ROM: [例如: MIUI 11]
- Android 版本 [例如: Oreo]
- ROM版本 [例如: 20.3.19]
**应用信息**
- 版本: [例如: 1.1.10]
- 安装包文件名: [例如: app-release-arm64-v8a.apk]
- 应用来源: [例如: Google Play]
**附加信息**
其他的可能与改错误相关的信息

View File

@@ -0,0 +1,17 @@
---
name: "[简体中文] 功能请求"
about: 你希望的能够在应用中增加的功能
title: "[Feature Request] "
labels: ''
assignees: ''
---
**功能描述**
请清晰的描述你想要的功能
**描述你希望的实现方式**
清晰的描述应用应该如何实现该功能
**附加信息**
其他的与改功能相关的附加信息

1
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1 @@
blank_issues_enabled: false

View File

@@ -1,10 +1,8 @@
## Clash for Android
A GUI for [clash](https://github.com/Dreamacro/clash) on Android
> NOTICE: Early testing currently
A Graphical user interface of [clash](https://github.com/Dreamacro/clash) for Android
<a href="https://play.google.com/store/apps/details?id=com.github.kr328.clash&pcampaignid=pcampaignidMKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1"><img width="200px" alt="Get it on Google Play" src="https://play.google.com/intl/en_us/badges/static/images/badges/en_badge_web_generic.png"/></a> or [Releases](https://github.com/Kr328/ClashForAndroid/releases)
### Feature
@@ -15,9 +13,7 @@ Fully feature of [clash](https://github.com/Dreamacro/clash) ~~(Exclude `externa
### Requirement
* Android 7.0+
* `arm64` or `x86_64` architecture
* `armeabi-v7a` , `arm64-v8a`, `x86` or `x86_64` Architecture
### License
@@ -39,7 +35,7 @@ See also [PRIVACY_POLICY.md](./PRIVACY_POLICY.md)
git submodule update --init --recursive
```
2. Install `Android SDK (include JDK)` ,`Android NDK` and `Golang`
2. Install `JDK 1.8`, `Android SDK` ,`Android NDK` and `Golang`
3. Configure `local.properties`

View File

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

View File

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

View File

@@ -268,7 +268,7 @@ class ProxiesActivity : BaseActivity(), ScrollBinding.Callback {
scrollBinding.scrollMaster(selected)
}
delay(200)
delay(500)
refreshMutex.unlock()
}

View File

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

View File

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

View File

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

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>

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>

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'

View File

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

View File

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