Skip to content

Commit

Permalink
Feature: Hot Update Translation (#32)
Browse files Browse the repository at this point in the history
* update translation data from repo
  • Loading branch information
chinosk6 authored Jun 27, 2024
1 parent 91dea41 commit dbb7c8d
Show file tree
Hide file tree
Showing 21 changed files with 994 additions and 41 deletions.
6 changes: 5 additions & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ android {
minSdk 29
targetSdk 34
versionCode 2
versionName "v1.1"
versionName "v1.2"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
Expand Down Expand Up @@ -112,6 +112,10 @@ dependencies {
implementation "io.coil-kt:coil-compose:2.6.0"
implementation "io.coil-kt:coil-svg:2.6.0"

implementation(platform("com.squareup.okhttp3:okhttp-bom:4.12.0"))
implementation "com.squareup.okhttp3:okhttp"
implementation "com.squareup.okhttp3:logging-interceptor"

implementation 'io.github.hexhacking:xdl:2.1.1'
implementation 'com.bytedance.android:shadowhook:1.0.9'
compileOnly 'de.robv.android.xposed:api:82'
Expand Down
11 changes: 11 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:usesCleartextTraffic="true"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
Expand Down Expand Up @@ -42,6 +43,16 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
</application>

</manifest>
2 changes: 1 addition & 1 deletion app/src/main/assets/gakumas-local
11 changes: 8 additions & 3 deletions app/src/main/cpp/GakumasLocalify/Hook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,11 @@ namespace GakumasLocal::HookMain {

void* fontCache = nullptr;
void* GetReplaceFont() {
static std::string fontName = Local::GetBasePath() / "local-files" / "gkamsZHFontMIX.otf";
if (!std::filesystem::exists(fontName)) {
return nullptr;
}

static auto CreateFontFromPath = reinterpret_cast<void (*)(void* self, Il2cppString* path)>(
Il2cppUtils::il2cpp_resolve_icall("UnityEngine.Font::Internal_CreateFontFromPath(UnityEngine.Font,System.String)")
);
Expand All @@ -315,7 +320,6 @@ namespace GakumasLocal::HookMain {
const auto newFont = Font_klass->New<void*>();
Font_ctor->Invoke<void>(newFont);

static std::string fontName = Local::GetBasePath() / "local-files" / "gkamsZHFontMIX.otf";
CreateFontFromPath(newFont, Il2cppString::New(fontName));
fontCache = newFont;
return newFont;
Expand All @@ -334,9 +338,10 @@ namespace GakumasLocal::HookMain {
static auto UpdateFontAssetData = Il2cppUtils::GetMethod("Unity.TextMeshPro.dll", "TMPro",
"TMP_FontAsset", "UpdateFontAssetData");

auto fontAsset = get_font->Invoke<void*>(TMP_Textself);
auto newFont = GetReplaceFont();
if (fontAsset && newFont) {
if (!newFont) return;
auto fontAsset = get_font->Invoke<void*>(TMP_Textself);
if (fontAsset) {
set_sourceFontFile->Invoke<void>(fontAsset, newFont);
if (!updatedFontPtrs.contains(fontAsset)) {
updatedFontPtrs.emplace(fontAsset);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import io.github.chinosk.gakumas.localify.databinding.ActivityMainBinding
import io.github.chinosk.gakumas.localify.models.GakumasConfig
import io.github.chinosk.gakumas.localify.models.ProgramConfig
import io.github.chinosk.gakumas.localify.models.ProgramConfigViewModel
import io.github.chinosk.gakumas.localify.models.ProgramConfigViewModelFactory
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
Expand Down Expand Up @@ -55,6 +58,15 @@ interface ConfigListener {
fun onBUseArmCorrectionChanged(value: Boolean)
fun onBUseScaleChanged(value: Boolean)
fun onBClickPresetChanged(index: Int)
fun onPCheckBuiltInAssetsChanged(value: Boolean)
fun onPUseRemoteAssetsChanged(value: Boolean)
fun onPCleanLocalAssetsChanged(value: Boolean)
fun onPDelRemoteAfterUpdateChanged(value: Boolean)
fun onPTransRemoteZipUrlChanged(s: CharSequence, start: Int, before: Int, count: Int)
fun mainPageAssetsViewDataUpdate(downloadAbleState: Boolean? = null,
downloadProgressState: Float? = null,
localResourceVersionState: String? = null,
errorString: String? = null)
}

class UserConfigViewModelFactory(private val initialValue: GakumasConfig) : ViewModelProvider.Factory {
Expand All @@ -78,10 +90,15 @@ interface ConfigUpdateListener: ConfigListener {
var factory: UserConfigViewModelFactory
var viewModel: UserConfigViewModel

var programConfig: ProgramConfig
var programConfigFactory: ProgramConfigViewModelFactory
var programConfigViewModel: ProgramConfigViewModel

fun pushKeyEvent(event: KeyEvent): Boolean
fun getConfigContent(): String
fun checkConfigAndUpdateView()
fun saveConfig()
fun saveProgramConfig()


override fun onEnabledChanged(value: Boolean) {
Expand Down Expand Up @@ -493,4 +510,37 @@ interface ConfigUpdateListener: ConfigListener {
saveConfig()
}

override fun onPCheckBuiltInAssetsChanged(value: Boolean) {
programConfig.checkBuiltInAssets = value
saveProgramConfig()
}

override fun onPUseRemoteAssetsChanged(value: Boolean) {
programConfig.useRemoteAssets = value
saveProgramConfig()
}

override fun onPCleanLocalAssetsChanged(value: Boolean) {
programConfig.cleanLocalAssets = value
saveProgramConfig()
}

override fun onPDelRemoteAfterUpdateChanged(value: Boolean) {
programConfig.delRemoteAfterUpdate = value
saveProgramConfig()
}

override fun onPTransRemoteZipUrlChanged(s: CharSequence, start: Int, before: Int, count: Int) {
programConfig.transRemoteZipUrl = s.toString()
saveProgramConfig()
}

override fun mainPageAssetsViewDataUpdate(downloadAbleState: Boolean?, downloadProgressState: Float?,
localResourceVersionState: String?, errorString: String?) {
downloadAbleState?.let { programConfigViewModel.downloadAbleState.value = downloadAbleState }
downloadProgressState?.let{ programConfigViewModel.downloadProgressState.value = downloadProgressState }
localResourceVersionState?.let{ programConfigViewModel.localResourceVersionState.value = localResourceVersionState }
errorString?.let{ programConfigViewModel.errorStringState.value = errorString }
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,19 @@ import android.net.Uri
import android.os.Handler
import android.os.Looper
import android.util.Log
import android.view.KeyEvent
import android.view.MotionEvent
import android.widget.Toast
import com.bytedance.shadowhook.ShadowHook
import com.bytedance.shadowhook.ShadowHook.ConfigBuilder
import com.google.gson.Gson
import de.robv.android.xposed.IXposedHookLoadPackage
import de.robv.android.xposed.IXposedHookZygoteInit
import de.robv.android.xposed.XC_MethodHook
import de.robv.android.xposed.XposedBridge
import de.robv.android.xposed.XposedHelpers
import de.robv.android.xposed.callbacks.XC_LoadPackage
import io.github.chinosk.gakumas.localify.hookUtils.FilesChecker
import android.view.KeyEvent
import android.view.MotionEvent
import android.widget.Toast
import com.google.gson.Gson
import de.robv.android.xposed.XposedBridge
import io.github.chinosk.gakumas.localify.models.GakumasConfig
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
Expand All @@ -33,6 +33,11 @@ import kotlinx.coroutines.launch
import java.io.File
import java.util.Locale
import kotlin.system.measureTimeMillis
import android.content.ContentResolver
import io.github.chinosk.gakumas.localify.hookUtils.FileHotUpdater
import io.github.chinosk.gakumas.localify.models.ProgramConfig
import java.io.BufferedReader
import java.io.InputStreamReader

val TAG = "GakumasLocalify"

Expand All @@ -46,6 +51,7 @@ class GakumasHookMain : IXposedHookLoadPackage, IXposedHookZygoteInit {
private var gkmsDataInited = false

private var getConfigError: Exception? = null
private var externalFilesChecked: Boolean = false

override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) {
// if (lpparam.packageName == "io.github.chinosk.gakumas.localify") {
Expand Down Expand Up @@ -183,7 +189,7 @@ class GakumasHookMain : IXposedHookLoadPackage, IXposedHookZygoteInit {
requestConfig(app.applicationContext)
}

FilesChecker.initAndCheck(app.filesDir, modulePath)
FilesChecker.initDir(app.filesDir, modulePath)
initHook(
"${app.applicationInfo.nativeLibraryDir}/libil2cpp.so",
File(
Expand Down Expand Up @@ -215,6 +221,7 @@ class GakumasHookMain : IXposedHookLoadPackage, IXposedHookZygoteInit {
fun initGkmsConfig(activity: Activity) {
val intent = activity.intent
val gkmsData = intent.getStringExtra("gkmsData")
val programData = intent.getStringExtra("localData")
if (gkmsData != null) {
gkmsDataInited = true
val initConfig = try {
Expand All @@ -223,10 +230,41 @@ class GakumasHookMain : IXposedHookLoadPackage, IXposedHookZygoteInit {
catch (e: Exception) {
null
}
val programConfig = try {
Gson().fromJson(programData, ProgramConfig::class.java)
}
catch (e: Exception) {
null
}

// 清理本地文件
if (programConfig?.cleanLocalAssets == true) {
FilesChecker.cleanAssets()
}

// 检查 files 版本和 assets 版本并更新
if (programConfig?.checkBuiltInAssets == true) {
FilesChecker.initAndCheck(activity.filesDir, modulePath)
}

// 强制导出 assets 文件
if (initConfig?.forceExportResource == true) {
FilesChecker.updateFiles()
}

// 使用热更新文件
if (programConfig?.useRemoteAssets == true) {
val dataUri = intent.data
if (dataUri != null) {
if (!externalFilesChecked) {
externalFilesChecked = true
// Log.d(TAG, "dataUri: $dataUri")
FileHotUpdater.updateFilesFromZip(activity, dataUri, activity.filesDir,
programConfig.delRemoteAfterUpdate)
}
}
}

loadConfig(gkmsData)
Log.d(TAG, "gkmsData: $gkmsData")
}
Expand Down
Loading

0 comments on commit dbb7c8d

Please sign in to comment.