Merge remote-tracking branch 'origin/projects_keeper_tag' into merge

This commit is contained in:
2026-05-27 15:21:47 +08:00
6 changed files with 198 additions and 16 deletions

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
#Wed May 20 16:12:13 HKT 2026
stageCount=21
#Wed May 27 14:51:29 HKT 2026
stageCount=23
libraryProject=libappbase
baseVersion=15.20
publishVersion=15.20.20
publishVersion=15.20.22
buildCount=0
baseBetaVersion=15.20.21
baseBetaVersion=15.20.23

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
#Wed May 20 16:12:13 HKT 2026
stageCount=21
#Wed May 27 14:51:29 HKT 2026
stageCount=23
libraryProject=libappbase
baseVersion=15.20
publishVersion=15.20.20
publishVersion=15.20.22
buildCount=0
baseBetaVersion=15.20.21
baseBetaVersion=15.20.23

View File

@@ -1,6 +1,8 @@
package cc.winboll.studio.libappbase.views;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
@@ -12,6 +14,7 @@ import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import cc.winboll.studio.libappbase.GlobalApplication;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.R;
@@ -74,12 +77,12 @@ public class AboutView extends LinearLayout {
private EditText metDevUserPassword;
// ===================================== 页面视图控件 =====================================
private DebugSwitchImageView ivAppIcon;
private DebugSwitchInfoImageView ivAppIcon;
private TextView tvAppNameVersion;
private TextView tvAppDesc;
private LinearLayout llFunctionContainer;
private ImageButton ibSebugStepOver;
private ImageButton ibSigngetDialog;
private ImageButton ibDebugUnlock;
private ImageButton ibWinBoLLHostDialog;
// ===================================== 构造方法(按参数从少到多排序) =====================================
@@ -193,12 +196,12 @@ public class AboutView extends LinearLayout {
llFunctionContainer = findViewById(R.id.ll_function_container);
// 功能按钮绑定
ibSebugStepOver = findViewById(R.id.ib_debug_step_over);
ibSigngetDialog = findViewById(R.id.ib_signgetdialog);
ibDebugUnlock = findViewById(R.id.ib_debug_unlock);
ibWinBoLLHostDialog = findViewById(R.id.ib_winbollhostdialog);
// 调试按钮统一只在调试模式显示
ibWinBoLLHostDialog.setVisibility(GlobalApplication.isDebugging() ? View.VISIBLE : View.GONE);
//ibSigngetDialog.setVisibility(GlobalApplication.isDebugging() ? View.VISIBLE : View.GONE);
//ibDebugUnlock.setVisibility(GlobalApplication.isDebugging() ? View.VISIBLE : View.GONE);
ibSebugStepOver.setVisibility(GlobalApplication.isDebugging() ? View.VISIBLE : View.GONE);
// 绑定按钮点击事件
@@ -310,6 +313,47 @@ public class AboutView extends LinearLayout {
LogUtils.d(TAG, "initAboutPageView():视图组装完成,功能项加载完毕");
}
// ===================================== 调试解锁弹窗 =====================================
private void showDebugUnlockDialog() {
final AlertDialog dialog = new AlertDialog.Builder(mContext).create();
dialog.setTitle("应用调试解锁");
dialog.setCanceledOnTouchOutside(true);
final EditText etToken = new EditText(mContext);
etToken.setHint("请输入调试Token");
dialog.setView(etToken);
dialog.setButton(DialogInterface.BUTTON_POSITIVE, "调试解锁", (DialogInterface.OnClickListener) null);
dialog.setButton(DialogInterface.BUTTON_NEGATIVE, "关闭", (DialogInterface.OnClickListener) null);
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface d) {
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String inputToken = etToken.getText().toString().trim();
String savedToken = DebugSwitchInfoImageView.getDebugToken();
if (savedToken != null && savedToken.equals(inputToken)) {
GlobalApplication.setIsDebugging(true);
GlobalApplication.saveDebugStatus(GlobalApplication.getInstance());
Toast.makeText(mContext, "调试解锁成功,重启应用后生效", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(mContext, "调试Token不匹配", Toast.LENGTH_SHORT).show();
dialog.dismiss();
}
}
});
dialog.getButton(AlertDialog.BUTTON_NEGATIVE).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dialog.dismiss();
}
});
}
});
dialog.show();
}
// ===================================== 内部工具/事件方法 =====================================
/**
* 绑定功能按钮点击事件,处理正版校验、调试地址配置弹窗唤起
@@ -335,6 +379,15 @@ public class AboutView extends LinearLayout {
new DebugHostDialog(mContext).show();
}
});
// 应用调试解锁按钮
ibDebugUnlock.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
LogUtils.d(TAG, "ibDebugUnlock onClick弹出调试解锁对话框");
showDebugUnlockDialog();
}
});
LogUtils.d(TAG, "setBtnClickListener():功能按钮点击事件绑定完成");
}

View File

@@ -0,0 +1,127 @@
package cc.winboll.studio.libappbase.views;
import android.app.AlertDialog;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
import java.util.UUID;
import cc.winboll.studio.libappbase.GlobalApplication;
/**
* @Author 豆包&ZhanGSKen<zhangsken@qq.com>
* @Date 2026/04/06 19:32
* @Describe 应用Logo控件连续点击6次弹出调试Token对话框支持复制与重置
*/
public class DebugSwitchInfoImageView extends ImageView {
public static final String TAG = "DebugSwitchInfoImageView";
// 连续点击计数
private int mClickCount = 0;
// 目标点击次数
private static final int TARGET_CLICK_COUNT = 7;
private static String mDebugToken = null;
private static final String SP_DEBUG_TOKEN = "debug_token_prefs";
private static final String KEY_DEBUG_TOKEN = "debug_token";
public static String getDebugToken() {
if (mDebugToken != null) {
return mDebugToken;
}
Context context = GlobalApplication.getInstance();
if (context != null) {
SharedPreferences sp = context.getSharedPreferences(SP_DEBUG_TOKEN, Context.MODE_PRIVATE);
mDebugToken = sp.getString(KEY_DEBUG_TOKEN, null);
if (mDebugToken == null) {
mDebugToken = UUID.randomUUID().toString();
sp.edit().putString(KEY_DEBUG_TOKEN, mDebugToken).apply();
}
}
return mDebugToken;
}
public static void resetDebugToken() {
Context context = GlobalApplication.getInstance();
if (context != null) {
mDebugToken = UUID.randomUUID().toString();
SharedPreferences sp = context.getSharedPreferences(SP_DEBUG_TOKEN, Context.MODE_PRIVATE);
sp.edit().putString(KEY_DEBUG_TOKEN, mDebugToken).apply();
}
}
private void showDebugTokenDialog() {
final AlertDialog dialog = new AlertDialog.Builder(getContext()).create();
dialog.setTitle("调试Token");
dialog.setMessage(getDebugToken());
dialog.setCanceledOnTouchOutside(false);
dialog.setButton(DialogInterface.BUTTON_POSITIVE, "复制到剪贴板", (DialogInterface.OnClickListener) null);
dialog.setButton(DialogInterface.BUTTON_NEUTRAL, "重置", (DialogInterface.OnClickListener) null);
dialog.setButton(DialogInterface.BUTTON_NEGATIVE, "关闭", (DialogInterface.OnClickListener) null);
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface d) {
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ClipboardManager cm = (ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE);
cm.setPrimaryClip(ClipData.newPlainText("DebugToken", getDebugToken()));
}
});
dialog.getButton(AlertDialog.BUTTON_NEUTRAL).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
resetDebugToken();
dialog.setMessage(getDebugToken());
}
});
dialog.getButton(AlertDialog.BUTTON_NEGATIVE).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dialog.dismiss();
}
});
}
});
dialog.show();
}
public DebugSwitchInfoImageView(Context context) {
super(context);
init();
}
public DebugSwitchInfoImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public DebugSwitchInfoImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public DebugSwitchInfoImageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
private void init() {
setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mClickCount++;
if (mClickCount >= TARGET_CLICK_COUNT) {
mClickCount = 0;
showDebugTokenDialog();
}
}
});
}
}

View File

@@ -15,7 +15,7 @@
android:paddingRight="16dp"
android:paddingBottom="16dp">
<cc.winboll.studio.libappbase.views.DebugSwitchImageView
<cc.winboll.studio.libappbase.views.DebugSwitchInfoImageView
android:id="@+id/iv_app_icon"
android:layout_width="48dp"
android:layout_height="48dp"
@@ -81,7 +81,8 @@
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/ic_key"
android:id="@+id/ib_signgetdialog"
android:id="@+id/ib_debug_unlock"
android:contentDescription="应用调试解锁"
android:scaleType="fitCenter"
android:adjustViewBounds="true"
android:background="@null"/>

View File

@@ -15,7 +15,7 @@
android:paddingRight="16dp"
android:paddingBottom="16dp">
<cc.winboll.studio.libappbase.views.DebugSwitchImageView
<cc.winboll.studio.libappbase.views.DebugSwitchInfoImageView
android:id="@+id/iv_app_icon"
android:layout_width="48dp"
android:layout_height="48dp"
@@ -81,7 +81,8 @@
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/ic_key"
android:id="@+id/ib_signgetdialog"
android:id="@+id/ib_debug_unlock"
android:contentDescription="应用调试解锁"
android:scaleType="fitCenter"
android:adjustViewBounds="true"
android:background="@null"/>