Skip to content

Commit be602b8

Browse files
committed
chore: clean inline comments, bilingual docs, simplify GET_STARTED
- Remove all section divider and inline comments across project - Add bilingual XML doc comments (EN/CN) on all public members - Simplify GET_STARTED: remove CoreCLR management, prune smali listing - ModInspector: normalize API naming, remove etc
1 parent 8394c97 commit be602b8

28 files changed

Lines changed: 917 additions & 1464 deletions

‎.gitignore‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ TestAndroidProject2/
5353
**/src/main/assets/*.pdb
5454
**/src/main/assets/*.json
5555
**/src/main/assets/*.bin
56+
**/src/main/assets/runtime
5657

5758
# Logs
5859
*.log

‎Android/library/build.gradle‎

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
import java.nio.file.Files
2+
import java.security.MessageDigest
3+
import java.util.zip.ZipEntry
4+
import java.util.zip.ZipInputStream
5+
16
plugins {
27
id 'com.android.library'
38
}
@@ -62,3 +67,71 @@ dependencies {
6267
androidTestImplementation 'androidx.test.ext:junit:1.2.1'
6368
androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
6469
}
70+
71+
tasks.register("downloadRuntime"){
72+
description = '下载并解压 ZIP 文件到指定目录,如果已存在则跳过'
73+
group = 'build'
74+
75+
// ========== 可配置参数 ==========
76+
def expectedSha256 = "2c40baffab79a89c4ac967407f704fe3e2cc7835cbc86f4fb4d59cd5fc8e1a3b";
77+
def zipUrl = 'https://github.com/StArraySharp/StArray.ModManager/releases/download/0/dotnet10_core_references.zip' // ZIP 下载地址
78+
def destDir = file("$projectDir/src/main/assets/runtime") // 解压目标目录
79+
def zipFile = file("$buildDir/cache/file.zip") // 本地缓存 ZIP 路径
80+
// =================================
81+
82+
onlyIf {
83+
!destDir.exists()
84+
}
85+
86+
doLast {
87+
zipFile.parentFile.mkdirs()
88+
89+
new URL(zipUrl).withInputStream { inputStream ->
90+
zipFile.withOutputStream { outputStream ->
91+
outputStream << inputStream
92+
}
93+
}
94+
// 2. 计算 SHA256 哈希值
95+
MessageDigest digest = MessageDigest.getInstance("SHA-256")
96+
zipFile.withInputStream { fis ->
97+
byte[] buffer = new byte[8192]
98+
int read
99+
while ((read = fis.read(buffer)) != -1) {
100+
digest.update(buffer, 0, read)
101+
}
102+
}
103+
byte[] hashBytes = digest.digest()
104+
String calculatedSha256 = hashBytes.collect { String.format("%02x", it) }.join()
105+
106+
// 3. 校验哈希值
107+
if (!calculatedSha256.equalsIgnoreCase(expectedSha256)) {
108+
Files.delete(zipFile.toPath())
109+
throw new GradleException(
110+
"SHA256 校验失败\n" +
111+
"预期: ${expectedSha256}\n" +
112+
"实际: ${calculatedSha256}\n" +
113+
"请检查网络或手动下载文件。"
114+
)
115+
}
116+
destDir.mkdirs()
117+
try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile))) {
118+
ZipEntry entry
119+
while ((entry = zis.getNextEntry()) != null) {
120+
String entryName = entry.name
121+
if (entryName.isEmpty()) continue
122+
def targetFile = new File(destDir, entryName)
123+
if (entry.isDirectory()) {
124+
targetFile.mkdirs()
125+
} else {
126+
targetFile.parentFile.mkdirs()
127+
targetFile.withOutputStream { out ->
128+
out << zis
129+
}
130+
}
131+
zis.closeEntry()
132+
}
133+
}
134+
zipFile.delete()
135+
}
136+
}
137+
preBuild.dependsOn downloadRuntime

‎Android/library/src/main/java/starray/android/modmanager/ModManager.java‎

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,21 @@
11
package starray.android.modmanager;
22

3+
import android.app.Activity;
4+
import android.content.res.AssetManager;
5+
import android.os.Environment;
36
import android.util.Log;
47
import net.dot.MonoRunner;
58

69
import java.io.File;
10+
import java.io.FileInputStream;
11+
import java.io.FileOutputStream;
12+
import java.io.IOException;
13+
import java.io.InputStreamReader;
14+
import java.io.OutputStream;
15+
import java.nio.file.Files;
16+
import java.nio.file.Path;
17+
import java.nio.file.Paths;
18+
import java.util.Objects;
719

820
/**
921
* ModManager — 封装 CoreCLR 启动。
@@ -17,25 +29,55 @@
1729
public class ModManager {
1830
private static final String TAG = "StArray.ModManager";
1931

32+
private String runtimeDir;
2033
public ModManager() {}
2134

22-
public ModManager dotnetRoot(String path) { MonoRunner.dotnetRoot(path); return this; }
35+
public ModManager dotnetRoot(String path) { MonoRunner.dotnetRoot(path); runtimeDir = path; return this; }
2336
public ModManager addAssemblyDir(String dir) { MonoRunner.addAssemblyDir(dir); return this; }
2437
public ModManager addNativeDir(String dir) { MonoRunner.addNativeDir(dir); return this; }
2538

2639
public int start(String dll, String type, String method,String... args) {
40+
extractRuntime();
2741
Log.i(TAG, "Starting " + dll + " -> " + type + "::" + method);
2842
if (args != null && args.length > 0) return MonoRunner.run(dll, type, method, args);
2943
return MonoRunner.run(dll, type, method);
3044
}
3145

46+
private void extractRuntime(){
47+
if (Files.exists(Paths.get(runtimeDir))){
48+
return;
49+
}
50+
try {
51+
Activity activity = ModManagerUtils.getUnityActivity();
52+
String[] dlls = Objects.requireNonNull(activity).getAssets().list("runtime");
53+
if (!Files.exists(Paths.get(runtimeDir))){
54+
Files.createDirectories(Paths.get(runtimeDir));
55+
}
56+
for (String dll : Objects.requireNonNull(dlls)) {
57+
var fis = activity.getAssets().open(dll);
58+
OutputStream out = new FileOutputStream(Paths.get(runtimeDir,new File(dll).getName()).toFile());
59+
{
60+
byte[] buffer = new byte[8192];
61+
int length;
62+
while ((length = fis.read(buffer)) != -1) {
63+
out.write(buffer, 0, length);
64+
}
65+
}
66+
out.close();
67+
}
68+
} catch (IOException e) {
69+
throw new RuntimeException(e);
70+
}
71+
}
72+
3273
public void stop() { MonoRunner.stop(); }
3374

3475
public static void launch() {
35-
final String runtimeRoot = "/sdcard/ModManager/runtime";
76+
final String esp = Environment.getExternalStorageDirectory().getAbsolutePath();
77+
final String runtimeRoot = esp + "/ModManager/runtime";
3678
final String[] assemblyDirs = {
3779
runtimeRoot,
38-
"/sdcard/ModManager/plugins",
80+
esp + "/ModManager/plugins",
3981
};
4082
final String[] nativeDirs = {
4183
runtimeRoot,
@@ -51,7 +93,7 @@ public void run() {
5193
manager.addAssemblyDir(dir);
5294
for (String dir : nativeDirs)
5395
manager.addNativeDir(dir);
54-
manager.start("StArray.ModManager.dll", "StArray.ModManager.Managed", "Entry",new File(runtimeRoot).getParentFile().getAbsolutePath() + "/mods");
96+
manager.start("StArray.ModManager.dll", "StArray.ModManager.Managed", "Entry", Objects.requireNonNull(new File(runtimeRoot).getParentFile()).getAbsolutePath() + "/mods");
5597
} catch (Exception e) {
5698
Log.e(TAG, "launch failed", e);
5799
}

‎Android/library/src/main/java/starray/android/modmanager/ModManagerUtils.java‎

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,12 @@ public class ModManagerUtils {
2828
private static EditText sHiddenEditText;
2929
private static boolean sEditTextAdded;
3030

31-
private static Activity getUnityActivity() {
31+
public static Activity getUnityActivity() {
3232
try {
3333
Class<?> clazz = Class.forName("com.unity3d.player.UnityPlayer");
3434
return (Activity) clazz.getField("currentActivity").get(null);
3535
} catch (Exception e) {
36-
android.util.Log.e("ModManagerUtils", "getUnityActivity", e);
36+
Log.e("ModManagerUtils", "getUnityActivity", e);
3737
}
3838
return null;
3939
}
@@ -102,11 +102,9 @@ private static void ensureHiddenEditText() {
102102
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
103103
public void onTextChanged(CharSequence s, int start, int before, int count) {}
104104
public void afterTextChanged(Editable s) {
105-
//sendTextToNative(); // 逐字实时同步到 C# 层
106105
}
107106
});
108107

109-
// 加入到 UnityPlayer.getFrameLayout() → 1x1 透明无光标 → requestFocus
110108
try {
111109
Class<?> upClass = Class.forName("com.unity3d.player.UnityPlayer");
112110
Object unityPlayer = upClass.getField("currentActivity").get(null);
@@ -129,13 +127,10 @@ public void afterTextChanged(Editable s) {
129127
}
130128
}
131129

132-
/** 发送 int[] 到 C 层,按 key 路由 */
133130
public static native void nativeSetData(String key, int[] data);
134131

135-
/** 从 C 层获取 int[],按 key 路由 */
136132
public static native int[] nativeGetData(String key);
137133

138-
/** 整量同步 — 把 EditText 当前文本转为 int[] 发送到 C (每字符 = 一个 int) */
139134
public static void sendTextToNative() {
140135
if (sHiddenEditText == null) {
141136
nativeSetData("ime_text", null);

0 commit comments

Comments
 (0)