1
0
世界 4 жил өмнө
parent
commit
a910ab6b8f
28 өөрчлөгдсөн 84 нэмэгдсэн , 38 устгасан
  1. 4 4
      .github/workflows/debug.yml
  2. 4 11
      app/src/main/AndroidManifest.xml
  3. 7 2
      app/src/main/java/io/nekohasekai/sagernet/SagerNet.kt
  4. 1 1
      app/src/main/java/io/nekohasekai/sagernet/bg/GuardedProcessPool.kt
  5. 1 1
      app/src/main/java/io/nekohasekai/sagernet/bg/ServiceNotification.kt
  6. 0 1
      app/src/main/java/io/nekohasekai/sagernet/bg/SubscriptionUpdater.kt
  7. 2 0
      app/src/main/java/io/nekohasekai/sagernet/bg/proto/V2RayInstance.kt
  8. 4 3
      app/src/main/java/io/nekohasekai/sagernet/fmt/hysteria/HysteriaFmt.kt
  9. 1 1
      app/src/main/java/io/nekohasekai/sagernet/fmt/internal/ConfigBean.java
  10. 1 1
      app/src/main/java/io/nekohasekai/sagernet/fmt/naive/NaiveFmt.kt
  11. 4 2
      app/src/main/java/io/nekohasekai/sagernet/fmt/v2ray/V2RayConfig.java
  12. 1 1
      app/src/main/java/io/nekohasekai/sagernet/ktx/Browsers.kt
  13. 1 1
      app/src/main/java/io/nekohasekai/sagernet/ui/ThemedActivity.kt
  14. 1 1
      app/src/main/java/io/nekohasekai/sagernet/ui/profile/TrojanGoSettingsActivity.kt
  15. 2 0
      app/src/main/java/io/nekohasekai/sagernet/utils/PackageCache.kt
  16. 2 0
      app/src/main/java/io/nekohasekai/sagernet/widget/AutoCollapseTextView.kt
  17. 1 0
      app/src/main/res/layout/layout_about.xml
  18. 2 1
      app/src/main/res/layout/layout_apps_item.xml
  19. 2 1
      app/src/main/res/layout/layout_asset_item.xml
  20. 1 1
      app/src/main/res/menu/add_route_menu.xml
  21. 1 1
      app/src/main/res/menu/import_asset_menu.xml
  22. 1 1
      app/src/main/res/menu/per_app_proxy_menu.xml
  23. 1 1
      app/src/main/res/menu/profile_config_menu.xml
  24. 0 0
      app/src/main/res/values-in/strings.xml
  25. 1 0
      buildSrc/src/main/kotlin/Helpers.kt
  26. 1 1
      external/editorkit
  27. 1 1
      external/termux-view
  28. 36 0
      lint.xml

+ 4 - 4
.github/workflows/debug.yml

@@ -270,8 +270,8 @@ jobs:
           echo "ndk.dir=${ANDROID_HOME}/ndk/21.4.7075529" >> local.properties
           ./run init action library
           ./run lib shadowsocks_libev
-  build:
-    name: Gradle Build
+  Lint:
+    name: Android Lint
     runs-on: ubuntu-latest
     needs:
       - libcore
@@ -308,11 +308,11 @@ jobs:
         with:
           path: ~/.gradle
           key: gradle-${{ hashFiles('**/*.gradle.kts') }}
-      - name: Debug Build
+      - name: Android Lint
         env:
           BUILD_PLUGIN: none
         run: |
           echo "sdk.dir=${ANDROID_HOME}" > local.properties
           echo "ndk.dir=${ANDROID_HOME}/ndk/21.4.7075529" >> local.properties
           ./run init action library
-          ./gradlew app:assembleOssDebug
+          ./gradlew :app:lint

+ 4 - 11
app/src/main/AndroidManifest.xml

@@ -33,6 +33,9 @@
     <uses-feature
         android:name="android.hardware.camera"
         android:required="false" />
+    <uses-feature
+        android:name="android.hardware.camera.autofocus"
+        android:required="false" />
 
     <queries>
         <intent>
@@ -44,10 +47,10 @@
     </queries>
 
     <application
-        android:banner="@mipmap/ic_launcher"
         android:name="io.nekohasekai.sagernet.SagerNet"
         android:allowBackup="true"
         android:autoRevokePermissions="allowed"
+        android:banner="@mipmap/ic_launcher"
         android:extractNativeLibs="true"
         android:fullBackupContent="@xml/backup_descriptor"
         android:fullBackupOnly="true"
@@ -342,16 +345,6 @@
             android:name="androidx.room.MultiInstanceInvalidationService"
             android:process=":bg" />
 
-        <service
-            android:name="androidx.work.multiprocess.RemoteWorkManagerService"
-            android:process=":bg"
-            tools:replace="android:process" />
-
-        <service
-            android:name="androidx.work.impl.background.systemjob.SystemJobService"
-            android:process=":bg"
-            tools:replace="android:process" />
-
     </application>
 
 </manifest>

+ 7 - 2
app/src/main/java/io/nekohasekai/sagernet/SagerNet.kt

@@ -21,6 +21,7 @@
 
 package io.nekohasekai.sagernet
 
+import android.annotation.SuppressLint
 import android.app.*
 import android.app.admin.DevicePolicyManager
 import android.content.ClipData
@@ -123,6 +124,7 @@ class SagerNet : Application(),
             .build()
     }
 
+    @SuppressLint("InlinedApi")
     companion object {
 
         @Volatile
@@ -141,9 +143,12 @@ class SagerNet : Application(),
         val configureIntent: (Context) -> PendingIntent by lazy {
             {
                 PendingIntent.getActivity(
-                    it, 0, Intent(
+                    it,
+                    0,
+                    Intent(
                         application, MainActivity::class.java
-                    ).setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT), PendingIntent.FLAG_IMMUTABLE
+                    ).setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT),
+                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) PendingIntent.FLAG_IMMUTABLE else 0
                 )
             }
         }

+ 1 - 1
app/src/main/java/io/nekohasekai/sagernet/bg/GuardedProcessPool.kt

@@ -62,7 +62,7 @@ class GuardedProcessPool(private val onFatal: suspend (IOException) -> Unit) : C
 
         @DelicateCoroutinesApi
         suspend fun looper(onRestartCallback: (suspend () -> Unit)?) {
-            var running = true
+            var running = false
             val cmdName = File(cmd.first()).nameWithoutExtension
             val exitChannel = Channel<Int>()
             try {

+ 1 - 1
app/src/main/java/io/nekohasekai/sagernet/bg/ServiceNotification.kt

@@ -135,7 +135,7 @@ class ServiceNotification(
                 service,
                 0,
                 Intent(Action.CLOSE).setPackage(service.packageName),
-                PendingIntent.FLAG_IMMUTABLE
+                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) PendingIntent.FLAG_IMMUTABLE else 0
             )
         ).apply {
             setShowsUserInterface(false)

+ 0 - 1
app/src/main/java/io/nekohasekai/sagernet/bg/SubscriptionUpdater.kt

@@ -82,7 +82,6 @@ object SubscriptionUpdater {
             if (subscriptions.isNotEmpty()) for (profile in subscriptions) {
                 val subscription = profile.subscription!!
 
-                val delay = subscription.autoUpdateDelay
                 if (((System.currentTimeMillis() / 1000).toInt() - subscription.lastUpdated) < subscription.autoUpdateDelay * 60) {
                     continue
                 }

+ 2 - 0
app/src/main/java/io/nekohasekai/sagernet/bg/proto/V2RayInstance.kt

@@ -19,6 +19,7 @@
 
 package io.nekohasekai.sagernet.bg.proto
 
+import android.annotation.SuppressLint
 import android.os.Build
 import android.os.SystemClock
 import android.webkit.WebResourceError
@@ -200,6 +201,7 @@ abstract class V2RayInstance(
         loadConfig()
     }
 
+    @SuppressLint("SetJavaScriptEnabled")
     override fun launch() {
         val context = if (Build.VERSION.SDK_INT < 24 || SagerNet.user.isUserUnlocked) SagerNet.application else SagerNet.deviceStorage
 

+ 4 - 3
app/src/main/java/io/nekohasekai/sagernet/fmt/hysteria/HysteriaFmt.kt

@@ -22,12 +22,13 @@ package io.nekohasekai.sagernet.fmt.hysteria
 import cn.hutool.core.util.NumberUtil
 import cn.hutool.json.JSONObject
 import io.nekohasekai.sagernet.fmt.LOCALHOST
+import io.nekohasekai.sagernet.ktx.wrapUri
 import java.io.File
 
 fun JSONObject.parseHysteria(): HysteriaBean {
     return HysteriaBean().apply {
-        serverAddress = getStr("server").substringBefore(":")
-        serverPort = getStr("server").substringAfter(":")
+        serverAddress = getStr("server").substringBeforeLast(":")
+        serverPort = getStr("server").substringAfterLast(":")
             .takeIf { NumberUtil.isInteger(it) }
             ?.toInt() ?: 443
         uploadMbps = getInt("up_mbps")
@@ -52,7 +53,7 @@ fun JSONObject.parseHysteria(): HysteriaBean {
 
 fun HysteriaBean.buildHysteriaConfig(port: Int, cacheFile: (() -> File)?): String {
     return JSONObject().also {
-        it["server"] = "$serverAddress:$serverPort"
+        it["server"] = wrapUri()
         it["up_mbps"] = uploadMbps
         it["down_mbps"] = downloadMbps
         it["socks5"] = JSONObject(mapOf("listen" to "$LOCALHOST:$port"))

+ 1 - 1
app/src/main/java/io/nekohasekai/sagernet/fmt/internal/ConfigBean.java

@@ -72,7 +72,7 @@ public class ConfigBean extends InternalBean {
         return KryoConverters.deserialize(new ConfigBean(), KryoConverters.serialize(this));
     }
 
-    public static final Creator<ConfigBean> ConfigBean = new CREATOR<ConfigBean>() {
+    public static final Creator<ConfigBean> CREATOR = new CREATOR<ConfigBean>() {
         @NonNull
         @Override
         public ConfigBean newInstance() {

+ 1 - 1
app/src/main/java/io/nekohasekai/sagernet/fmt/naive/NaiveFmt.kt

@@ -46,7 +46,7 @@ fun parseNaive(link: String): NaiveBean {
 
 fun NaiveBean.toUri(proxyOnly: Boolean = false): String {
     val builder = linkBuilder()
-        .host(serverAddress)
+        .host(finalAddress)
         .port(finalPort)
     if (username.isNotBlank()) {
         builder.username(username)

+ 4 - 2
app/src/main/java/io/nekohasekai/sagernet/fmt/v2ray/V2RayConfig.java

@@ -25,11 +25,13 @@ import com.google.gson.annotations.SerializedName;
 import com.google.gson.stream.JsonToken;
 
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
 
 import io.nekohasekai.sagernet.fmt.gson.JsonLazyInterface;
 import io.nekohasekai.sagernet.fmt.gson.JsonOr;
+import kotlin.text.StringsKt;
 
 @SuppressWarnings({"SpellCheckingInspection", "unused", "RedundantSuppression"})
 public class V2RayConfig {
@@ -228,7 +230,7 @@ public class V2RayConfig {
         @Nullable
         @Override
         protected Class<? extends InboundConfigurationObject> getType() {
-            switch (ctx.protocol.toLowerCase()) {
+            switch (ctx.protocol.toLowerCase(Locale.ROOT)) {
                 case "dokodemo-door":
                     return DokodemoDoorInboundConfigurationObject.class;
                 case "http":
@@ -445,7 +447,7 @@ public class V2RayConfig {
         @Nullable
         @Override
         protected Class<? extends OutboundConfigurationObject> getType() {
-            switch (ctx.protocol.toLowerCase()) {
+            switch (ctx.protocol.toLowerCase(Locale.ROOT)) {
                 case "blackhole":
                     return BlackholeOutboundConfigurationObject.class;
                 case "dns":

+ 1 - 1
app/src/main/java/io/nekohasekai/sagernet/ktx/Browsers.kt

@@ -1,4 +1,4 @@
-/******************************************************************************
+  /******************************************************************************
  *                                                                            *
  * Copyright (C) 2021 by nekohasekai <[email protected]>             *
  *                                                                            *

+ 1 - 1
app/src/main/java/io/nekohasekai/sagernet/ui/ThemedActivity.kt

@@ -71,6 +71,6 @@ abstract class ThemedActivity : AppCompatActivity {
             maxLines = 10
         }
     }
-    internal open fun snackbarInternal(text: CharSequence): Snackbar = TODO()
+    internal open fun snackbarInternal(text: CharSequence): Snackbar = throw NotImplementedError()
 
 }

+ 1 - 1
app/src/main/java/io/nekohasekai/sagernet/ui/profile/TrojanGoSettingsActivity.kt

@@ -159,7 +159,7 @@ class TrojanGoSettingsActivity : ProfileSettingsActivity<TrojanGoBean>(),
         pluginConfigure = findPreference(Key.SERVER_PLUGIN_CONFIGURE)!!
         pluginConfigure.setOnBindEditTextListener(EditTextPreferenceModifiers.Monospace)
         pluginConfigure.onPreferenceChangeListener = this@TrojanGoSettingsActivity
-        pluginConfiguration = PluginConfiguration(DataStore.serverPlugin ?: "")
+        pluginConfiguration = PluginConfiguration(DataStore.serverPlugin)
         initPlugins()
     }
 

+ 2 - 0
app/src/main/java/io/nekohasekai/sagernet/utils/PackageCache.kt

@@ -20,6 +20,7 @@
 package io.nekohasekai.sagernet.utils
 
 import android.Manifest
+import android.annotation.SuppressLint
 import android.content.pm.ApplicationInfo
 import android.content.pm.PackageInfo
 import android.content.pm.PackageManager
@@ -46,6 +47,7 @@ object PackageCache {
         loaded.unlock()
     }
 
+    @SuppressLint("InlinedApi")
     fun reload() {
         installedPackages = app.packageManager.getInstalledPackages(PackageManager.GET_PERMISSIONS or PackageManager.MATCH_UNINSTALLED_PACKAGES)
             .filter {

+ 2 - 0
app/src/main/java/io/nekohasekai/sagernet/widget/AutoCollapseTextView.kt

@@ -21,6 +21,7 @@
 
 package io.nekohasekai.sagernet.widget
 
+import android.annotation.SuppressLint
 import android.content.Context
 import android.graphics.Rect
 import android.util.AttributeSet
@@ -50,6 +51,7 @@ class AutoCollapseTextView @JvmOverloads constructor(
         } catch (e: IndexOutOfBoundsException) {
         }
 
+    @SuppressLint("ClickableViewAccessibility")
     override fun onTouchEvent(event: MotionEvent?) = try {
         super.onTouchEvent(event)
     } catch (e: IndexOutOfBoundsException) {

+ 1 - 0
app/src/main/res/layout/layout_about.xml

@@ -87,6 +87,7 @@
                         android:layout_marginTop="16dp"
                         android:textAppearance="?attr/textAppearanceBody2"
                         android:textColor="?android:textColorSecondary"
+                        android:textIsSelectable="true"
                         android:textSize="12sp" />
 
                 </LinearLayout>

+ 2 - 1
app/src/main/res/layout/layout_apps_item.xml

@@ -7,7 +7,8 @@
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:layout_margin="4dp"
-    app:cardElevation="2dp">
+    app:cardElevation="2dp"
+    tools:ignore="SelectableText">
 
     <LinearLayout
         android:layout_width="match_parent"

+ 2 - 1
app/src/main/res/layout/layout_asset_item.xml

@@ -28,7 +28,8 @@
         <LinearLayout
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:orientation="horizontal">
+            android:orientation="horizontal"
+            android:baselineAligned="false">
 
             <LinearLayout
                 android:layout_width="0dp"

+ 1 - 1
app/src/main/res/menu/add_route_menu.xml

@@ -5,7 +5,7 @@
         android:id="@+id/action_new_route"
         android:icon="@drawable/ic_baseline_add_road_24"
         android:title="@string/route_add"
-        app:showAsAction="always" />
+        app:showAsAction="ifRoom" />
     <item
         android:id="@+id/action_reset_route"
         android:title="@string/route_reset"

+ 1 - 1
app/src/main/res/menu/import_asset_menu.xml

@@ -6,5 +6,5 @@
         android:id="@+id/action_import_file"
         android:icon="@drawable/ic_action_note_add"
         android:title="@string/action_import_file"
-        app:showAsAction="ifRoom" />
+        app:showAsAction="always" />
 </menu>

+ 1 - 1
app/src/main/res/menu/per_app_proxy_menu.xml

@@ -21,5 +21,5 @@
         android:id="@+id/action_import_clipboard"
         android:icon="?attr/actionModePasteDrawable"
         android:title="@string/action_import"
-        app:showAsAction="ifRoom" />
+        app:showAsAction="always" />
 </menu>

+ 1 - 1
app/src/main/res/menu/profile_config_menu.xml

@@ -5,7 +5,7 @@
           android:title="@string/delete"
           android:icon="@drawable/ic_action_delete"
           android:alphabeticShortcut="d"
-          app:showAsAction="always"/>
+          app:showAsAction="ifRoom"/>
     <item android:id="@+id/action_apply"
           android:title="@string/apply"
           android:icon="@drawable/ic_action_done"

+ 0 - 0
app/src/main/res/values-id/strings.xml → app/src/main/res/values-in/strings.xml


+ 1 - 0
buildSrc/src/main/kotlin/Helpers.kt

@@ -108,6 +108,7 @@ fun Project.setupCommon() {
             isShowAll = true
             isCheckAllWarnings = true
             isCheckReleaseBuilds = false
+            isWarningsAsErrors = true
             htmlOutput = project.file("build/lint.html")
         }
         packagingOptions {

+ 1 - 1
external/editorkit

@@ -1 +1 @@
-Subproject commit 1c3edebe8693b9435b7140759a91bbc739edd8dc
+Subproject commit e7d1d0dca2c3e9b313f28dc34df1e12282f89206

+ 1 - 1
external/termux-view

@@ -1 +1 @@
-Subproject commit 1672998d713c89bffd2ccfa7f8747849e8eee71d
+Subproject commit e0f4525b4fe6f8c9d5cad9d94d5e10fe208310f0

+ 36 - 0
lint.xml

@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<lint>
+    <issue id="UnusedAttribute" severity="ignore" />
+    <issue id="UnknownNullness" severity="ignore" />
+    <issue id="DiscouragedPrivateApi" severity="ignore" />
+    <issue id="Typos" severity="ignore" />
+    <issue id="RtlSymmetry" severity="ignore" />
+    <issue id="ContentDescription" severity="ignore" />
+    <issue id="UnusedResources" severity="ignore" />
+    <issue id="VectorRaster" severity="ignore" />
+
+    <issue id="StringFormatInvalid" severity="ignore" />
+    <issue id="Untranslatable" severity="ignore" />
+    <issue id="ImpliedQuantity" severity="ignore" />
+    <issue id="PluralsCandidate" severity="ignore" />
+    <issue id="DuplicateStrings" severity="ignore" />
+    <issue id="TypographyQuotes" severity="ignore" />
+
+    <issue id="SelectableText" severity="ignore" />
+    <issue id="InsecureBaseConfiguration" severity="ignore" />
+    <issue id="NotifyDataSetChanged" severity="ignore" />
+    <issue id="UselessParent" severity="ignore" />
+    <issue id="SyntheticAccessor" severity="ignore" />
+    <issue id="UselessLeaf" severity="ignore" />
+    <issue id="UnusedIds" severity="ignore" />
+    <issue id="ConvertToWebp" severity="ignore" />
+    <issue id="SetTextI18n" severity="ignore" />
+    <issue id="HardcodedText" severity="ignore" />
+    <issue id="RtlHardcoded" severity="ignore" />
+    <issue id="MissingTranslation" severity="ignore" />
+    <issue id="ExtraTranslation" severity="ignore" />
+    <issue id="RestrictedApi" severity="ignore" />
+
+    <issue id="InvalidPackage" severity="ignore" />
+    <issue id="TrustAllX509TrustManager" severity="ignore" />
+</lint>