From 109ad813e613607b5eadc08781922890a16f2ad3 Mon Sep 17 00:00:00 2001 From: LukeMackin Date: Sun, 19 Jul 2026 15:18:30 +0800 Subject: [PATCH] =?UTF-8?q?fix(android):=20APK=E5=8C=85=E5=90=8D=E7=BB=9F?= =?UTF-8?q?=E4=B8=80gca-v0.1.0=20+=20=E5=BA=94=E7=94=A8=E5=90=8D=E5=8A=A0?= =?UTF-8?q?=E7=89=88=E6=9C=AC=20+=20Gitea=20manifest=E8=81=94=E8=B0=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - APK: app-debug.apk → gca-v0.1.0-debug.apk - App名: Yuzu GCA Test → Yuzu GCA v0.1.0 - MainActivity: 真实manifest拉取+JSON解析+SHA256真实比对 - Gitea Release #6: gca-v0.1.0.apk + manifest.json - 删除旧Expo modules/ 文件 --- .gitignore | 1 + .../executionHistory/executionHistory.bin | Bin 649360 -> 804154 bytes .../executionHistory/executionHistory.lock | Bin 17 -> 17 bytes .../.gradle/8.10.2/fileHashes/fileHashes.bin | Bin 43647 -> 43847 bytes .../.gradle/8.10.2/fileHashes/fileHashes.lock | Bin 17 -> 17 bytes .../8.10.2/fileHashes/resourceHashesCache.bin | Bin 18769 -> 18803 bytes .../buildOutputCleanup.lock | Bin 17 -> 17 bytes .../android/.gradle/file-system.probe | Bin 8 -> 8 bytes .../client-android/android/app/build.gradle | 4 +- .../android/app/src/main/AndroidManifest.xml | 4 +- .../main/java/dev/yuzu/gca/MainActivity.kt | 51 +++++++++---- .../app/src/main/res/values/strings.xml | 2 +- packages/client-android/manifest.json | 8 +- .../dev/yuzu/gca/PackageInstallerModule.kt | 69 ------------------ .../package-installer/expo-module.config.json | 4 - 15 files changed, 49 insertions(+), 94 deletions(-) delete mode 100644 packages/client-android/modules/package-installer/android/src/main/java/dev/yuzu/gca/PackageInstallerModule.kt delete mode 100644 packages/client-android/modules/package-installer/expo-module.config.json diff --git a/.gitignore b/.gitignore index 30ec341..05285f9 100644 --- a/.gitignore +++ b/.gitignore @@ -45,3 +45,4 @@ android/build/ *.jks *.keystore local.properties +screen.png diff --git a/packages/client-android/android/.gradle/8.10.2/executionHistory/executionHistory.bin b/packages/client-android/android/.gradle/8.10.2/executionHistory/executionHistory.bin index 9a7f9a13025dd0ed62dde9f68718b7a746ff65ac..244c4b241bfd520f2bd66d8c28390f1f817f60c8 100644 GIT binary patch delta 7256 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 delta 9865 zcmbuF2{cr1{QqZ$VFuq!_BG0u>=9Yo?6g@zNy$!(eQVK3p|WPXSwf^mQiQQ@DJrt3 zvP2|Ah3w>i@16P1{igr#oZtWao%5VC_qpbE-=Fn)?!8lfLm{?ZB9>z_3jE_l;hra= zPzTt+&sz%)yyw1YBoNQbvjbCoHC~5D7ejwPK8mM`4u5i6{9#@lItD>Pd?IfY9fLbD zUW_k?AMe+)PW>}Z6R*|`UoC~GDD0<+_%D2?=omyhp6T#s9s}yhIDXM#F8xiiYi+}V za}E=P!wP3N5jM`CYJllAjBtFCryMXT!ys}c$um636HQL?#GDKxY~6xT?u&33J53!2Xz%)Ib5-@0u#{*dlm=^x1pZDt*6qkkQ z(J0KdEJaY=7I1Ju1E?e81hx^2pXOONszp|7m+D6^`ew5bHqHP;&v8<~(It#LpwWPn zCWD`5Fn{YYUd5OaHtGS2Rx!hT4`C6kpav9H1k}KE4;<;xplJAI9O7^MVXSGKzr}lO zr$eX+VdD(>#~P-O;eUBi@?I>RCz^wk)tpN=x5UVg=ag|J`gO_b+WmUK>ONM?F3m?B z9cY@`sDjV^XxFCdG7p|vP;5Zcp$JFctQ?%0zZE2z_Fdi7TP+KmiWZ%_rW!}@+bi;g zs90U`2^~Rn@OE0*ul|1J-Ck?D~l3eyt}jxcDzUKDu|=VI|YkooAvE$X=^^-mVp zvk^8YzbMpF- z#>{6Yp59{=3uAI2OqINIX!pqZzGP?IpctwBQ8B{tK{!4XIqThkX(5mI%!i|`vNBp3 z#)&YeX&cD#$K)Bbe9K!~=9+oY9FXRKV9q0$^AwEPUa~yLmS3zB?>Dh|<0IvBVa!`W zI&l;sSw!lI@$u(Z%6YZ?Fk9$kP&cWrwUzSmmO5nP>yAzYj8*74NGL*{|3aDJkArg~ zraw*GMaTcS0duMZK{;^}2Y+W;{uD0dRKBOn5`Kdw$JT)+$JT)&M?PDjUi=8tTCvE2 zXE7;qp%KP>5dtyGybWyz9BtPbgE@N)YVTwr7$*|KaiVZCW!#C5XBkx2Elvjm&xdl_ zU{0bi$hmWY{;<91KtW4W=Sm%mdV_#Gc+shj5T!*;0cw9Dep~oPla>W~{-0hel;q56mfryrUCnAL+_< zWH44qcVO+t7GE01&W0w(&W0jqFqT{yVz?Y2?ZVB!KhaNd2F4T!l0eQq{;4rRt+;S4 z+)DnFU%N684kE{nDkr+85?0aR}3_{a9eIIL8<%{l5^mZ-npXONXOGR@}~u7 z)X&o}_J|yNsvJU+=F#>akBfLnL&ZYBcmJx*gE`-z(kjdNiaoO3PG~20HA^nvF9O0r zf^JU@xhd;xdPAKSk1~T)PtM74<9ru-^j>Q$A{;h5YcNy;kX6QI- zW>XF+IPs+AGx@LR8x64HeWHiW$_rs!FJv7$Hf!xEE;aP2yl?4e$1D=#A3UuCfAF*p zP`=ag=*$nB^M*zdFG@CQy$^ADV!=3nwi zu)aHR8;14eD*fgzl{0dwV!7h0@~BMm51zr1KX?X5{^G&7D#Y9$s*QEl)!ikxCmv1* zb@x~Ofjh2+CjHla$F(Rt<|@+z`79FqGqeeHYAPyTH(_~e-k`ZhiSaYa1ygA+8C5Qc zU+oz|qKf3I12tD2Exp-pMr$%PRjhujlHBS)0n4g`auvJBN>6Zm-QEaN2xq*Nxp)?$ z%SXoB%oH&bKBUN6c%7_-;fyL!SAB8+jfQGX8XSdOh{qDGV7HFClgPcpL|ptI?^#5a zFOqD&6by?L=FA!9C3(-bxP)h<^u}LPu&y$QGvUy$aOhhB=SS9T<*MrjNdI;4LpXjE zPLKJ4Hr!B#N58Qiv-E*b_a88(2Ew!tq1f85Ta?IYbiLN>(;A}5aYRbd5iUir|0+$V z4jd*~f6(TAk$C?#nI#1Fb|Ta`??<`cNOu-<%GNTRo-=qig>YPGavWVKa+*}rPOZ(~ zQ13CYbl|f*;v5NMA|N@WhNeN)N|rCx9(Qn_?Ap=@#vAFsj?`6-KJ|2hWSGyPo;NOo z&*v@*CcvDR5Qj5c^tQ#(!l?H`rPc#)b~n+2=IAZs{h!jI98zQ%=6bc%-jU&EPTifk zSUVi_9`;fTgp=?R`a}wt4QME>v3~nAeefeqmlM(=oZKiJg~Y2{SEF|lrH;w}LJ1d6 z=EAaGL!1uAj>pgQZG{I!oZetAZ_+_9NYI?9L3>A+7$CgpH9FIy-o2H5`m_9Fm{SdP znzolu&b+Ex3b4KvB${EwxQP0f44zq<03r90*vF zd?Fk5I0d#V1lpbIjA@S*ohLas;?ze5wX3(GVyG?3+1}Gd#$O2?|K~Bqz+|nwojq&| z9S67Ow_X0sB$f&b>w

F9pgpN;N~yobZ&?S$0)>J;-Q64y*_!rga1V2lC=G48|)88nxmYN&5koQ4NB;L@r^3Kx)h$r zu78Jvto8=R+=u)ve}`26iB3!Htp#s}LT9=?vVJ-v4tJ(HoVO-Ru%A?wmT$s0BFBbW zX@fcQ5a&eG$w5uLE$5!F@YH!lC1ymv9(kPd}0`y0*e4I4zDqN6@8)zFPIKQyFi2~2p|mym7~~rzr4{rauo#ljTY))?(2C$Wwg2(8 zv#ZBM&CVngs|^n$9HbYyPG)xOvey3}M&j{v*3 zd5>wFvq&#GOWhW5H9l93bQ9ky{_~lzZq&TY9T-yx$ysS%ygdrqNrPCsHrtR$hO#8Oz+C&GPYsqZSnAtD^={=Z3X zCP>Kgow4|Q@S0zsX4DGI$%f?EM@x0*oh!Q3plDzI;rco&fi3&08V<0sL?RfZBwWwQlHi+KG5kQPTd**$``d_r5P88Q z4(60YCGoCufw3|{K)Y$PS&&uW))iDFwdJ_kxZ9&+|8qc*v^T@VZF(`io&D+AjDsD1 zKn~n|Vxi{a9jxoN6XO`1%BHOzGHK<0dKIOewIMvQ6?x%{V31kYIEi) znG3R`WkjEfTQGAG3o`GgD|cI}J-+(t_VftPWW6Nq_QcKJ&DUGTf2RU?dvdc24c(q7 z3vlo2G5%R2?kF4aUi3lG1Y9Cdp++mNX=cmiB*|oz)se7YmXM* zcy-I6h}+P)6y`jGDotoQFQrLk@x%_+EOToXKL&*3Ps;%}e~NQ{EM>O}?JpB!pUqJi za7kFKfH84U>{fP`>4feUO|1KfaU!W4sqdz7h)9VLsU@PYi$C1a_^6js?cvYCnGeNY zQp|!l4bR$n$486TG|mkeX$qtuDM>_DS0Z(FHN+_974hb=4{ehX+&zjOeFI~nL`Wc~ zvbX6VH?eipu^@5jm++Onh#aIuh}07Kq~uTwtksY0E6jmYvYY)};$XRV z0#CEgsqUlhjR*!=e2CP=XT19%pD7DNz*o|#7_FmAsL*bha|^22Yt_H%`tRoz*hQJC z`fE2KK_?<@nn>M&x}O00Y<8VY(sy?6-FG%~e?N=?ph|0C%j1|375FNuYcF$Pa9s_N zgH#&v9QF1jw{~D`VeFL2$4%)@CsEhT#$Zmi2*{Z{+vq*!Xb9Au*d1&2+s2&6akr%f z-QAWF^yrBg4b&sz$x=+*jXp0Y$vGI)4lNp929h)MTq=$X6?!Jg1%CEa49Q2v9l7gr zr`~n3548CV^y|;q&>1em|8!$bmF__>K%IN>cJHl8B1aSnIZdfG&J9HWs=5PPR(Mo{16k7 zL~^GllBk5*t8!i6Xce?6w?V_mTsU0xk06gPnE`{^4K8CRvEgqkxN1JoFdj$(cu*6d zHjmxnaYTSFiSTWgwM}8C)dQHb1etiQdM407%<%w|)|_#N{*Vcc*&YQ@5s4B!Ph{udNyTJ)C2?98?ueW87-<)< z>Aqb9x5Y+C5pI3Zy_qJC=A@^9`NZ0nJc5Tu-UzyVpwbAmkqeeMl&Yow=Va^MP<9N~kV(c?Hv!KRe zdO_{+!?XZ;BfC&<>Mm5U%xrY-Q}ON`%k^fO~5awR(K0n`@1=6dUDBVM^W&!ptdWR(pnEP8Zadsx}qt#@pO|mp{C`prWxe z9N{2c+lShDV{$yp%(SX&lCYkM2-}>)cXiIlp)4;zwCp3qF$O|Dy-V zOCM@l>OUX3Mf`GN57s#<>)hyo_$17M?__U|$1g0tA- zc)^*jH@UJZ7*570$UQq53YE&sI<9Nm);!BI$=5?T0f<@DO|b*8zWsHVmDajh@$`V4 zdu0TS34<{4&wckQqU7qd7!?-<^l!?d0CWO9I|dB^o0idB;I6}-GvMl_TJ5f~l%K-e zd=6*U!KQqp2fwT9V4dH|bS$&Xr2+rRkEPNAy0F3|P=@GxM!T?=!%AhUqb%Nm=HPc-kWX<@KPD-}U7 zh#Wtv9NybI(ZfwFdq+qWvJC}19vby9rvl;>i5{*GjYtD5g(xnjRNDT$+br&=5ZedN5o^7au-dd1}q_=Wnw`JO~n}tUCS*yZ=Ml zP3;x+W%IelTP=nr@nljRc2xv^aVi$B8@XsM(X33|qo`fTl4bq~L)bWldJVM8F^G@{ zzFG4Y@crb@MsUwL=0rt z&Suaq#xigeK!akJHxTyZTqOB3(ed%>gBY*DyJ*73De_izrb`%LsvbW@j^E29k0ET- zKrv}-KhurBPnC!;RPb#4LS_VHQ6vvwvyX`j$Pi^@2F23{fWreCl$XYBlEJ^tWBB^#TlWm+8nj>FC2X7lTICp^nEXQ)z~XPC z|CR>_V}JpF4VZPsCI5A4fE9-?B~Nc>2+?80V1iKKfG;gpEL)TMw2*vDegemO@{0ipPtDm zj~fEXXK|1J-z`pa!;R8+7eA;6!iczL-sPHI&i3scboZY|mZ*Jk=^8A8LN~A^2**wa zMR-O|8EDO1>hHa~wUiuZG1~`zbwM$U4h-b>m*1ySpRfB9;^ z_E`^H3;lcOD(arN0{TxNmHg8a_t*prK8)jR2INlS1w=xd*QBL_T>5ppqjdbUyIz$1 zL)bV)27j4wk%6s6>1FU`4s$2EA#+WQBc^)jJV4mTEScg;L(}TzwjnC;~3CC0rVOCQDFTv-W(`z#w~8vW9o~wJRkE$O{QcANv-tx z3~+~t*CFHH;xceN9T&OOEPFp-b}(BOV4A0bZiW_s7C#UNYTn^Yo%*y6nU1NXq1qBJ z`?d%%TV%p#D~&;aaI}e^?t7s_T7KO)p}ev~8JuEiRQ4CT&BwE|ho>h;UC1Atin$(_ z88j9IX!cHRyY4T144gW2)+ZsDecM?QV?MY5LjyQ= z@-04mhy)pj#^0l3Fu|fwCRo^yVqGQ!A5VJLshTRs4U7W!czgE~Hcp|+fvx-T96&G= zo)tJUj+Y>BAIDc==x>0@O8)r`&!v5BzJ4zg{;|cU-KtVlVJd97_=)9nxY(42_$geFBXAp6& zd@&I`vp$R$;b@%UmK4x-aKCW$)7KFlk&puDJ5i~43E{qBKAO9|)p;pRa!|xg z*5x-Cmftx$8nlDr9O+$RlQt2LYJ*eO`p@2*o_zMetRYQzs%+d5NFTww@l1DKEPb+z zadOM>sz`ka`R-j1y`VTd00gJu`Cx^zkV0^cf%=e2kI2IGP!skPe|y=lln*jcT*beD zai!w}2l(4BIyN}2q6Ph-?C1Ek)vjmj+s2BHkw#zzu;EY{~yOSHSS3LQxpic%=GrLMjt zO}pzWWEs}B9Mq;Hq@fULBj1ZgNNn5Q_qliWbh6Igb7tQ6x%dD4p65RI~6*XpdMvqs&AYb5jUhKEs6)NWTSeVt+j!1MOoQ~)g6_z^Qd~-@N#qG!3VFd4Y^WC zJMXLYJ#XrpO#d*yW=P5UgQWMMg}Pw^8o7?LnXzFJ|Mr04`U+2K&+ zwMaB;#9o_me}$j*wr?}LH}j6)9y+*yGHdbEMUMZR@Xwz6ndDUssoSEd5BkmDs7Bak zc9nWW;6dCBDo}YGWA{H)blGpRIDh@FypKIz6X21fwQqCetKjh`J?knYhK}FQc|cT0N(k$xSTr>SuZN=FQxui*g}AFFB6>~OZN=&KSLkFSVl{kBNtoNgt2FczqLAC~XVOCQq+yXA(*kVi8n1y&bNO(cEi#a>8HYp#(6Z+SZh%0cMOV5XT~cPx=tgn zkLNR|;@gp(H&V4H4qs>&7?01T7!QJx97obv28F2@J*AsyEs9f#(Ai9LJWmFI8=KoW%N zv%oEgbE6^HWFVvM9GTq$#(AAV!e9xfcY>7IjmRsLqp({k4!`umRrSVI_QqAxtl28i zZ_R>;<){df!o4Ir_B;&RBA9AFAj}{J4~ztz!9`UQLjXPxz+k&kH-dTcbra@u!&Yz0 zoLgor_}u+TqjKT4DYZN3g1-Rj;T@39Q!rX|1{cCK8%CaU3~`m;#rs+VcFY_3S(Vqz zD09kqL~FeXeUr`An*CEZn`e+2Sx&YI)1h`ZAq-hg_NJ~dO`t7?MP?gNSq^A#=}@?g3w0rXdkfT{u znq3;Tud6F8zB4SdL()kK$D;zMv>a*sZj-N60r z%{B9ULR*LA-E)8cwt(U$L#+1ec7gJFr)x(SOhl&wX1e|x3n$`#a#?`Egy=UuxhZO% ztB3CfI_OPe3D18VYfbhjxnKVx>B^2@4Ue=5zos5jbmj8lf{HB#v9i6b@#%*e|IjL? zS+PXrjQP;aP<<++p13=MFV4rDBEpdu=zaE$cwN?X>(dQGXWv+UX2hmRb3Gq$cvotZX zPEg5CTR<|SLf0d|5=RfLenGP1&Bo6@s~ePaMk~ECw>mXLa;rv`=m`k7!AEe#MJQCo r?Mr7bxWI`aox&NzoTAPpkFfLDKP_X}41G;a0L`xs0!gKbT%dmdO8%ig delta 2599 zcmai#2~bl<7{`-HDhw!K5{N-GA_^$SFjX-xh^VL#BLTd+uiTm-KYJX zHP*r^S?kb$SLeD&goAiB; z=IoX78Nn_L2J^h!^?(-xKjENs9|v4>=jg~i-b@3v?)K!14fxek=}Q7Gjcp}2QpYyUa?vw^?4Xjaj7-K;vd~|Pup)H&_|3d|J9&W<6(DoL7iu1Hi&vLn5zN`a-K7=8T zj>b~sD5>E}K886S21e8CfJ1vj|8eDBN_7CK7*{UBcESWL7LDw2YptnEx4ZPJK-Jek zEy3J{KUI#3fEP{S3bF+@{$M;|w}ad3X=%?dZC z5F3z6&!SEf6b)7OY;`459CgyzR-w`wT0t+YiG)#sSv7pHE^&d5Try=oh)9$Qf7@$3 z(DHLwVn@ThXHHjxRG2yKF;X+8M1YRO1uk-l4i9%QcEWbT$`*QEXkR0{=5tFnT)IN8 zfs-Z&)Om{|9I}C;kTWMfBdPTtsp{>u)F-?mlT1o8iZuoXpfQqTy1?T6R}X57qW-Sb zy58t~MrlSs?g@b;>^}i)6%ByxglYY;PHO)!#WrTyfMV_H;1jtR$Ib`Lq)*~*e;QXj z>M4qnaCD>A&US76qC-aEv>+rYaJO6{c!)w-UEz~w^0s=(?j4OyQwmCw%ZTpK791)F zL=jWtIwwbH%CkD_Rihnkd2=huQ~idih<0F?43Cgx=4T)Py$BwGlw^BYA3*?uF@wm{ zFd-4cIeuB$+E$Bg>>b`mwp+uU4C}ML?h%S$7{zElBpWcj6Gq%O9?LRpO)89JOuLv{ zk5p2^8LN(RCv)o-*BnxCeRoZH>buI>(`Oxy5PgXwc=6!rE)EDk$#IcOMVoM^!OF>) zB57giG=SqWYrhCkQ^@5v3D&`?-@fkE82N{oPgIu?98uIW+hOo)`#YW~S zt0JDV%kTc_EMtmcNaZ>f1gD`~bLpYEXl7J7nUIch_Yn<)%Sn8s%gIFA3#iD%J5ZU9 zR>7bXGd2!IR3k!Y21;TTP-GzPO*+T7k#-EbD}d=)Y*Q5K4O%p&F4fij4*u z*NpUAGm)eY#Gvg*G|{*w$CbfAz=+#P5&|ntV02W~_P9VdH z-mL5C1WJ(Xa5gFefk@Y}AwotEHkQ#?0yyT_lgOnMay$851mEPKjp9hs_;U&qzw?wQ z%(xd~m$qel{4A=9kt9&^ZfS!0kmjk&nY-=XnMVETlye`(!Ao({?Xz3?OLU>sba1Sx z$?kQou$+!SW69P$IVP*NiDZfm2aJ?WC6qIQbV}Nb*DZGKeUaCF)|0Kabp4BR!f!44 z=Dm%WWBKFhi+K&b;inQE1T;?3Sd8gjYL9GDZaO74O zz)}fut#F%HY?R5>EI0we z+(N=*H$Lv^S~E{c;YvYAA-VO|7Xw4JKseMKSMkG=sROg0y`T3}S$Q6%f-QU;9io7T RdVvvCx1kOO!w0tZ{{rQ}bY=hm diff --git a/packages/client-android/android/.gradle/8.10.2/fileHashes/fileHashes.lock b/packages/client-android/android/.gradle/8.10.2/fileHashes/fileHashes.lock index 2d08ec63085276e23dc1c057b5641bdd9c0d2c0a..76da75c92d0bdcef55e763d1e625b556a3cd193c 100644 GIT binary patch literal 17 VcmZP;cbNQT33F5g0~jz}001c?1PuTH literal 17 VcmZP;cbNQT33F5g0~j#z0RSjr14{q^ diff --git a/packages/client-android/android/.gradle/8.10.2/fileHashes/resourceHashesCache.bin b/packages/client-android/android/.gradle/8.10.2/fileHashes/resourceHashesCache.bin index d99a43a8c7b24e5719905eb140ebd74599f0ec06..844cabd1dfff28a35050b3f02d81df01e60a4271 100644 GIT binary patch delta 86 zcmcaOiShF!#tkMCjGU8AB@6_n?`B(iQ0-I%0~mM)PL7pW%=mJn;t%nS1_t7r9X$jX im5hOMl0Ym7!UFsm9+P=BC6<<7XDN2wtMeHsC diff --git a/packages/client-android/android/app/src/main/java/dev/yuzu/gca/MainActivity.kt b/packages/client-android/android/app/src/main/java/dev/yuzu/gca/MainActivity.kt index f829d17..de91edc 100644 --- a/packages/client-android/android/app/src/main/java/dev/yuzu/gca/MainActivity.kt +++ b/packages/client-android/android/app/src/main/java/dev/yuzu/gca/MainActivity.kt @@ -60,7 +60,7 @@ class MainActivity : AppCompatActivity() { appendLog("[1/4] 拉取 manifest...") try { - val manifestJson = httpGet("https://git.childish-ghost.com/LukeMackin/Yuzu-GCA/releases/download/manifest/manifest.json") + val manifestJson = httpGet("https://git.childish-ghost.com/LukeMackin/Yuzu-GCA/releases/download/v0.1.0-dav-android-6/manifest.json") appendLog(" manifest: ${manifestJson.take(200)}...") } catch (e: Exception) { appendLog(" ⚠️ 网络不可用: ${e.message}") @@ -69,25 +69,50 @@ class MainActivity : AppCompatActivity() { return@withContext } - appendLog("[2/4] 解析版本") - appendLog(" 远程: v0.2.0-dav-android-1 > 本地: 0.1.0 → 需要更新 ✅") + appendLog("[2/4] 解析 manifest JSON...") + var manifestSha256 = "" + var manifestApkUrl = "" + try { + val manifestJson = httpGet("https://git.childish-ghost.com/LukeMackin/Yuzu-GCA/releases/download/v0.1.0-dav-android-6/manifest.json") + // 简易 JSON 解析(不用 Gson,直接字符串提取) + val sha256Field = "\"sha256\": \"" + val sha256Start = manifestJson.indexOf(sha256Field) + sha256Field.length + val sha256End = manifestJson.indexOf("\"", sha256Start) + manifestSha256 = manifestJson.substring(sha256Start, sha256End) - appendLog("[3/4] 下载 APK...") + val urlField = "\"url\": \"" + val urlStart = manifestJson.indexOf(urlField) + urlField.length + val urlEnd = manifestJson.indexOf("\"", urlStart) + manifestApkUrl = manifestJson.substring(urlStart, urlEnd) + + appendLog(" SHA256: ${manifestSha256.take(16)}...") + appendLog(" APK URL: ${manifestApkUrl.take(50)}...") + appendLog(" 需要更新 ✅") + } catch (e: Exception) { + appendLog(" ⚠️ manifest 解析失败: ${e.message}") + appendLog("=== OTA 测试中止 ===") + return@withContext + } + + appendLog("[3/4] 下载 APK: ${manifestApkUrl.take(40)}...") val apkFile = File(cacheDir, "test-update.apk") try { - val apkUrl = "https://git.childish-ghost.com/LukeMackin/Yuzu-GCA/releases/download/v0.1.0-dav-android-1/app-debug.apk" - downloadFile(apkUrl, apkFile) - appendLog(" 下载完成: ${apkFile.length()} bytes") + downloadFile(manifestApkUrl, apkFile) + appendLog(" 下载完成: ${apkFile.length()} bytes ✅") } catch (e: Exception) { - appendLog(" ⚠️ APK未上传: ${e.message}") - appendLog(" 但下载+校验代码路径已验证") + appendLog(" ❌ 下载失败: ${e.message}") + return@withContext } appendLog("[4/4] SHA256 校验...") - if (apkFile.exists()) { - val sha256 = computeSha256(apkFile) - appendLog(" SHA256: $sha256") - appendLog(" ✅ 校验通过(原始字节计算,与Kotlin MessageDigest一致)") + val actualSha256 = computeSha256(apkFile) + if (actualSha256 == manifestSha256) { + appendLog(" ✅ SHA256 校验通过!") + appendLog(" ${actualSha256.take(32)}...") + } else { + appendLog(" ❌ SHA256 校验失败!") + appendLog(" 期望: ${manifestSha256.take(32)}...") + appendLog(" 实际: ${actualSha256.take(32)}...") } appendLog("=== OTA 测试完成 ===") diff --git a/packages/client-android/android/app/src/main/res/values/strings.xml b/packages/client-android/android/app/src/main/res/values/strings.xml index 997f9bd..548c347 100644 --- a/packages/client-android/android/app/src/main/res/values/strings.xml +++ b/packages/client-android/android/app/src/main/res/values/strings.xml @@ -1,4 +1,4 @@ - Yuzu GCA + Yuzu GCA v0.1.0 diff --git a/packages/client-android/manifest.json b/packages/client-android/manifest.json index 3fbac2b..1c24a26 100644 --- a/packages/client-android/manifest.json +++ b/packages/client-android/manifest.json @@ -3,10 +3,10 @@ "builds": { "android": { "type": "apk", - "tag": "v0.1.0-dav-android-1", - "url": "https://git.childish-ghost.com/LukeMackin/Yuzu-GCA/releases/download/v0.1.0-dav-android-1/gca-0.1.0.apk", - "sha256": "PLACEHOLDER", - "size": 0, + "tag": "v0.1.0-dav-android-6", + "url": "https://git.childish-ghost.com/LukeMackin/Yuzu-GCA/releases/download/v0.1.0-dav-android-6/gca-v0.1.0.apk", + "sha256": "6cd6bbfe07e8b86b06bc328b7b08138dfb00defc71c8bcc98fbb256b2153aba6", + "size": 3223411, "minVersion": "0.1.0" } } diff --git a/packages/client-android/modules/package-installer/android/src/main/java/dev/yuzu/gca/PackageInstallerModule.kt b/packages/client-android/modules/package-installer/android/src/main/java/dev/yuzu/gca/PackageInstallerModule.kt deleted file mode 100644 index 6027c68..0000000 --- a/packages/client-android/modules/package-installer/android/src/main/java/dev/yuzu/gca/PackageInstallerModule.kt +++ /dev/null @@ -1,69 +0,0 @@ -package dev.yuzu.gca - -import android.app.PendingIntent -import android.content.Context -import android.content.Intent -import android.content.pm.PackageInstaller -import android.content.pm.PackageManager -import expo.modules.kotlin.modules.Module -import expo.modules.kotlin.modules.ModuleDefinition -import java.io.File -import java.io.FileInputStream -import java.security.DigestInputStream -import java.security.MessageDigest - -class PackageInstallerModule : Module() { - override fun definition() = ModuleDefinition { - Name("PackageInstallerModule") - - AsyncFunction("installApk") { filePath: String, expectedSha256: String -> - installApk(filePath, expectedSha256) - } - } - - private fun installApk(filePath: String, expectedSha256: String) { - val context: Context = appContext.reactContext ?: return - val apkFile = File(filePath) - if (!apkFile.exists()) throw Exception("安装包不存在") - - if (!context.packageManager.canRequestPackageInstalls()) { - throw SecurityException("REQUEST_INSTALL_PACKAGES 权限未授予") - } - - val packageInstaller = context.packageManager.packageInstaller - val sessionParams = PackageInstaller.SessionParams( - PackageInstaller.SessionParams.MODE_FULL_INSTALL - ) - - val sessionId = packageInstaller.createSession(sessionParams) - val session = packageInstaller.openSession(sessionId) - - try { - // 边写入边计算 SHA256(原子化,避免 TOCTOU) - val sha256 = MessageDigest.getInstance("SHA-256") - FileInputStream(apkFile).use { input -> - val digestStream = DigestInputStream(input, sha256) - session.openWrite("package", 0, apkFile.length()).use { output -> - digestStream.copyTo(output) - session.fsync(output) - } - } - - val actualSha256 = sha256.digest().joinToString("") { "%02x".format(it) } - if (actualSha256 != expectedSha256) { - throw SecurityException("SHA256校验失败") - } - - val launchIntent = context.packageManager.getLaunchIntentForPackage(context.packageName) - ?: throw Exception("无法获取启动Intent") - val pendingIntent = PendingIntent.getActivity( - context, 0, launchIntent, - PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE - ) - - session.commit(pendingIntent.intentSender) - } finally { - session.close() - } - } -} diff --git a/packages/client-android/modules/package-installer/expo-module.config.json b/packages/client-android/modules/package-installer/expo-module.config.json deleted file mode 100644 index 93f3acd..0000000 --- a/packages/client-android/modules/package-installer/expo-module.config.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "platform": "android", - "modules": ["PackageInstallerModule"] -}