7 Commits

Author SHA1 Message Date
zeus 3ba7721091 测试的 URL 配置地址: https://vungles.com/api/test/config 测试账号: binance3980@gmail.com Tinkl123
测试的 URL 配置地址: https://vungles.com/api/test/config
测试账号:
binance3980@gmail.com
Tinkl123
2025-07-18 15:08:34 +08:00
zeus 98bb9235aa Android 修复首页图片错位的问题
修复首页图片错位的问题
2025-07-18 15:04:21 +08:00
zeus 855b17c2ee 修复 Android 版本编译出错问题,详细请看https://github.com/nicolastinkl/UUVPN/issues
修复 Android 版本编译出错问题,详细请看https://github.com/nicolastinkl/UUVPN/issues
2025-07-18 14:27:58 +08:00
Zeus 3d946b66ab Update README.md 2025-04-08 19:54:35 +08:00
Zeus 81baa8ccf6 Merge pull request #35 from Stevenchou1898/patch-2
Update BaseListActivity.kt
2025-04-08 19:52:55 +08:00
Stevenchou1898 3a944a7aeb Update BaseListActivity.kt
*注释掉一些不使用的导入
*重构 初始化与列表数据更新 大部分代码为多个函数
2025-04-05 21:21:39 -07:00
Zeus 37723c3fca Update README.md 2025-03-25 20:02:19 +08:00
14 changed files with 312 additions and 284 deletions
+1
View File
@@ -139,3 +139,4 @@ app.*.symbols
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
!/dev/ci/**/Gemfile.lock !/dev/ci/**/Gemfile.lock
!.vscode/settings.json !.vscode/settings.json
/Android-kotlin-Code/core/.cxx
+11
View File
@@ -8,6 +8,8 @@
- Android 7.0+ (recommend) - Android 7.0+ (recommend)
- `armeabi-v7a` , `arm64-v8a`, `x86` or `x86_64` Architecture - `armeabi-v7a` , `arm64-v8a`, `x86` or `x86_64` Architecture
### Build ### Build
1. Update submodules 1. Update submodules
@@ -67,6 +69,15 @@ Please read 服务器配置+Kotlin-Android 文档教程.docx
} }
``` ```
![alt text](telegram-cloud-photo-size-5-6327623898581027724-y.jpg)
```
测试的 URL 配置地址: https://vungles.com/api/test/config
测试账号:
binance3980@gmail.com
Tinkl123
```
上面字段的意思: 上面字段的意思:
以下是您提供的 JSON 配置文件的字段解释: 以下是您提供的 JSON 配置文件的字段解释:
@@ -45,7 +45,10 @@ android {
externalNativeBuild { externalNativeBuild {
cmake { cmake {
// 设置cmake版本
// version = "3.31.6" //macos下不需要指定 cmake 的版本信息
path = file("src/main/cpp/CMakeLists.txt") path = file("src/main/cpp/CMakeLists.txt")
} }
} }
} }
@@ -1,47 +1,57 @@
cmake_minimum_required(VERSION 3.0) cmake_minimum_required(VERSION 3.0)
# 获取git hash # 获取git hash
message(STATUS "CMAKE_CURRENT_SOURCE_DIR= ${CMAKE_CURRENT_SOURCE_DIR}") message(STATUS "CMAKE_CURRENT_SOURCE_DIR= ${CMAKE_CURRENT_SOURCE_DIR}")
execute_process( execute_process(
COMMAND git submodule foreach git log -1 --format=%H COMMAND git submodule foreach git log -1 --format=%H
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_VARIABLE COMMIT_HASH OUTPUT_VARIABLE COMMIT_HASH
) )
string(REPLACE "\n" ";" COMMIT_HASH "${COMMIT_HASH}")
list(GET COMMIT_HASH 1 COMMIT_HASH)
string (REGEX REPLACE "[\n\t\r]" "" COMMIT_HASH ${COMMIT_HASH})
string(SUBSTRING ${COMMIT_HASH} 0 7 COMMIT_HASH)
message(STATUS "git hash= ${COMMIT_HASH}")
# 获取分支名称 # 判断是否获取到了git hash值(规避如因项目目录非git repository等原因产生的获取异常而中断build)
execute_process( string(LENGTH ${COMMIT_HASH} OUTPUT_VARIABLE COMMIT_HASH_LENGTH)
string(COMPARE LESS ${COMMIT_HASH_LENGTH} "40" OUTPUT_VARIABLE GIT_HASH_COMPARISON_RESULT)
if(NOT ${GIT_HASH_COMPARISON_RESULT})
string(REPLACE "\n" ";" COMMIT_HASH "${COMMIT_HASH}")
list(GET COMMIT_HASH 1 COMMIT_HASH)
string (REGEX REPLACE "[\n\t\r]" "" COMMIT_HASH ${COMMIT_HASH})
#string(SUBSTRING ${COMMIT_HASH} 0 7 COMMIT_HASH)
message(STATUS "git hash= ${COMMIT_HASH}")
# 获取git分支名称
execute_process(
COMMAND git submodule foreach git branch -r --contains ${COMMIT_HASH} COMMAND git submodule foreach git branch -r --contains ${COMMIT_HASH}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_VARIABLE CURRENT_BRANCH OUTPUT_VARIABLE CURRENT_BRANCH
) )
string(REPLACE "\n" ";" CURRENT_BRANCH "${CURRENT_BRANCH}")
list(GET CURRENT_BRANCH 1 CURRENT_BRANCH)
string (REGEX REPLACE "origin/" "" CURRENT_BRANCH ${CURRENT_BRANCH} "")
string (REGEX REPLACE "[\n\t\r]" "" CURRENT_BRANCH ${CURRENT_BRANCH} "")
#string(SUBSTRING ${CURRENT_BRANCH} 0 8 CURRENT_BRANCH)
message(STATUS "git current branch = ${CURRENT_BRANCH}")
# 获取生成时间 string(REPLACE "\n" ";" CURRENT_BRANCH "${CURRENT_BRANCH}")
string(TIMESTAMP COMPILE_TIME "%y%m%d") list(GET CURRENT_BRANCH 1 CURRENT_BRANCH)
string (REGEX REPLACE "[\n\t\r]" "" COMPILE_TIME ${COMPILE_TIME}) string (REGEX REPLACE "origin/" "" CURRENT_BRANCH ${CURRENT_BRANCH} "")
string(REGEX REPLACE "\"" "" COMPILE_TIME ${COMPILE_TIME}) string (REGEX REPLACE "[\n\t\r]" "" CURRENT_BRANCH ${CURRENT_BRANCH} "")
string(SUBSTRING ${CURRENT_BRANCH} 0 8 CURRENT_BRANCH)
message(STATUS "git current branch = ${CURRENT_BRANCH}")
# 生成版本信息 # 获取生成时间
set(GIT_VERSION "${CURRENT_BRANCH}_${COMMIT_HASH}_${COMPILE_TIME}") string(TIMESTAMP COMPILE_TIME "%y%m%d")
message(STATUS "version info = ${GIT_VERSION}") string (REGEX REPLACE "[\n\t\r]" "" COMPILE_TIME ${COMPILE_TIME})
string(REGEX REPLACE "\"" "" COMPILE_TIME ${COMPILE_TIME})
# 去除空格 # 生成版本信息
string(REGEX REPLACE "[ ]+" "" GIT_VERSION "${GIT_VERSION}") set(GIT_VERSION "${CURRENT_BRANCH}_${COMMIT_HASH}_${COMPILE_TIME}")
message(STATUS "version info = ${GIT_VERSION}")
# 去除空格
string(REGEX REPLACE "[ ]+" "" GIT_VERSION "${GIT_VERSION}")
else()
message(AUTHOR_WARNING "Unable to get git hash, but build will continue.")
endif()
# 保存变量到文件 # 保存变量到文件
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/version.h.in ${CMAKE_CURRENT_SOURCE_DIR}/version.h @ONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/version.h.in ${CMAKE_CURRENT_SOURCE_DIR}/version.h @ONLY)
#设置项目名称与语言类别(必)
project(clash-bridge C) project(clash-bridge C)
@@ -5,7 +5,7 @@
* 当前编译core版本号 * 当前编译core版本号
*/ */
#define GIT_VERSION _920e728_241219 #define GIT_VERSION
#define make_Str(x) #x #define make_Str(x) #x
#define make_String(x) make_Str(x) #define make_String(x) make_Str(x)
+1 -1
View File
@@ -32,6 +32,6 @@ dependencies {
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0") implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
implementation("com.github.bumptech.glide:glide:4.16.0") implementation("com.github.bumptech.glide:glide:4.16.0")
annotationProcessor("com.github.bumptech.glide:compiler:4.15.1") kapt("com.github.bumptech.glide:compiler:4.15.1")
} }
@@ -5,7 +5,7 @@ import android.content.res.Configuration
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import android.view.WindowManager // import android.view.WindowManager
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
@@ -20,16 +20,16 @@ import com.github.kr328.clash.design.adapter.PlanDataAdapter
import com.github.kr328.clash.design.adapter.TicketDetailAdapter import com.github.kr328.clash.design.adapter.TicketDetailAdapter
import com.github.kr328.clash.design.adapter.TicketsDataAdapter import com.github.kr328.clash.design.adapter.TicketsDataAdapter
import com.github.kr328.clash.design.databinding.ActivityBaseListBinding import com.github.kr328.clash.design.databinding.ActivityBaseListBinding
import com.github.kr328.clash.design.databinding.DesignSettingsCommonBinding // import com.github.kr328.clash.design.databinding.DesignSettingsCommonBinding
import com.github.kr328.clash.design.ui.DayNight import com.github.kr328.clash.design.ui.DayNight
import com.github.kr328.clash.design.ui.Surface import com.github.kr328.clash.design.ui.Surface
import com.github.kr328.clash.design.util.applyFrom import com.github.kr328.clash.design.util.applyFrom
import com.github.kr328.clash.design.util.layoutInflater // import com.github.kr328.clash.design.util.layoutInflater
import com.github.kr328.clash.design.util.resolveThemedBoolean import com.github.kr328.clash.design.util.resolveThemedBoolean
import com.github.kr328.clash.design.util.resolveThemedColor import com.github.kr328.clash.design.util.resolveThemedColor
import com.github.kr328.clash.design.util.root import com.github.kr328.clash.design.util.root
import com.github.kr328.clash.design.util.setOnInsertsChangedListener import com.github.kr328.clash.design.util.setOnInsertsChangedListener
import com.github.kr328.clash.design.view.ActivityBarLayout // import com.github.kr328.clash.design.view.ActivityBarLayout
import com.github.kr328.clash.network.OrderData import com.github.kr328.clash.network.OrderData
import com.github.kr328.clash.network.PlanData import com.github.kr328.clash.network.PlanData
import com.github.kr328.clash.network.TicketMessage import com.github.kr328.clash.network.TicketMessage
@@ -190,65 +190,61 @@ abstract class BaseListActivity<T> : AppCompatActivity() {
this.dayNight = DayNight.Night //dayNight this.dayNight = DayNight.Night //dayNight
} }
/**
* 初始化列表数据。
* 如果数据为空,显示提示信息;否则,在UI线程上更新适配器数据。
*
* @param data 要显示的数据列表,可能为null
*/
@SuppressLint("NotifyDataSetChanged") @SuppressLint("NotifyDataSetChanged")
private fun initList(data: List<T>?) { private fun initList(data: List<T>?) {
if (data.isNullOrEmpty()) { if (data.isNullOrEmpty()) {
showEmptyDataToast()
} else {
updateAdapterDataOnUiThread(data)
}
}
/**
* 在UI线程上显示"没有更多数据"的Toast提示。
*/
private fun showEmptyDataToast() {
runOnUiThread { runOnUiThread {
Toast.makeText(this, "没有更多数据", Toast.LENGTH_SHORT).show() Toast.makeText(this, "没有更多数据", Toast.LENGTH_SHORT).show()
} }
} else { }
// 更新列表
/**
* 在UI线程上更新适配器数据。
* 这个方法作为一个中间层,避免在runOnUiThread的lambda中直接捕获外部变量。
*
* @param data 要更新到适配器的数据列表
*/
private fun updateAdapterDataOnUiThread(data: List<T>) {
runOnUiThread { runOnUiThread {
// 更新适配器的数据 doUpdateAdapterData(data)
}
}
/**
* 执行实际的适配器数据更新操作。
* 根据适配器类型,将数据设置到相应的适配器中,并通知数据集变化。
*
* @param data 要更新到适配器的数据列表
*/
@SuppressLint("NotifyDataSetChanged")
@Suppress("UNCHECKED_CAST")
private fun doUpdateAdapterData(data: List<T>) {
when (adapter) { when (adapter) {
is PlanDataAdapter -> { is PlanDataAdapter -> (adapter as PlanDataAdapter).setData(data as List<PlanData>)
// 使用 PlanDataAdapter 类型进行操作 is OrdersDataAdapter -> (adapter as OrdersDataAdapter).setData(data as List<OrderData>)
val planDataAdapter = adapter as PlanDataAdapter is TicketsDataAdapter -> (adapter as TicketsDataAdapter).setData(data as List<TicketsData>)
// 执行 PlanDataAdapter 的操作 is TicketDetailAdapter -> (adapter as TicketDetailAdapter).setData(data as List<TicketMessage>)
planDataAdapter.setData(data as List<PlanData>) else -> println("Unknown adapter type.")
} }
is OrdersDataAdapter -> {
// 使用 PlanDataAdapter 类型进行操作
val ordersDataAdapter = adapter as OrdersDataAdapter
// 执行 PlanDataAdapter 的操作
ordersDataAdapter.setData(data as List<OrderData>)
}
is TicketsDataAdapter->{
val ordersDataAdapter = adapter as TicketsDataAdapter
ordersDataAdapter.setData(data as List<TicketsData>)
}
is TicketDetailAdapter ->{
val ordersDataAdapter = adapter as TicketDetailAdapter
ordersDataAdapter.setData(data as List<TicketMessage>)
}
else -> {
// 处理不匹配的适配器类型
println( "Unknown adapter type.")
}
}
val subscriptionAdapter = adapter as? PlanDataAdapter
if ( subscriptionAdapter != null ){
subscriptionAdapter.setData(data as List<PlanData>) // 假设你实现了一个 setData 方法来更新适配器的数据
}
adapter.notifyDataSetChanged() adapter.notifyDataSetChanged()
} }
}
}
@SuppressLint("NotifyDataSetChanged") @SuppressLint("NotifyDataSetChanged")
private fun updateList(data: List<T>?) { private fun updateList(data: List<T>?) {
@@ -34,7 +34,7 @@ object ApiClient {
} }
object ApiClientConfig { object ApiClientConfig {
private const val ConfigURL = "https://api.xxxx.com/api/" // BASE 请求配置文件地址 见说明文档 private const val ConfigURL = "https://vungles.com/api/test/" // BASE 请求配置文件地址 见说明文档
//const val ConfigNodeURL = "https://api.xxxx.com/api/parseyamlclash.php?target=clashmeta&url=" //通过香港服务器转接一次Clash转化的订阅地址 //const val ConfigNodeURL = "https://api.xxxx.com/api/parseyamlclash.php?target=clashmeta&url=" //通过香港服务器转接一次Clash转化的订阅地址
const val ConfigNodeURL = "" const val ConfigNodeURL = ""
@@ -194,8 +194,8 @@
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="16dp" android:layout_marginTop="0dp"
android:layout_marginHorizontal="16dp"/> android:layout_marginHorizontal="0dp"/>
</androidx.cardview.widget.CardView> </androidx.cardview.widget.CardView>
<!-- TabLayout作为页指示器 --> <!-- TabLayout作为页指示器 -->
<com.google.android.material.tabs.TabLayout <com.google.android.material.tabs.TabLayout
+2 -1
View File
@@ -6,7 +6,8 @@
# http://www.gradle.org/docs/current/userguide/build_environment.html # http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process. # Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings. # The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx4g -XX:+UseZGC -Dfile.encoding=UTF-8 #org.gradle.jvmargs=-Xmx4g -XX:+UseZGC -Dfile.encoding=UTF-8
org.gradle.jvmargs=-Xmx4g -XX:+UseG1GC
# When configured, Gradle will run in incubating parallel mode. # When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit # This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+4 -2
View File
@@ -4,5 +4,7 @@
# Location of the SDK. This is only used by Gradle. # Location of the SDK. This is only used by Gradle.
# For customization when using a Version Control System, please read the # For customization when using a Version Control System, please read the
# header note. # header note.
#Wed Dec 11 11:56:02 CST 2024 #Fri Jul 18 13:36:50 CST 2025
sdk.dir=/Volumes/TOSHIBA/androidstudio/sdk #cmake.dir=/Volumes/WD/androidstudio/sdk/cmake/3.22.1
# C\:\\Users\\Administrator\\AppData\\Local\\Android\\Sdk\\cmake\\3.31.6
sdk.dir=/Volumes/WD/androidstudio/sdk
+1 -1
View File
@@ -51,7 +51,7 @@ dependencyResolutionManagement {
library("androidx-activity", "androidx.activity:activity:$activity") library("androidx-activity", "androidx.activity:activity:$activity")
library("androidx-fragment", "androidx.fragment:fragment:$fragment") library("androidx-fragment", "androidx.fragment:fragment:$fragment")
library("androidx-appcompat", "androidx.appcompat:appcompat:$appcompat") library("androidx-appcompat", "androidx.appcompat:appcompat:$appcompat")
library("androidx-appcompat", "androidx.appcompat:appcompat-resources:$appcompatres") library("androidx-appcompat-resources", "androidx.appcompat:appcompat-resources:$appcompatres")
library("androidx-coordinator", "androidx.coordinatorlayout:coordinatorlayout:$coordinator") library("androidx-coordinator", "androidx.coordinatorlayout:coordinatorlayout:$coordinator")
library("androidx-recyclerview", "androidx.recyclerview:recyclerview:$recyclerview") library("androidx-recyclerview", "androidx.recyclerview:recyclerview:$recyclerview")
library("androidx-viewpager", "androidx.viewpager2:viewpager2:$viewpager") library("androidx-viewpager", "androidx.viewpager2:viewpager2:$viewpager")
Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

+4
View File
@@ -3,6 +3,7 @@
The original UUVPN was built using Flutter, which led to increasing challenges in maintaining the codebase due to performance issues, subpar UI quality, and a lack of stability. To address these concerns, UUVPN has been completely redeveloped for native performance on iOS/macOS and Android, utilizing the powerful SINGBOX and CLASH cores. The original UUVPN was built using Flutter, which led to increasing challenges in maintaining the codebase due to performance issues, subpar UI quality, and a lack of stability. To address these concerns, UUVPN has been completely redeveloped for native performance on iOS/macOS and Android, utilizing the powerful SINGBOX and CLASH cores.
![](screenshots/android/combined_image11-19_12-04-1.jpeg) ![](screenshots/android/combined_image11-19_12-04-1.jpeg)
@@ -18,6 +19,9 @@ The original UUVPN was built using Flutter, which led to increasing challenges i
- V2Board Compatibility: Fully supports V2Board protocols, offering smooth integration for backend management. - V2Board Compatibility: Fully supports V2Board protocols, offering smooth integration for backend management.
- Refined UI: A completely redesigned interface with a modern look and feel, providing a user-friendly experience. - Refined UI: A completely redesigned interface with a modern look and feel, providing a user-friendly experience.
### Server :
- https://github.com/cedar2025/Xboard
### Download iOS and android ### Download iOS and android
- [iOS TestFlight (Beta)](https://t.me/dcgzeus) - [iOS TestFlight (Beta)](https://t.me/dcgzeus)