commit 79840766bb1ab56bd2f0d10b125edb3967a9763c Author: zilinsoft Date: Tue Jun 30 17:28:37 2026 +0800 初始git版本。 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fd0bc32 --- /dev/null +++ b/.gitignore @@ -0,0 +1,21 @@ +Publish/ +**/obj +*.pdb +**/dcu +*.dcu +**/Secure +*/.vs +*.iml +**/.gradle +**/local.properties +**/.idea/caches +**/.idea/libraries +**/.idea/modules.xml +**/.idea/workspace.xml +**/.idea/navEditor.xml +**/.idea/assetWizardSettings.xml +**/.DS_Store +**/build +**/captures +**/.externalNativeBuild +**/.cxx \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..415bc43 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# 手动打卡 + +#### 介绍 diff --git a/Source/ManualSign/.idea/.gitignore b/Source/ManualSign/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/Source/ManualSign/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/Source/ManualSign/.idea/AndroidProjectSystem.xml b/Source/ManualSign/.idea/AndroidProjectSystem.xml new file mode 100644 index 0000000..4a53bee --- /dev/null +++ b/Source/ManualSign/.idea/AndroidProjectSystem.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/Source/ManualSign/.idea/compiler.xml b/Source/ManualSign/.idea/compiler.xml new file mode 100644 index 0000000..b86273d --- /dev/null +++ b/Source/ManualSign/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Source/ManualSign/.idea/deploymentTargetSelector.xml b/Source/ManualSign/.idea/deploymentTargetSelector.xml new file mode 100644 index 0000000..ca16a99 --- /dev/null +++ b/Source/ManualSign/.idea/deploymentTargetSelector.xml @@ -0,0 +1,11 @@ + + + + + + + + + \ No newline at end of file diff --git a/Source/ManualSign/.idea/gradle.xml b/Source/ManualSign/.idea/gradle.xml new file mode 100644 index 0000000..639c779 --- /dev/null +++ b/Source/ManualSign/.idea/gradle.xml @@ -0,0 +1,19 @@ + + + + + + + \ No newline at end of file diff --git a/Source/ManualSign/.idea/migrations.xml b/Source/ManualSign/.idea/migrations.xml new file mode 100644 index 0000000..f8051a6 --- /dev/null +++ b/Source/ManualSign/.idea/migrations.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/Source/ManualSign/.idea/misc.xml b/Source/ManualSign/.idea/misc.xml new file mode 100644 index 0000000..b2c751a --- /dev/null +++ b/Source/ManualSign/.idea/misc.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/Source/ManualSign/.idea/runConfigurations.xml b/Source/ManualSign/.idea/runConfigurations.xml new file mode 100644 index 0000000..16660f1 --- /dev/null +++ b/Source/ManualSign/.idea/runConfigurations.xml @@ -0,0 +1,17 @@ + + + + + + \ No newline at end of file diff --git a/Source/ManualSign/app/.gitignore b/Source/ManualSign/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/Source/ManualSign/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/Source/ManualSign/app/build.gradle.kts b/Source/ManualSign/app/build.gradle.kts new file mode 100644 index 0000000..68fd80f --- /dev/null +++ b/Source/ManualSign/app/build.gradle.kts @@ -0,0 +1,61 @@ +plugins { + alias(libs.plugins.android.application) + alias(libs.plugins.kotlin.compose) +} + +android { + namespace = "com.itrycn.manualsign" + compileSdk { + version = release(36) { + minorApiLevel = 1 + } + } + viewBinding { + enable=true + } + defaultConfig { + applicationId = "com.itrycn.manualsign" + minSdk = 24 + targetSdk = 36 + versionCode = 1 + versionName = "1.0" + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + buildFeatures { + compose = true + } +} + +dependencies { + implementation(libs.androidx.core.ktx) + implementation(libs.androidx.lifecycle.runtime.ktx) + implementation(libs.androidx.activity.compose) + implementation(platform(libs.androidx.compose.bom)) + implementation(libs.androidx.compose.ui) + implementation(libs.androidx.compose.ui.graphics) + implementation(libs.androidx.compose.ui.tooling.preview) + implementation(libs.androidx.compose.material3) + implementation(libs.androidx.appcompat) + testImplementation(libs.junit) + androidTestImplementation(libs.androidx.junit) + androidTestImplementation(libs.androidx.espresso.core) + androidTestImplementation(platform(libs.androidx.compose.bom)) + androidTestImplementation(libs.androidx.compose.ui.test.junit4) + debugImplementation(libs.androidx.compose.ui.tooling) + debugImplementation(libs.androidx.compose.ui.test.manifest) +} \ No newline at end of file diff --git a/Source/ManualSign/app/proguard-rules.pro b/Source/ManualSign/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/Source/ManualSign/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/Source/ManualSign/app/src/androidTest/java/com/itrycn/manualsign/ExampleInstrumentedTest.kt b/Source/ManualSign/app/src/androidTest/java/com/itrycn/manualsign/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..cc6d93d --- /dev/null +++ b/Source/ManualSign/app/src/androidTest/java/com/itrycn/manualsign/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package com.itrycn.manualsign + +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.ext.junit.runners.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("com.itrycn.manualsign", appContext.packageName) + } +} \ No newline at end of file diff --git a/Source/ManualSign/app/src/main/AndroidManifest.xml b/Source/ManualSign/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..c0f2243 --- /dev/null +++ b/Source/ManualSign/app/src/main/AndroidManifest.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/ManualSign/app/src/main/java/com/itrycn/manualsign/MainActivity.kt b/Source/ManualSign/app/src/main/java/com/itrycn/manualsign/MainActivity.kt new file mode 100644 index 0000000..488cbfe --- /dev/null +++ b/Source/ManualSign/app/src/main/java/com/itrycn/manualsign/MainActivity.kt @@ -0,0 +1,465 @@ +package com.itrycn.manualsign + +import android.annotation.SuppressLint +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.drawable.ColorDrawable +import android.graphics.drawable.Drawable +import android.graphics.drawable.GradientDrawable +import android.os.Bundle +import android.view.MotionEvent +import android.view.View +import android.view.View.GONE +import android.view.View.VISIBLE +import android.widget.Button +import android.widget.LinearLayout +import android.widget.ProgressBar +import android.widget.Toast +import androidx.appcompat.app.AppCompatActivity +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.core.content.res.ResourcesCompat +import com.itrycn.manualsign.databinding.ActivityMainBinding +import com.itrycn.manualsign.ui.theme.ManualSignTheme +import org.json.JSONArray +import org.json.JSONObject +import java.net.HttpURLConnection +import java.net.URL +import kotlin.concurrent.thread +import android.os.Handler +import android.os.Looper +import android.view.Gravity +import android.widget.TextView +import androidx.appcompat.widget.Toolbar +import java.net.URLEncoder + +class MainActivity : AppCompatActivity() { + // ViewBinding 绑定布局 + private lateinit var binding: ActivityMainBinding + // 整个类通用的公共 Int 变量 M + private var UnDakaCount: Int = 0 + private var DakaTotalCount: Int = 0 + // 你可以替换成自己的接口地址 + // 接口要求:返回纯 JSON 数组,例如 ["按钮1","按钮2","按钮3"] + private val apiUrl = "http://gs2.dangyou.com:8081/xin.aspx" + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivityMainBinding.inflate(layoutInflater) + setContentView(binding.root) + val toolbar = findViewById(R.id.toolbar) + setSupportActionBar(toolbar) + supportActionBar?.setDisplayHomeAsUpEnabled(true) + binding.stickySignTip.setPadding(24, 14, 24, 14) + binding.stickySignTip.gravity= Gravity.CENTER + binding.stickySignTip.background = GradientDrawable().apply { + setColor(Color.WHITE) + cornerRadius = 50f + } + + // ✅ 修复:让整个布局往下偏移,不被状态栏挡住 + //binding.root.setPadding(0, 100, 0, 0) + // 请求接口并生成按钮 + fetchDataAndCreateButtons() + } + override fun onSupportNavigateUp(): Boolean { + finish() + return true + } + // 加在这里 + override fun onResume() { + super.onResume() + fetchDataAndCreateButtons() + } + // 网络请求 + 动态创建按钮 + private fun fetchDataAndCreateButtons() { + thread { // 子线程请求网络(Android 禁止主线程联网) + try { + // 1. 网络请求 + val url = URL("$apiUrl?api=GetManualSign") + val conn = url.openConnection() as HttpURLConnection + conn.requestMethod = "POST" + conn.connectTimeout = 5000 + conn.readTimeout = 5000 + // 允许输出(POST 必须) + conn.doOutput = true + conn.doInput = true + + // 设置参数格式 + conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded") + // 读取返回数据 + val result = conn.inputStream.bufferedReader().readText() + conn.disconnect() + + // 2. 解析 JSON 数组 + val jsonObject = JSONObject(result) + val dataArray: JSONArray = jsonObject.getJSONArray("datas") + val buttonList = mutableListOf() + for (i in 0 until dataArray.length()) { + val item=dataArray.getJSONObject(i) + buttonList.add(item) + } + + // 3. 主线程更新 UI(创建按钮) + runOnUiThread { + createButtons(buttonList) + } + + } catch (e: Exception) { + e.printStackTrace() + runOnUiThread { + Toast.makeText(this, "请求失败:${e.message}", Toast.LENGTH_SHORT).show() + } + } + } + } + @SuppressLint("SetTextI18n") + private fun postData(btn: Button, url: String, data: String) { + thread { // 子线程请求网络(Android 禁止主线程联网) + try { + // 1. 网络请求 + val url = URL(url) + val conn = url.openConnection() as HttpURLConnection + conn.requestMethod = "POST" + conn.connectTimeout = 5000 + conn.readTimeout = 5000 + // 允许输出(POST 必须) + conn.doOutput = true + conn.doInput = true + + // 设置参数格式 + conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded") + val out = conn.outputStream + out.write(data.toByteArray()) + out.flush() + out.close() + // 读取返回数据 + val result = conn.inputStream.bufferedReader().readText() + conn.disconnect() + val jsonObject = JSONObject(result) + val code = jsonObject.getInt("code") + if(code==200) + { + runOnUiThread { + // 左侧图标(使用系统默认图标,你也可以换自己的) + val icon = ResourcesCompat.getDrawable(resources, R.drawable.right, theme) + icon?.setBounds(0, 0, 45, 45) // 设置图标大小 + btn.setCompoundDrawables(icon, null, null, null) // 左、上、右、下 + btn.compoundDrawablePadding = 12 // 图标和文字间距 + btn.isEnabled=false + UnDakaCount-- + if(UnDakaCount<0){UnDakaCount=0} + RefreshState() + Toast.makeText(this, "打卡成功", Toast.LENGTH_SHORT).show() + } + } + else{ + runOnUiThread { + Toast.makeText(this, "打卡失败=>"+jsonObject.getString("msg"), Toast.LENGTH_SHORT).show() + } + } + + } catch (e: Exception) { + e.printStackTrace() + runOnUiThread { + Toast.makeText(this, "请求失败:${e.message}", Toast.LENGTH_SHORT).show() + } + } + } + } + /** + * 获取指定日期的 10 位时间戳(秒) + * @param dateStr 日期字符串,例如 "2025-01-01" 或 "2025-01-01 12:00:00" + * @param pattern 日期格式,例如 "yyyy-MM-dd" 或 "yyyy-MM-dd HH:mm:ss" + * @return 10位时间戳(Long类型) + */ + fun get10Timestamp(dateStr: String, pattern: String = "yyyy-MM-dd"): Long { + val sdf = java.text.SimpleDateFormat(pattern, java.util.Locale.CHINA) + sdf.timeZone = java.util.TimeZone.getTimeZone("GMT+8") // 东八区 + val date = sdf.parse(dateStr) + return (date?.time ?: 0) / 1000 // 转10位(秒) + } + // 获取今天:yyyy-MM-dd + fun getTodayDate(): String { + val sdf = java.text.SimpleDateFormat("yyyy-MM-dd", java.util.Locale.CHINA) + sdf.timeZone = java.util.TimeZone.getTimeZone("GMT+8") + return sdf.format(java.util.Date()) + } + @SuppressLint("SetTextI18n") + fun RefreshState() { + if (UnDakaCount <= 0) { + binding.stickySignTip.setTextColor(Color.BLUE) + binding.stickySignTip.text = + "今日打卡进度:" + (DakaTotalCount - UnDakaCount) + "/" + DakaTotalCount + ",全部打卡完成" + } else { + binding.stickySignTip.setTextColor(Color.RED) + binding.stickySignTip.text = + "今日打卡进度:" + (DakaTotalCount - UnDakaCount) + "/" + DakaTotalCount + ",还剩" + UnDakaCount + "条未打卡" + } + } + /** + * 根据包名打开其他应用 + * @param packageName 应用包名(如 com.tencent.mm 微信) + */ + fun openAppByPackage(appName:String, packageName: String) { + try { + val intent = packageManager.getLaunchIntentForPackage(packageName) + if (intent != null) { + startActivity(intent) + } else { + Toast.makeText(this, "未安装$appName", Toast.LENGTH_SHORT).show() + } + } catch (e: Exception) { + Toast.makeText(this, "打开失败:${e.message}", Toast.LENGTH_SHORT).show() + } + } + /** + * 根据包名获取应用图标 + */ + private fun getAppIcon(packageName: String): Drawable? { + return try { + packageManager.getApplicationIcon(packageName) + } catch (e: Exception) { + // 获取失败返回默认图标 + ResourcesCompat.getDrawable(resources, R.mipmap.ic_launcher, theme) + } + } + // 横向进度条 Drawable(按钮内部显示) + private class ProgressDrawable : ColorDrawable(Color.GRAY) { + private var progress = 0f + private var duration = 3000L + private var onEnd: (() -> Unit)? = null + private val handler = android.os.Handler(android.os.Looper.getMainLooper()) + private var startTime = 0L + + fun startProgress(duration: Long, onEnd: () -> Unit) { + this.duration = duration + this.onEnd = onEnd + startTime = System.currentTimeMillis() + handler.post(updateProgress) + } + + private val updateProgress = object : Runnable { + override fun run() { + val elapsed = System.currentTimeMillis() - startTime + progress = (elapsed.toFloat() / duration).coerceAtMost(1f) + invalidateSelf() + + if (progress < 1f) { + handler.postDelayed(this, 16) + } else { + onEnd?.invoke() + } + } + } + + override fun draw(canvas: Canvas) { + super.draw(canvas) + //paint.color = Color.parseColor("#2196F3") + val width = bounds.width() * progress + //canvas.drawRect(0f, 0f, width, bounds.height().toFloat(), paint) + } + } + private fun showtip(msg: String,textColor: Int,backColor: Int) + { + // 点击/长按完成后 → 在最顶部插入成功提示文字 + // ============================================== + val tip = TextView(this@MainActivity).apply { + text = msg + textSize = 14f + setTextColor(textColor) + setPadding(24, 14, 24, 14) + gravity = Gravity.CENTER + background = GradientDrawable().apply { + setColor(backColor) + cornerRadius = 50f + } + layoutParams = LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT + ).apply { + bottomMargin = 16 + // ✅ 关键:给提示条本身加顶部间距,永远不被遮挡 + topMargin = 15 + } + } + + // 插入到按钮容器最顶部 + binding.buttonContainer.addView(tip, 0) + // 3秒后自动移除提示 + tip.postDelayed({ + binding.buttonContainer.removeView(tip) + }, 3000) + } + // 根据列表动态生成按钮 + @SuppressLint("ClickableViewAccessibility", "SetTextI18n") + private fun createButtons(list: List) { + val layout = binding.buttonContainer + layout.removeAllViews() + var sign_count=0 + for (jo in list) { + // 外层水平布局,放 主按钮 + 右侧小按钮 + val parentLayout = LinearLayout(this).apply { + orientation = LinearLayout.HORIZONTAL + layoutParams = LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT + ).apply { + topMargin = 2 + } + } + + // 主按钮容器(包含按钮 + 进度条) + val mainBtnContainer = LinearLayout(this).apply { + orientation = LinearLayout.VERTICAL + layoutParams = LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1.0f) + } + + val mainBtn = Button(this).apply { + this.text = jo.getString("appName") + this.contentDescription = jo.getString("appName") + this.textSize = 16f + this.setPadding(40, 30, 200, 30) + this.tag = jo + + // 已签到状态处理 + if (jo.getLong("signTime") >= get10Timestamp(getTodayDate())) { + this.isEnabled = false + sign_count++ + val icon = androidx.core.content.res.ResourcesCompat.getDrawable(resources, R.drawable.right, theme) + icon?.setBounds(0, 0, 45, 45) + this.setCompoundDrawables(icon, null, null, null) + this.compoundDrawablePadding = 12 + } + } + + // 进度条(放在主按钮下方) + val progressBar = ProgressBar(this, null, android.R.attr.progressBarStyleHorizontal).apply { + layoutParams = LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + 20 // 进度条高度 + ) + isIndeterminate = false + max = 100 + progress = 0 + visibility = View.GONE // 默认隐藏 + } + mainBtnContainer.addView(progressBar) + // 添加按钮和进度条到容器 + mainBtnContainer.addView(mainBtn) + + // 右侧小按钮 + val smallBtn = Button(this).apply { + this.text = "打开" + this.textSize = 14f + this.setPadding(20, 30, 20, 30) + this.minWidth = 250 + this.minimumWidth = 250 + + this.setOnClickListener { + // ============================================== + + openAppByPackage(jo.getString("appName"), jo.getString("pkgName")) + } + } + val icon2 = getAppIcon(jo.getString("pkgName")) + icon2?.setBounds(0, 0, 60, 60) + smallBtn.setCompoundDrawables(icon2, null, null, null) + smallBtn.compoundDrawablePadding = 1 + + // ========== 长按进度条核心逻辑 ========== + val handler = Handler(Looper.getMainLooper()) + var progressRunnable: Runnable? = null + var currentProgress = 0f + val totalDuration = 1000L // 3秒 + val interval = 20L + + // 长按主按钮开始 + mainBtn.setOnLongClickListener { + if (!mainBtn.isEnabled) return@setOnLongClickListener false + + currentProgress = 0f + progressBar.progress = 0 + progressBar.visibility = View.VISIBLE + mainBtn.text = "签到中..." + + // 进度更新任务 + progressRunnable = object : Runnable { + override fun run() { + currentProgress += (interval * 100f / totalDuration) + if (currentProgress >= 100) { + // 进度完成,执行签到 + progressBar.progress = 100 + progressBar.visibility = View.GONE + mainBtn.text = jo.getString("appName") + mainBtn.isEnabled = false + // 执行签到事件 + postData( + mainBtn, + "$apiUrl?api=saveSign", + "id="+jo.getInt("id")+"&pkgName=" + URLEncoder.encode(jo.getString("pkgName"), "UTF-8") + + "&appName=" + URLEncoder.encode(jo.getString("appName"), "UTF-8") + + "&phone_model=" + URLEncoder.encode(jo.getString("phone_model"), "UTF-8") + + "&signResult=1" + ) + + } else { + // 继续更新进度 + progressBar.progress = currentProgress.toInt() + handler.postDelayed(this, interval) + } + } + } + handler.postDelayed(progressRunnable, interval) + true + } + + mainBtn.setOnTouchListener { _, event -> + if (event.action == MotionEvent.ACTION_UP || event.action == MotionEvent.ACTION_CANCEL) { + // 使用 ?.let 安全处理可空变量 + progressRunnable?.let { runnable -> + handler.removeCallbacks(runnable) + progressBar.visibility = View.GONE + mainBtn.text = jo.getString("appName") + } + // 不再需要设置 progressRunnable = null + } + false + } + + // 添加到布局 + parentLayout.addView(mainBtnContainer) + parentLayout.addView(smallBtn) + layout.addView(parentLayout) + } + title="今日打卡("+list.count()+")" + UnDakaCount=list.count()-sign_count + DakaTotalCount=list.count() + RefreshState() + //if(sign_count==list.count()) + //{ + // showtip("全部$sign_count 条打卡任务已完成。",Color.BLUE,Color.WHITE); + //} + //else{ + //Toast.makeText(this, "今日共有"+list.count()+"条打卡任务,已完成$sign_count 条。\n还剩"+(list.count()-sign_count)+"条。", Toast.LENGTH_SHORT).show() + //showtip("今日共有"+list.count()+"条打卡任务,已完成$sign_count 条。",Color.GRAY,Color.YELLOW); + //} + } +} + +@Composable +fun Greeting(name: String, modifier: Modifier = Modifier) { + Text( + text = "Hello $name!", + modifier = modifier + ) +} + +@Preview(showBackground = true) +@Composable +fun GreetingPreview() { + ManualSignTheme { + Greeting("Android") + } +} \ No newline at end of file diff --git a/Source/ManualSign/app/src/main/java/com/itrycn/manualsign/ui/theme/Color.kt b/Source/ManualSign/app/src/main/java/com/itrycn/manualsign/ui/theme/Color.kt new file mode 100644 index 0000000..4aa62a7 --- /dev/null +++ b/Source/ManualSign/app/src/main/java/com/itrycn/manualsign/ui/theme/Color.kt @@ -0,0 +1,11 @@ +package com.itrycn.manualsign.ui.theme + +import androidx.compose.ui.graphics.Color + +val Purple80 = Color(0xFFD0BCFF) +val PurpleGrey80 = Color(0xFFCCC2DC) +val Pink80 = Color(0xFFEFB8C8) + +val Purple40 = Color(0xFF6650a4) +val PurpleGrey40 = Color(0xFF625b71) +val Pink40 = Color(0xFF7D5260) \ No newline at end of file diff --git a/Source/ManualSign/app/src/main/java/com/itrycn/manualsign/ui/theme/Theme.kt b/Source/ManualSign/app/src/main/java/com/itrycn/manualsign/ui/theme/Theme.kt new file mode 100644 index 0000000..8d991c6 --- /dev/null +++ b/Source/ManualSign/app/src/main/java/com/itrycn/manualsign/ui/theme/Theme.kt @@ -0,0 +1,58 @@ +package com.itrycn.manualsign.ui.theme + +import android.app.Activity +import android.os.Build +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.dynamicDarkColorScheme +import androidx.compose.material3.dynamicLightColorScheme +import androidx.compose.material3.lightColorScheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.platform.LocalContext + +private val DarkColorScheme = darkColorScheme( + primary = Purple80, + secondary = PurpleGrey80, + tertiary = Pink80 +) + +private val LightColorScheme = lightColorScheme( + primary = Purple40, + secondary = PurpleGrey40, + tertiary = Pink40 + + /* Other default colors to override + background = Color(0xFFFFFBFE), + surface = Color(0xFFFFFBFE), + onPrimary = Color.White, + onSecondary = Color.White, + onTertiary = Color.White, + onBackground = Color(0xFF1C1B1F), + onSurface = Color(0xFF1C1B1F), + */ +) + +@Composable +fun ManualSignTheme( + darkTheme: Boolean = isSystemInDarkTheme(), + // Dynamic color is available on Android 12+ + dynamicColor: Boolean = true, + content: @Composable () -> Unit +) { + val colorScheme = when { + dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { + val context = LocalContext.current + if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) + } + + darkTheme -> DarkColorScheme + else -> LightColorScheme + } + + MaterialTheme( + colorScheme = colorScheme, + typography = Typography, + content = content + ) +} \ No newline at end of file diff --git a/Source/ManualSign/app/src/main/java/com/itrycn/manualsign/ui/theme/Type.kt b/Source/ManualSign/app/src/main/java/com/itrycn/manualsign/ui/theme/Type.kt new file mode 100644 index 0000000..b3110a3 --- /dev/null +++ b/Source/ManualSign/app/src/main/java/com/itrycn/manualsign/ui/theme/Type.kt @@ -0,0 +1,34 @@ +package com.itrycn.manualsign.ui.theme + +import androidx.compose.material3.Typography +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.sp + +// Set of Material typography styles to start with +val Typography = Typography( + bodyLarge = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 16.sp, + lineHeight = 24.sp, + letterSpacing = 0.5.sp + ) + /* Other default text styles to override + titleLarge = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 22.sp, + lineHeight = 28.sp, + letterSpacing = 0.sp + ), + labelSmall = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Medium, + fontSize = 11.sp, + lineHeight = 16.sp, + letterSpacing = 0.5.sp + ) + */ +) \ No newline at end of file diff --git a/Source/ManualSign/app/src/main/res/drawable/ic_launcher_background.xml b/Source/ManualSign/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/Source/ManualSign/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/ManualSign/app/src/main/res/drawable/ic_launcher_foreground.xml b/Source/ManualSign/app/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/Source/ManualSign/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/Source/ManualSign/app/src/main/res/drawable/right.png b/Source/ManualSign/app/src/main/res/drawable/right.png new file mode 100644 index 0000000..08c60b7 Binary files /dev/null and b/Source/ManualSign/app/src/main/res/drawable/right.png differ diff --git a/Source/ManualSign/app/src/main/res/layout/activity_main.xml b/Source/ManualSign/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..cda1064 --- /dev/null +++ b/Source/ManualSign/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/ManualSign/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/Source/ManualSign/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..6f3b755 --- /dev/null +++ b/Source/ManualSign/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Source/ManualSign/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/Source/ManualSign/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..6f3b755 --- /dev/null +++ b/Source/ManualSign/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Source/ManualSign/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/Source/ManualSign/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 Binary files /dev/null and b/Source/ManualSign/app/src/main/res/mipmap-hdpi/ic_launcher.webp differ diff --git a/Source/ManualSign/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/Source/ManualSign/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d Binary files /dev/null and b/Source/ManualSign/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ diff --git a/Source/ManualSign/app/src/main/res/mipmap-hdpi/icon.png b/Source/ManualSign/app/src/main/res/mipmap-hdpi/icon.png new file mode 100644 index 0000000..27b5671 Binary files /dev/null and b/Source/ManualSign/app/src/main/res/mipmap-hdpi/icon.png differ diff --git a/Source/ManualSign/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/Source/ManualSign/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 Binary files /dev/null and b/Source/ManualSign/app/src/main/res/mipmap-mdpi/ic_launcher.webp differ diff --git a/Source/ManualSign/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/Source/ManualSign/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d Binary files /dev/null and b/Source/ManualSign/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ diff --git a/Source/ManualSign/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/Source/ManualSign/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 Binary files /dev/null and b/Source/ManualSign/app/src/main/res/mipmap-xhdpi/ic_launcher.webp differ diff --git a/Source/ManualSign/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/Source/ManualSign/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1b9a695 Binary files /dev/null and b/Source/ManualSign/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ diff --git a/Source/ManualSign/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/Source/ManualSign/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000..28d4b77 Binary files /dev/null and b/Source/ManualSign/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ diff --git a/Source/ManualSign/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/Source/ManualSign/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9287f50 Binary files /dev/null and b/Source/ManualSign/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ diff --git a/Source/ManualSign/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/Source/ManualSign/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 0000000..aa7d642 Binary files /dev/null and b/Source/ManualSign/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ diff --git a/Source/ManualSign/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/Source/ManualSign/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9126ae3 Binary files /dev/null and b/Source/ManualSign/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ diff --git a/Source/ManualSign/app/src/main/res/values/colors.xml b/Source/ManualSign/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..f8c6127 --- /dev/null +++ b/Source/ManualSign/app/src/main/res/values/colors.xml @@ -0,0 +1,10 @@ + + + #FFBB86FC + #FF6200EE + #FF3700B3 + #FF03DAC5 + #FF018786 + #FF000000 + #FFFFFFFF + \ No newline at end of file diff --git a/Source/ManualSign/app/src/main/res/values/strings.xml b/Source/ManualSign/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..9387713 --- /dev/null +++ b/Source/ManualSign/app/src/main/res/values/strings.xml @@ -0,0 +1,4 @@ + + 手动打卡 + 今日打卡进度:无 + \ No newline at end of file diff --git a/Source/ManualSign/app/src/main/res/values/themes.xml b/Source/ManualSign/app/src/main/res/values/themes.xml new file mode 100644 index 0000000..1b1b365 --- /dev/null +++ b/Source/ManualSign/app/src/main/res/values/themes.xml @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/Source/ManualSign/app/src/main/res/xml/backup_rules.xml b/Source/ManualSign/app/src/main/res/xml/backup_rules.xml new file mode 100644 index 0000000..4df9255 --- /dev/null +++ b/Source/ManualSign/app/src/main/res/xml/backup_rules.xml @@ -0,0 +1,13 @@ + + + + \ No newline at end of file diff --git a/Source/ManualSign/app/src/main/res/xml/data_extraction_rules.xml b/Source/ManualSign/app/src/main/res/xml/data_extraction_rules.xml new file mode 100644 index 0000000..9ee9997 --- /dev/null +++ b/Source/ManualSign/app/src/main/res/xml/data_extraction_rules.xml @@ -0,0 +1,19 @@ + + + + + + + \ No newline at end of file diff --git a/Source/ManualSign/app/src/test/java/com/itrycn/manualsign/ExampleUnitTest.kt b/Source/ManualSign/app/src/test/java/com/itrycn/manualsign/ExampleUnitTest.kt new file mode 100644 index 0000000..3bad36e --- /dev/null +++ b/Source/ManualSign/app/src/test/java/com/itrycn/manualsign/ExampleUnitTest.kt @@ -0,0 +1,17 @@ +package com.itrycn.manualsign + +import org.junit.Test + +import org.junit.Assert.* + +/** + * Example local unit test, which will execute on the development machine (host). + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +class ExampleUnitTest { + @Test + fun addition_isCorrect() { + assertEquals(4, 2 + 2) + } +} \ No newline at end of file diff --git a/Source/ManualSign/build.gradle.kts b/Source/ManualSign/build.gradle.kts new file mode 100644 index 0000000..18318be --- /dev/null +++ b/Source/ManualSign/build.gradle.kts @@ -0,0 +1,5 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +plugins { + alias(libs.plugins.android.application) apply false + alias(libs.plugins.kotlin.compose) apply false +} \ No newline at end of file diff --git a/Source/ManualSign/gradle.properties b/Source/ManualSign/gradle.properties new file mode 100644 index 0000000..20e2a01 --- /dev/null +++ b/Source/ManualSign/gradle.properties @@ -0,0 +1,23 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. For more details, visit +# https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects +# org.gradle.parallel=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app's APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Kotlin code style for this project: "official" or "obsolete": +kotlin.code.style=official +# Enables namespacing of each library's R class so that its R class includes only the +# resources declared in the library itself and none from the library's dependencies, +# thereby reducing the size of the R class for that library +android.nonTransitiveRClass=true \ No newline at end of file diff --git a/Source/ManualSign/gradle/libs.versions.toml b/Source/ManualSign/gradle/libs.versions.toml new file mode 100644 index 0000000..53cf7c0 --- /dev/null +++ b/Source/ManualSign/gradle/libs.versions.toml @@ -0,0 +1,33 @@ +[versions] +agp = "9.1.1" +coreKtx = "1.17.0" +junit = "4.13.2" +junitVersion = "1.3.0" +espressoCore = "3.7.0" +lifecycleRuntimeKtx = "2.10.0" +activityCompose = "1.12.4" +kotlin = "2.2.10" +composeBom = "2024.09.00" +appcompat = "1.7.1" + +[libraries] +androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } +junit = { group = "junit", name = "junit", version.ref = "junit" } +androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } +androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" } +androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" } +androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" } +androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" } +androidx-compose-ui = { group = "androidx.compose.ui", name = "ui" } +androidx-compose-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" } +androidx-compose-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" } +androidx-compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" } +androidx-compose-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" } +androidx-compose-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" } +androidx-compose-material3 = { group = "androidx.compose.material3", name = "material3" } +androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" } + +[plugins] +android-application = { id = "com.android.application", version.ref = "agp" } +kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } + diff --git a/Source/ManualSign/gradle/wrapper/gradle-wrapper.jar b/Source/ManualSign/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..8bdaf60 Binary files /dev/null and b/Source/ManualSign/gradle/wrapper/gradle-wrapper.jar differ diff --git a/Source/ManualSign/gradle/wrapper/gradle-wrapper.properties b/Source/ManualSign/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..ea64cd5 --- /dev/null +++ b/Source/ManualSign/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,9 @@ +#Sat Apr 04 09:36:30 CST 2026 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionSha256Sum=b266d5ff6b90eada6dc3b20cb090e3731302e553a27c5d3e4df1f0d76beaff06 +distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.1-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/Source/ManualSign/gradlew b/Source/ManualSign/gradlew new file mode 100644 index 0000000..ef07e01 --- /dev/null +++ b/Source/ManualSign/gradlew @@ -0,0 +1,251 @@ +#!/bin/sh + +# +# Copyright © 2015 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH="\\\"\\\"" + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/Source/ManualSign/gradlew.bat b/Source/ManualSign/gradlew.bat new file mode 100644 index 0000000..db3a6ac --- /dev/null +++ b/Source/ManualSign/gradlew.bat @@ -0,0 +1,94 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH= + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/Source/ManualSign/settings.gradle.kts b/Source/ManualSign/settings.gradle.kts new file mode 100644 index 0000000..6d26d57 --- /dev/null +++ b/Source/ManualSign/settings.gradle.kts @@ -0,0 +1,24 @@ +pluginManagement { + repositories { + google { + content { + includeGroupByRegex("com\\.android.*") + includeGroupByRegex("com\\.google.*") + includeGroupByRegex("androidx.*") + } + } + mavenCentral() + gradlePluginPortal() + } +} +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + } +} + +rootProject.name = "ManualSign" +include(":app") + \ No newline at end of file diff --git a/查看项目.ryp b/查看项目.ryp new file mode 100644 index 0000000..8df00c3 --- /dev/null +++ b/查看项目.ryp @@ -0,0 +1,6 @@ +[project] +name=ֶ +engname=ManualSign +usqver=4 +proglang=android +progID=d60f3ce6-f811-42d1-b7c8-253f765ee3f2