[{"data":1,"prerenderedAt":992},["ShallowReactive",2],{"navigation_docs":3,"-android-hidden-hardening-dep-isolate":173,"-android-hidden-hardening-dep-isolate-surround":987},[4,22,29,36,107,138,145,161],{"title":5,"icon":6,"path":7,"stem":8,"children":9},"博客","i-lucide-pen-line","\u002Fblog","0.blog",[10,12,17],{"title":5,"path":7,"stem":11,"icon":6},"0.blog\u002Findex",{"title":13,"path":14,"stem":15,"icon":16},"创建基于 UIKit 的原生 iOS 项目","\u002Fblog\u002Fcreate-uikit-ios-project","0.blog\u002F01.create-uikit-ios-project","i-lucide-app-window",{"title":18,"path":19,"stem":20,"icon":21},"Lockify：把账号和密码留在自己的手机里","\u002Fblog\u002Flockify","0.blog\u002F02.lockify","i-lucide-lock",{"title":23,"path":24,"stem":25,"children":26,"icon":28},"年度总结","\u002Fannual-review","1.annual-review\u002Findex",[27],{"title":23,"path":24,"stem":25,"icon":28},"i-lucide-git-commit",{"title":30,"path":31,"stem":32,"children":33,"icon":35},"故事","\u002Fstories","2.stories\u002Findex",[34],{"title":30,"path":31,"stem":32,"icon":35},"i-lucide-feather",{"title":37,"icon":38,"path":39,"stem":40,"children":41},"Android","i-simple-icons-android","\u002Fandroid","3.android",[42,44,49],{"title":37,"path":39,"stem":43,"icon":38},"3.android\u002Findex",{"title":45,"path":46,"stem":47,"icon":48},"初探Navigation","\u002Fandroid\u002Fcompose-navigation","3.android\u002F01.compose-navigation","i-lucide-route",{"title":50,"icon":51,"path":52,"stem":53,"children":54},"安卓代码加固","i-lucide-shield","\u002Fandroid\u002Fhidden-hardening","3.android\u002F02.hidden-hardening\u002Findex",[55,58,62,67,72,77,82,87,92,97,102],{"title":56,"path":52,"stem":53,"icon":57},"安卓代码加固：总览","i-lucide-map",{"title":59,"path":60,"stem":61,"icon":21},"安卓代码加固（1）：加密DEX","\u002Fandroid\u002Fhidden-hardening\u002Fencrypt-dex","3.android\u002F02.hidden-hardening\u002F01.encrypt-dex",{"title":63,"path":64,"stem":65,"icon":66},"安卓代码加固（2）：Native解密","\u002Fandroid\u002Fhidden-hardening\u002Fnative-decrypt","3.android\u002F02.hidden-hardening\u002F02.native-decrypt","i-lucide-cpu",{"title":68,"path":69,"stem":70,"icon":71},"安卓代码加固（3）：内存加载","\u002Fandroid\u002Fhidden-hardening\u002Fmemory-load","3.android\u002F02.hidden-hardening\u002F03.memory-load","i-lucide-memory-stick",{"title":73,"path":74,"stem":75,"icon":76},"安卓代码加固（4）：指令分发","\u002Fandroid\u002Fhidden-hardening\u002Fopcode-dispatch","3.android\u002F02.hidden-hardening\u002F04.opcode-dispatch","i-lucide-hash",{"title":78,"path":79,"stem":80,"icon":81},"安卓代码加固（5）：XOR混淆","\u002Fandroid\u002Fhidden-hardening\u002Fxor-obfuscate","3.android\u002F02.hidden-hardening\u002F05.xor-obfuscate","i-lucide-shuffle",{"title":83,"path":84,"stem":85,"icon":86},"安卓代码加固（6）：密钥外置","\u002Fandroid\u002Fhidden-hardening\u002Fkey-external","3.android\u002F02.hidden-hardening\u002F06.key-external","i-lucide-key",{"title":88,"path":89,"stem":90,"icon":91},"安卓代码加固（7）：依赖隔离","\u002Fandroid\u002Fhidden-hardening\u002Fdep-isolate","3.android\u002F02.hidden-hardening\u002F07.dep-isolate","i-lucide-layers",{"title":93,"path":94,"stem":95,"icon":96},"安卓代码加固（8）：构建校验","\u002Fandroid\u002Fhidden-hardening\u002Fbuild-verify","3.android\u002F02.hidden-hardening\u002F08.build-verify","i-lucide-shield-check",{"title":98,"path":99,"stem":100,"icon":101},"安卓代码加固（9）：防录屏","\u002Fandroid\u002Fhidden-hardening\u002Fflag-secure","3.android\u002F02.hidden-hardening\u002F09.flag-secure","i-lucide-eye-off",{"title":103,"path":104,"stem":105,"icon":106},"安卓代码加固（10）：ABI门禁","\u002Fandroid\u002Fhidden-hardening\u002Fabi-gate","3.android\u002F02.hidden-hardening\u002F10.abi-gate","i-lucide-git-compare",{"title":108,"icon":109,"path":110,"stem":111,"children":112},"iOS","i-simple-icons-apple","\u002Fios","4.ios",[113,115,120,125,129,133],{"title":108,"path":110,"stem":114,"icon":109},"4.ios\u002Findex",{"title":116,"path":117,"stem":118,"icon":119},"iOS面试题1","\u002Fios\u002Fios-interview1","4.ios\u002F01.ios-interview1","i-lucide-sparkles",{"title":121,"path":122,"stem":123,"icon":124},"设置启动图","\u002Fios\u002Fset-launch-screen","4.ios\u002F02.set-launch-screen","i-lucide-image",{"title":126,"path":127,"stem":128,"icon":48},"路由管理","\u002Fios\u002Frouting","4.ios\u002F03.routing",{"title":130,"path":131,"stem":132,"icon":91},"状态管理","\u002Fios\u002Fstate-management","4.ios\u002F04.state-management",{"title":134,"path":135,"stem":136,"icon":137},"事件传递","\u002Fios\u002Fevent-delivery","4.ios\u002F05.event-delivery","i-lucide-pointer",{"title":139,"path":140,"stem":141,"children":142,"icon":144},"Flutter","\u002Fflutter","5.flutter\u002Findex",[143],{"title":139,"path":140,"stem":141,"icon":144},"i-simple-icons-flutter",{"title":146,"icon":147,"path":148,"stem":149,"children":150,"page":160},"面试","i-lucide-graduation-cap","\u002Finterview","6.interview",[151,156],{"title":152,"path":153,"stem":154,"icon":155},"Flutter面试题1","\u002Finterview\u002Fflutter-interview1","6.interview\u002F01.flutter-interview1","i-lucide-boxes",{"title":157,"path":158,"stem":159,"icon":66},"Flutter面试题2","\u002Finterview\u002Fflutter-interview2","6.interview\u002F02.flutter-interview2",false,{"title":162,"icon":163,"path":164,"stem":165,"children":166},"算法学习","i-lucide-binary","\u002Falgorithm","7.algorithm",[167,169],{"title":162,"path":164,"stem":168,"icon":163},"7.algorithm\u002Findex",{"title":170,"path":171,"stem":172},"算法基础1：复杂度分析","\u002Falgorithm\u002Ftime-space-complexity","7.algorithm\u002F01.time-space-complexity",{"id":174,"title":88,"body":175,"description":970,"extension":971,"links":972,"meta":975,"navigation":982,"path":89,"seo":983,"stem":90,"__hash__":986},"docs\u002F3.android\u002F02.hidden-hardening\u002F07.dep-isolate.md",{"type":176,"value":177,"toc":962},"minimark",[178,192,207,211,277,349,353,356,404,415,421,586,596,600,607,747,753,757,764,773,795,803,807,818,938,941,958],[179,180,181,182,186,187,191],"p",{},"即使已经加密，只要宿主使用 ",[183,184,185],"code",{},"implementation(project(\":hidden-landing-page\"))","，明文 class 仍会进入 APK。加固的第一道检查是 ",[188,189,190],"strong",{},"依赖图","，不是算法。",[193,194,195,198,199,202,203,206],"note",{},[183,196,197],{},":hidden-sdk"," 只作为 d8 的 ",[183,200,201],{},"--lib","，接口留在主 DEX。实现进入加密 dex。两边不要互相 ",[183,204,205],{},"implementation","。",[208,209,210],"h2",{"id":210},"模块边界",[212,213,219],"pre",{"className":214,"code":215,"filename":216,"language":217,"meta":218,"style":218},"language-kotlin shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","include(\":app\")\ninclude(\":hidden-sdk\")\ninclude(\":hidden-landing-page\")\ninclude(\":ads\")\n","settings.gradle.kts","kotlin","",[183,220,221,241,253,265],{"__ignoreMap":218},[222,223,226,230,234,238],"span",{"class":224,"line":225},"line",1,[222,227,229],{"class":228},"s2Zo4","include",[222,231,233],{"class":232},"sTEyZ","(",[222,235,237],{"class":236},"sfazB","\":app\"",[222,239,240],{"class":232},")\n",[222,242,244,246,248,251],{"class":224,"line":243},2,[222,245,229],{"class":228},[222,247,233],{"class":232},[222,249,250],{"class":236},"\":hidden-sdk\"",[222,252,240],{"class":232},[222,254,256,258,260,263],{"class":224,"line":255},3,[222,257,229],{"class":228},[222,259,233],{"class":232},[222,261,262],{"class":236},"\":hidden-landing-page\"",[222,264,240],{"class":232},[222,266,268,270,272,275],{"class":224,"line":267},4,[222,269,229],{"class":228},[222,271,233],{"class":232},[222,273,274],{"class":236},"\":ads\"",[222,276,240],{"class":232},[278,279,280,293],"table",{},[281,282,283],"thead",{},[284,285,286,290],"tr",{},[287,288,289],"th",{},"写法",[287,291,292],{},"结果",[294,295,296,308,318,329,339],"tbody",{},[284,297,298,305],{},[299,300,301,302],"td",{},"宿主 ",[183,303,304],{},"implementation(hidden-sdk)",[299,306,307],{},"正确。接口在主 dex，实现在 AAR assets",[284,309,310,315],{},[299,311,301,312],{},[183,313,314],{},"implementation(hidden-landing-page)",[299,316,317],{},"明文 class 进入 APK",[284,319,320,326],{},[299,321,322,323],{},"landing-page ",[183,324,325],{},"implementation(:hidden-sdk)",[299,327,328],{},"SDK 类打进加密 dex，体积变大且无必要",[284,330,331,336],{},[299,332,322,333],{},[183,334,335],{},"compileOnly(:hidden-sdk)",[299,337,338],{},"本仓库内部正确",[284,340,341,346],{},[299,342,301,343],{},[183,344,345],{},"import com.example.minidex.hidden",[299,347,348],{},"编译期把实现引用写进主 dex",[208,350,352],{"id":351},"强制-compileonly","强制 compileOnly",[179,354,355],{},"landing-page 模块的头注释和依赖固定了方向：",[212,357,360],{"className":214,"code":358,"filename":359,"language":217,"meta":218,"style":218},"\u002F\u002F 不要被宿主以 implementation \u002F api \u002F runtimeOnly 依赖，否则明文会进 APK。\n\u002F\u002F 对 :hidden-sdk 只能 compileOnly：接口进宿主，实现进加密 dex。\ndependencies {\n    compileOnly(project(\":hidden-sdk\"))\n}\n","hidden-landing-page\u002Fbuild.gradle.kts",[183,361,362,368,373,381,398],{"__ignoreMap":218},[222,363,364],{"class":224,"line":225},[222,365,367],{"class":366},"sHwdD","\u002F\u002F 不要被宿主以 implementation \u002F api \u002F runtimeOnly 依赖，否则明文会进 APK。\n",[222,369,370],{"class":224,"line":243},[222,371,372],{"class":366},"\u002F\u002F 对 :hidden-sdk 只能 compileOnly：接口进宿主，实现进加密 dex。\n",[222,374,375,378],{"class":224,"line":255},[222,376,377],{"class":228},"dependencies",[222,379,380],{"class":232}," {\n",[222,382,383,386,388,391,393,395],{"class":224,"line":267},[222,384,385],{"class":228},"    compileOnly",[222,387,233],{"class":232},[222,389,390],{"class":228},"project",[222,392,233],{"class":232},[222,394,250],{"class":236},[222,396,397],{"class":232},"))\n",[222,399,401],{"class":224,"line":400},5,[222,402,403],{"class":232},"}\n",[179,405,406,407,410,411,414],{},"它还需要 SDK 里的 ",[183,408,409],{},"HiddenIncomingKeepAlive","。Service 和 Receiver 必须留在主 DEX，供系统拉起。",[183,412,413],{},"compileOnly"," 让编译期能解析这些符号，运行时由宿主 ClassLoader 提供，class 不会打进 jar。",[179,416,417,418,420],{},"解析期再加一层检查：运行时相关的 configuration 里如果出现 ",[183,419,197],{},"，直接失败：",[212,422,424],{"className":214,"code":423,"filename":359,"language":217,"meta":218,"style":218},"configurations.configureEach {\n    val runtimeLike = configurationName.contains(\"Implementation\") ||\n        configurationName.contains(\"Runtime\") ||\n        configurationName == \"api\" ||\n        configurationName.endsWith(\"Api\")\n    if (!runtimeLike) return@configureEach\n    incoming.afterResolve {\n        check(leaked.isEmpty()) {\n            \":hidden-landing-page 把 :hidden-sdk 放进了 $configurationName。必须 compileOnly。\"\n        }\n    }\n}\n",[183,425,426,436,465,481,495,509,531,542,557,569,575,581],{"__ignoreMap":218},[222,427,428,431,434],{"class":224,"line":225},[222,429,430],{"class":232},"configurations.",[222,432,433],{"class":228},"configureEach",[222,435,380],{"class":232},[222,437,438,442,445,448,451,454,456,459,462],{"class":224,"line":243},[222,439,441],{"class":440},"sMK4o","    val",[222,443,444],{"class":232}," runtimeLike ",[222,446,447],{"class":440},"=",[222,449,450],{"class":232}," configurationName.",[222,452,453],{"class":228},"contains",[222,455,233],{"class":232},[222,457,458],{"class":236},"\"Implementation\"",[222,460,461],{"class":232},") ",[222,463,464],{"class":440},"||\n",[222,466,467,470,472,474,477,479],{"class":224,"line":255},[222,468,469],{"class":232},"        configurationName.",[222,471,453],{"class":228},[222,473,233],{"class":232},[222,475,476],{"class":236},"\"Runtime\"",[222,478,461],{"class":232},[222,480,464],{"class":440},[222,482,483,486,489,492],{"class":224,"line":267},[222,484,485],{"class":232},"        configurationName ",[222,487,488],{"class":440},"==",[222,490,491],{"class":236}," \"api\"",[222,493,494],{"class":440}," ||\n",[222,496,497,499,502,504,507],{"class":224,"line":400},[222,498,469],{"class":232},[222,500,501],{"class":228},"endsWith",[222,503,233],{"class":232},[222,505,506],{"class":236},"\"Api\"",[222,508,240],{"class":232},[222,510,512,516,519,522,525,528],{"class":224,"line":511},6,[222,513,515],{"class":514},"s7zQu","    if",[222,517,518],{"class":232}," (",[222,520,521],{"class":440},"!",[222,523,524],{"class":232},"runtimeLike) ",[222,526,527],{"class":514},"return",[222,529,530],{"class":232},"@configureEach\n",[222,532,534,537,540],{"class":224,"line":533},7,[222,535,536],{"class":232},"    incoming.",[222,538,539],{"class":228},"afterResolve",[222,541,380],{"class":232},[222,543,545,548,551,554],{"class":224,"line":544},8,[222,546,547],{"class":228},"        check",[222,549,550],{"class":232},"(leaked.",[222,552,553],{"class":228},"isEmpty",[222,555,556],{"class":232},"()) {\n",[222,558,560,563,566],{"class":224,"line":559},9,[222,561,562],{"class":236},"            \":hidden-landing-page 把 :hidden-sdk 放进了 ",[222,564,565],{"class":232},"$configurationName",[222,567,568],{"class":236},"。必须 compileOnly。\"\n",[222,570,572],{"class":224,"line":571},10,[222,573,574],{"class":232},"        }\n",[222,576,578],{"class":224,"line":577},11,[222,579,580],{"class":232},"    }\n",[222,582,584],{"class":224,"line":583},12,[222,585,403],{"class":232},[179,587,588,591,592,595],{},[183,589,590],{},":app"," 做对称检查：任何 runtime configuration 解析到 ",[183,593,594],{},":hidden-landing-page"," 就失败。",[208,597,599],{"id":598},"禁止源码-import","禁止源码 import",[179,601,602,603,606],{},"即使没有写 Gradle 依赖，只要有人把实现类拷进 app 源码并 import，主 dex 仍会留下类描述符。",[183,604,605],{},"preBuild"," 会扫描全部 kt\u002Fjava 文件：",[212,608,611],{"className":214,"code":609,"filename":610,"language":217,"meta":218,"style":218},"tasks.register(\"verifyAppDoesNotImportHiddenLandingPage\") {\n    doLast {\n        val forbidden = Regex(\"\"\"import\\s+com\\.example\\.minidex\\.hidden\\b\"\"\")\n        check(offenders.isEmpty()) {\n            \":app 不能 import hidden-landing-page，请走 HiddenSdk.invoke。\"\n        }\n    }\n}\ntasks.named(\"preBuild\").configure {\n    dependsOn(\"verifyAppDoesNotImportHiddenLandingPage\")\n}\n","app\u002Fbuild.gradle.kts",[183,612,613,629,636,684,695,700,704,708,712,732,743],{"__ignoreMap":218},[222,614,615,618,621,623,626],{"class":224,"line":225},[222,616,617],{"class":232},"tasks.",[222,619,620],{"class":228},"register",[222,622,233],{"class":232},[222,624,625],{"class":236},"\"verifyAppDoesNotImportHiddenLandingPage\"",[222,627,628],{"class":232},") {\n",[222,630,631,634],{"class":224,"line":243},[222,632,633],{"class":228},"    doLast",[222,635,380],{"class":232},[222,637,638,641,644,646,649,651,654,657,660,663,666,668,671,673,676,679,682],{"class":224,"line":255},[222,639,640],{"class":440},"        val",[222,642,643],{"class":232}," forbidden ",[222,645,447],{"class":440},[222,647,648],{"class":228}," Regex",[222,650,233],{"class":232},[222,652,653],{"class":236},"\"\"\"import",[222,655,656],{"class":232},"\\s",[222,658,659],{"class":236},"+com",[222,661,662],{"class":232},"\\.",[222,664,665],{"class":236},"example",[222,667,662],{"class":232},[222,669,670],{"class":236},"minidex",[222,672,662],{"class":232},[222,674,675],{"class":236},"hidden",[222,677,678],{"class":232},"\\b",[222,680,681],{"class":236},"\"\"\"",[222,683,240],{"class":232},[222,685,686,688,691,693],{"class":224,"line":267},[222,687,547],{"class":228},[222,689,690],{"class":232},"(offenders.",[222,692,553],{"class":228},[222,694,556],{"class":232},[222,696,697],{"class":224,"line":400},[222,698,699],{"class":236},"            \":app 不能 import hidden-landing-page，请走 HiddenSdk.invoke。\"\n",[222,701,702],{"class":224,"line":511},[222,703,574],{"class":232},[222,705,706],{"class":224,"line":533},[222,707,580],{"class":232},[222,709,710],{"class":224,"line":544},[222,711,403],{"class":232},[222,713,714,716,719,721,724,727,730],{"class":224,"line":559},[222,715,617],{"class":232},[222,717,718],{"class":228},"named",[222,720,233],{"class":232},[222,722,723],{"class":236},"\"preBuild\"",[222,725,726],{"class":232},").",[222,728,729],{"class":228},"configure",[222,731,380],{"class":232},[222,733,734,737,739,741],{"class":224,"line":571},[222,735,736],{"class":228},"    dependsOn",[222,738,233],{"class":232},[222,740,625],{"class":236},[222,742,240],{"class":232},[222,744,745],{"class":224,"line":577},[222,746,403],{"class":232},[179,748,749,750,206],{},"宿主只允许 ",[183,751,752],{},"com.example.minidex.sdk.*",[208,754,756],{"id":755},"保留必须-keep-的入口","保留必须 keep 的入口",[179,758,759,760,763],{},"AAR 带有 ",[183,761,762],{},"consumer-rules.pro","。宿主开启 R8 时，不能把 JNI 入口和系统要反射的占位类 shrink 掉：",[212,765,771],{"className":766,"code":768,"filename":769,"language":770,"meta":218},[767],"language-text","-keep class com.example.minidex.sdk.HiddenSdk { *; }\n-keep class com.example.minidex.sdk.HiddenInitResult { *; }\n-keep class com.example.minidex.sdk.HiddenInitResult$Code { *; }\n-keep class com.example.minidex.sdk.internal.HiddenIncomingKeepAlive { *; }\n-keep class com.example.minidex.sdk.internal.HiddenIncomingKeepAliveService { *; }\n-keep class com.example.minidex.sdk.internal.HiddenIncomingAlarmReceiver { *; }\n-keep class com.example.minidex.sdk.internal.HiddenDecrypt { *; }\n-keep class com.example.minidex.sdk.internal.HiddenCrypto { *; }\n","hidden-sdk\u002Fconsumer-rules.pro","text",[183,772,768],{"__ignoreMap":218},[179,774,775,778,779,782,783,786,787,790,791,794],{},[183,776,777],{},"HiddenSdk"," 的 ",[183,780,781],{},"nativeInit"," \u002F ",[183,784,785],{},"nativeDispatch"," 按类名 + 方法名绑定。R8 改名后 so 会 ",[183,788,789],{},"UnsatisfiedLinkError","。KeepAlive 相关类由系统 ",[183,792,793],{},"Intent"," 拉起，也必须留名。",[796,797,798,799,802],"warning",{},"这些规则是为了保留入口，不是把实现 keep 进主 DEX。实现类本来就不在 ",[183,800,801],{},"classes.jar"," 里。",[208,804,806],{"id":805},"复用时不要拆-aar","复用时不要拆 AAR",[179,808,809,810,813,814,817],{},"其他工程 ",[188,811,812],{},"不要"," ",[183,815,816],{},"include(\":hidden-landing-page\")","，也不要解压 AAR 再单独拷贝 payload。",[819,820,821,854,871],"code-group",{},[212,822,825],{"className":214,"code":823,"filename":824,"language":217,"meta":218,"style":218},"dependencies {\n    implementation(files(\"libs\u002Fhidden-sdk-1.0.0.aar\"))\n}\n","拖拽 AAR",[183,826,827,833,850],{"__ignoreMap":218},[222,828,829,831],{"class":224,"line":225},[222,830,377],{"class":228},[222,832,380],{"class":232},[222,834,835,838,840,843,845,848],{"class":224,"line":243},[222,836,837],{"class":228},"    implementation",[222,839,233],{"class":232},[222,841,842],{"class":228},"files",[222,844,233],{"class":232},[222,846,847],{"class":236},"\"libs\u002Fhidden-sdk-1.0.0.aar\"",[222,849,397],{"class":232},[222,851,852],{"class":224,"line":255},[222,853,403],{"class":232},[212,855,858],{"className":214,"code":856,"filename":857,"language":217,"meta":218,"style":218},"implementation(\"com.example.minidex:hidden-sdk:1.0.0\")\n","Maven",[183,859,860],{"__ignoreMap":218},[222,861,862,864,866,869],{"class":224,"line":225},[222,863,205],{"class":228},[222,865,233],{"class":232},[222,867,868],{"class":236},"\"com.example.minidex:hidden-sdk:1.0.0\"",[222,870,240],{"class":232},[212,872,875],{"className":214,"code":873,"filename":874,"language":217,"meta":218,"style":218},"includeBuild(\"..\u002Fhidden-dex-minidemo\") {\n    dependencySubstitution {\n        substitute(module(\"com.example.minidex:hidden-sdk\"))\n            .using(project(\":hidden-sdk\"))\n    }\n}\n","includeBuild",[183,876,877,888,895,912,930,934],{"__ignoreMap":218},[222,878,879,881,883,886],{"class":224,"line":225},[222,880,874],{"class":228},[222,882,233],{"class":232},[222,884,885],{"class":236},"\"..\u002Fhidden-dex-minidemo\"",[222,887,628],{"class":232},[222,889,890,893],{"class":224,"line":243},[222,891,892],{"class":228},"    dependencySubstitution",[222,894,380],{"class":232},[222,896,897,900,902,905,907,910],{"class":224,"line":255},[222,898,899],{"class":228},"        substitute",[222,901,233],{"class":232},[222,903,904],{"class":228},"module",[222,906,233],{"class":232},[222,908,909],{"class":236},"\"com.example.minidex:hidden-sdk\"",[222,911,397],{"class":232},[222,913,914,917,920,922,924,926,928],{"class":224,"line":267},[222,915,916],{"class":232},"            .",[222,918,919],{"class":228},"using",[222,921,233],{"class":232},[222,923,390],{"class":228},[222,925,233],{"class":232},[222,927,250],{"class":236},[222,929,397],{"class":232},[222,931,932],{"class":224,"line":400},[222,933,580],{"class":232},[222,935,936],{"class":224,"line":511},[222,937,403],{"class":232},[208,939,940],{"id":940},"下一步",[942,943,944,952],"ul",{},[945,946,947,951],"li",{},[948,949,950],"a",{"href":94},"构建校验","：打包后再扫一遍 APK \u002F AAR",[945,953,954,957],{},[948,955,956],{"href":52},"总览","：模块与产物对照",[959,960,961],"style",{},"html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}",{"title":218,"searchDepth":243,"depth":243,"links":963},[964,965,966,967,968,969],{"id":210,"depth":243,"text":210},{"id":351,"depth":243,"text":352},{"id":598,"depth":243,"text":599},{"id":755,"depth":243,"text":756},{"id":805,"depth":243,"text":806},{"id":940,"depth":243,"text":940},"宿主只 implementation hidden-sdk。landing-page 对 SDK 必须 compileOnly，明文 class 不准进入 APK。","md",[973,974],{"label":93,"icon":96,"to":94},{"label":73,"icon":76,"to":74},{"date":976,"categories":977,"tags":979},"2026-09-21",[978],"android",[37,980,981],"Gradle","模块",{"icon":91},{"title":984,"description":985},"安卓代码加固（7）：Hidden DEX 模块依赖隔离","hidden-dex-minidemo 用 compileOnly、解析期检查和禁止 import，保证 HiddenLandingPage 只出现在加密 payload，不进入主 DEX。","qD38-m6eMXbxfjVmNjwaPNQwaGTCqcDUKYc9ZDtDlRg",[988,990],{"title":83,"path":84,"stem":85,"description":989,"icon":86,"children":-1},"SDK \u002F AAR 不带 AES 密钥。CI 用环境变量，本地 debug 用 gitignore 文件。",{"title":93,"path":94,"stem":95,"description":991,"icon":96,"children":-1},"assemble 之后检查 AAR \u002F APK：无明文 HiddenLandingPage，有 HDX1 payload 和 so。",1790767046719]