Skip to content

适配最新版微信(8.0.65+)#261

Merged
eritpchy merged 2 commits intoeritpchy:mainfrom
GreenTeodoro839:main
Mar 4, 2026
Merged

适配最新版微信(8.0.65+)#261
eritpchy merged 2 commits intoeritpchy:mainfrom
GreenTeodoro839:main

Conversation

@GreenTeodoro839
Copy link

已经在最新版微信测试通过。目前存在一点小bug:切换支付方式时,键盘的遮罩没有消失,会遮挡部分界面。另外还修了一下workflow,解决GitHub Action编译失败

Copilot AI review requested due to automatic review settings March 4, 2026 12:41
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

该 PR 旨在适配最新版微信(8.0.65+)的支付界面结构变化(新增 WxaLiteAppTransparentLiteUI 场景),并修复 GitHub Actions 构建失败问题,以保持指纹支付插件在新版微信下可用。

Changes:

  • 为微信 8.0.65+ 新的 LiteApp 支付界面增加基于键盘控件可见性检测的指纹覆盖层逻辑
  • 扩展若干版本/文案匹配逻辑(如支付方式/优惠选择、设置页结构变更)
  • 更新 GitHub Actions 工作流以使用 actions/setup-java@v4 并启用 Gradle cache

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 7 comments.

File Description
settings.gradle 尝试绕过 3rdparty FingerprintIdentify 根工程的已下线依赖以修复构建
app/src/main/java/com/surcumference/fingerprint/plugin/impl/wechat/WeChatBasePlugin.java 增加 LiteApp 支付键盘检测与覆盖层、输入模拟等核心适配逻辑
app/src/main/java/com/surcumference/fingerprint/Constant.java 新增微信版本号常量用于分支判断
.github/workflows/android.yml 修复 CI JDK 安装方式并增加 Gradle 缓存

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

// The FingerprintIdentify root build.gradle contains a deprecated buildscript
// dependency (com.novoda:bintray-release) that can no longer be resolved after
// Bintray shutdown. We only need :FingerprintIdentifyLib, so skip the root build.gradle.
project(':3rdparty:FingerprintIdentify').buildFileName = 'no_build'
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

project(':3rdparty:FingerprintIdentify').buildFileName = 'no_build' will make Gradle look for a file literally named no_build inside 3rdparty/FingerprintIdentify. If that file isn’t present in the repo/submodule checkout, configuration will fail with a missing build script error. Consider committing an empty no_build file (or pointing to an existing minimal Gradle script) so this is deterministic in CI/local builds.

Copilot uses AI. Check for mistakes.
Comment on lines +186 to +195
} else if (!keyboardVisible && wasVisible[0]) {
removeFingerprintCover(decorView);
restoreKeyboardContainerHeight(mKeyboardContainer);
cancelFingerprintIdentify();
mSavedAlphaMap.clear();
mSavedClickableMap.clear();
if (Config.from(listenerContext).isVolumeDownMonitorEnabled()) {
ViewUtils.unregisterVolumeKeyDownEventListener(activity.getWindow());
}
}
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the global layout listener, when the Tenpay keyboard transitions from visible -> not visible, you clear mSavedAlphaMap/mSavedClickableMap but never call restoreChildViewStates(...). Since saveChildViewStates(...) sets children alpha=0 and clickable=false, this path can permanently leave the password layout hidden/unclickable (and clearing the maps prevents recovery). Restore child states (and remove any keyboard cover) before clearing the maps.

Copilot uses AI. Check for mistakes.
Comment on lines +395 to +401
final Runnable switchToPasswordRunnable = () -> {
removeFingerprintCover(rootView);
restoreKeyboardContainerHeight(finalKeyboardContainer);
restoreChildViewStates(finalPasswordLayout, true, mSavedAlphaMap, mSavedClickableMap);
cancelFingerprintIdentify();
mMockCurrentUser = false;
};
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

switchToPasswordRunnable removes the fingerprint cover, but it never removes the keyboardCoverLayout that was added to rootView earlier. That cover will remain on screen and can block/obscure the UI even after switching back to password input. Remove keyboardCoverLayout as part of the switch-to-password cleanup (and consider also removing it on dismiss).

Copilot uses AI. Check for mistakes.
Comment on lines +258 to +267
if (!activityClzName.contains(".WalletPayUI") && !activityClzName.contains(".UIPageFragmentActivity")) {
if (getVersionCode(activity) >= Constant.WeChat.WECHAT_VERSION_CODE_8_0_20 && activityClzName.contains("com.tencent.mm.ui.LauncherUI")) {
stopFragmentObserver(activity);
} else if (activityClzName.contains(".WxaLiteAppTransparentLiteUI")) {
onPayDialogDismiss(activity, activity.getWindow().getDecorView(), 3);
}
}
ActivityViewObserverHolder.stop(ActivityViewObserverHolder.Key.WeChatPayView);
ActivityViewObserverHolder.stop(ActivityViewObserverHolder.Key.WeChatPaymentMethodView);
onPayDialogDismiss(activity, activity.getWindow().getDecorView(), 2);
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

onActivityPaused calls onPayDialogDismiss(..., 3) for .WxaLiteAppTransparentLiteUI, but then unconditionally calls onPayDialogDismiss(..., 2) immediately afterwards. This double-dismiss can cause inconsistent cleanup (e.g., removing/restoring overlays twice) and makes it hard to reason about param semantics. Consider making these mutually exclusive (or folding the logic into a single call).

Copilot uses AI. Check for mistakes.
Comment on lines +920 to +927
protected void onPayDialogDismiss(Context context, View rootView, int param) {
L.d("PayDialog dismiss");
if (!Config.from(context).isOn()) {
return;
}
ViewGroup viewGroup = (ViewGroup) rootView;
cancelFingerprintIdentify();
if (rootView != null) {
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

onPayDialogDismiss(Context, View, int) casts rootView to ViewGroup and calls rootView.findViewWithTag(...) before checking rootView != null. If rootView is null (or not a ViewGroup), this will crash with NPE/ClassCastException. Move the cast and all rootView.* access behind a null/instanceof ViewGroup check.

Copilot uses AI. Check for mistakes.
Comment on lines +954 to +955
viewGroup.addView(createKeyboardCoverLayout(context, mKeyboardPasswordLayout));
}
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When mFingerprintCoverShowing is true, onPayDialogDismiss removes the fingerprint cover and restores container height, but it doesn’t restore the alpha/clickable states previously modified by saveChildViewStates(...) (and it even adds a new keyboardCoverLayout). This can leave the password layout’s children invisible/unclickable after dismiss. Restore child view states and clear the saved maps during dismiss cleanup instead of adding another cover overlay.

Suggested change
viewGroup.addView(createKeyboardCoverLayout(context, mKeyboardPasswordLayout));
}
restoreChildViewStates(mKeyboardPasswordLayout, true, mSavedAlphaMap, mSavedClickableMap);
mSavedAlphaMap.clear();
mSavedClickableMap.clear();
}
mFingerprintCoverShowing = false;

Copilot uses AI. Check for mistakes.
Comment on lines +614 to +618
throw new IllegalArgumentException("Password contains invalid character: " + c);
}
View digitView = ViewUtils.findViewByName(finalKeyboardParent, packageName, keyIds);
if (digitView == null) {
throw new NullPointerException("Cannot find digit view");
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inputDigitalPasswordByTouch throws IllegalArgumentException / NullPointerException inside the handler.postDelayed(...) runnable. Those exceptions occur asynchronously on the main thread and won’t be caught by the try/catch around the call site, so they can crash WeChat. Replace the throws inside the runnable with safe early-returns + logging/toast, or propagate errors via a callback that can be handled.

Suggested change
throw new IllegalArgumentException("Password contains invalid character: " + c);
}
View digitView = ViewUtils.findViewByName(finalKeyboardParent, packageName, keyIds);
if (digitView == null) {
throw new NullPointerException("Cannot find digit view");
L.e("inputDigitalPasswordByTouch: Password contains invalid character: " + c);
Toaster.show("Password contains invalid character");
return;
}
View digitView = ViewUtils.findViewByName(finalKeyboardParent, packageName, keyIds);
if (digitView == null) {
L.e("inputDigitalPasswordByTouch: Cannot find digit view for character: " + c);
Toaster.show("Unable to input password automatically");
return;

Copilot uses AI. Check for mistakes.
@eritpchy eritpchy merged commit 3b71cc0 into eritpchy:main Mar 4, 2026
3 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants