Compare commits
2 Commits
originmast
...
appbase-v1
| Author | SHA1 | Date | |
|---|---|---|---|
| 2896b6401b | |||
| 1aa270482e |
@@ -1,8 +1,8 @@
|
||||
#Created by .winboll/winboll_app_build.gradle
|
||||
#Tue Jan 13 03:23:34 HKT 2026
|
||||
stageCount=5
|
||||
#Tue Jan 20 20:54:24 HKT 2026
|
||||
stageCount=6
|
||||
libraryProject=libappbase
|
||||
baseVersion=15.15
|
||||
publishVersion=15.15.4
|
||||
publishVersion=15.15.5
|
||||
buildCount=0
|
||||
baseBetaVersion=15.15.5
|
||||
baseBetaVersion=15.15.6
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#Created by .winboll/winboll_app_build.gradle
|
||||
#Tue Jan 13 03:23:17 HKT 2026
|
||||
stageCount=5
|
||||
#Tue Jan 20 20:54:24 HKT 2026
|
||||
stageCount=6
|
||||
libraryProject=libappbase
|
||||
baseVersion=15.15
|
||||
publishVersion=15.15.4
|
||||
publishVersion=15.15.5
|
||||
buildCount=0
|
||||
baseBetaVersion=15.15.5
|
||||
baseBetaVersion=15.15.6
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
package cc.winboll.studio.libappbase.dialogs;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import cc.winboll.studio.libappbase.R;
|
||||
import cc.winboll.studio.libappbase.ToastUtils;
|
||||
import cc.winboll.studio.libappbase.utils.APPUtils;
|
||||
import cc.winboll.studio.libappbase.utils.SignGetUtils;
|
||||
|
||||
/**
|
||||
* @Describe 签名显示+正版校验对话框
|
||||
* @Author 豆包&ZhanGSKen<zhangsken@qq.com>
|
||||
* @Date 2026/01/20 21:20:00
|
||||
* @LastEditTime 2026/01/21 11:00:00
|
||||
*/
|
||||
public class SignGetDialog extends Dialog {
|
||||
private static final String TAG = "SignGetDialog";
|
||||
private EditText etSignFingerprint;
|
||||
private TextView tvAuthResult;
|
||||
private Context mContext;
|
||||
|
||||
public SignGetDialog(Context context) {
|
||||
super(context, R.style.DialogStyle); // 适配默认对话框样式
|
||||
this.mContext = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.dialog_sign_get); // 绑定xml布局
|
||||
setCancelable(true); // 点击外部可关闭
|
||||
initView();
|
||||
initSignAndCheck(); // 获取签名+正版校验
|
||||
}
|
||||
|
||||
private void initView() {
|
||||
etSignFingerprint = findViewById(R.id.et_sign_fingerprint);
|
||||
tvAuthResult = findViewById(R.id.tv_auth_result);
|
||||
// 输入框只读,方便复制
|
||||
etSignFingerprint.setEnabled(false);
|
||||
}
|
||||
|
||||
// 核心:获取签名+调用APPUtils校验
|
||||
private void initSignAndCheck() {
|
||||
// 1. 获取当前应用签名
|
||||
String sign = getCurrentSign();
|
||||
if (sign == null) {
|
||||
etSignFingerprint.setText("签名获取失败");
|
||||
} else {
|
||||
// 签名字符串转0/1 bit数组(每2个bit加空格,每16位换行,下一行无前置空格)
|
||||
String bitArrayStr = convertSignToBitArrayWithWrap(sign);
|
||||
etSignFingerprint.setText(bitArrayStr);
|
||||
}
|
||||
LogUtils.d(TAG, "当前应用签名:" + sign);
|
||||
|
||||
// 2. 正版校验+显示结果
|
||||
APPUtils.checkAppValid(mContext);
|
||||
boolean isOfficial = isSignValid();
|
||||
if (isOfficial) {
|
||||
ToastUtils.show("这是正版的WinBoLL应用,请放心使用。");
|
||||
tvAuthResult.setTextColor(Color.BLUE);
|
||||
tvAuthResult.setText("这是正版的WinBoLL应用,请放心使用。");
|
||||
} else {
|
||||
ToastUtils.show("您使用的可能不是正版的 WinBoLL 应用。");
|
||||
tvAuthResult.setTextColor(Color.RED);
|
||||
tvAuthResult.setText("您使用的可能不是正版的 WinBoLL 应用。");
|
||||
}
|
||||
}
|
||||
|
||||
// 核心修改:签名字符串转0/1 bit数组(每2个bit加空格,每16位换行,下一行无前置空格)
|
||||
private String convertSignToBitArrayWithWrap(String signStr) {
|
||||
StringBuilder bitBuilder = new StringBuilder();
|
||||
// 1. 字符转8位bit
|
||||
for (char c : signStr.toCharArray()) {
|
||||
String bit8 = String.format("%8s", Integer.toBinaryString(c)).replace(' ', '0');
|
||||
bitBuilder.append(bit8);
|
||||
}
|
||||
String fullBitStr = bitBuilder.toString();
|
||||
|
||||
// 2. 按16位分组,组内每2个bit加空格(避免换行后带空格)
|
||||
StringBuilder finalBuilder = new StringBuilder();
|
||||
int groupSize = 16; // 每组16个bit
|
||||
for (int i = 0; i < fullBitStr.length(); i += groupSize) {
|
||||
// 截取16位bit为一组
|
||||
int end = Math.min(i + groupSize, fullBitStr.length());
|
||||
String group = fullBitStr.substring(i, end);
|
||||
|
||||
// 组内每2个bit加空格
|
||||
StringBuilder groupWithSpace = new StringBuilder();
|
||||
for (int j = 0; j < group.length(); j++) {
|
||||
groupWithSpace.append(group.charAt(j));
|
||||
if ((j + 1) % 2 == 0 && j != group.length() - 1) {
|
||||
groupWithSpace.append(" ");
|
||||
}
|
||||
}
|
||||
|
||||
// 添加组到最终结果,每组后换行(最后一组不换行)
|
||||
finalBuilder.append(groupWithSpace);
|
||||
if (end < fullBitStr.length()) {
|
||||
finalBuilder.append("\n");
|
||||
}
|
||||
}
|
||||
return finalBuilder.toString();
|
||||
}
|
||||
|
||||
// 获取签名(复用SignGetUtils逻辑,避免重复代码)
|
||||
private String getCurrentSign() {
|
||||
try {
|
||||
return SignGetUtils.getSignStr(mContext); // 复用工具类逻辑
|
||||
} catch (Exception e) {
|
||||
LogUtils.e(TAG, "获取签名失败", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// 校验签名是否合法(匹配APPUtils目标签名)
|
||||
private boolean isSignValid() {
|
||||
String currentSign = getCurrentSign();
|
||||
String targetSign = APPUtils.TARGET_SIGN_FINGERPRINT; // 取APPUtils目标签名
|
||||
return currentSign != null && targetSign != null && currentSign.equals(targetSign);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
package cc.winboll.studio.libappbase.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.Signature;
|
||||
import android.util.Base64;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
/**
|
||||
* @Author 豆包&ZhanGSKen<zhangsken@qq.com>
|
||||
* @Date 2026/01/20 19:17
|
||||
* @Describe APPUtils 应用包名、签名校验工具类
|
||||
*/
|
||||
public class APPUtils {
|
||||
|
||||
public static final String TAG = "APPUtils";
|
||||
// 目标应用签名指纹(BASE64格式,自行替换为你的合法指纹)
|
||||
//public static final String TARGET_SIGN_FINGERPRINT = "你的应用签名SHA1指纹BASE64值";
|
||||
public static final String TARGET_SIGN_FINGERPRINT = "bMArVdXE4ZZo42vS9e/kXE63MkE=";
|
||||
// 目标应用包名(自行替换为你的应用包名)
|
||||
private static final String TARGET_PACKAGE_NAME = "cc.winboll.studio.你的应用包名";
|
||||
|
||||
/**
|
||||
* 检查应用包名+签名指纹合法性,不匹配打日志,匹配无操作
|
||||
* @param context 上下文
|
||||
*/
|
||||
public static void checkAppValid(Context context) {
|
||||
if (context == null) {
|
||||
LogUtils.w(TAG, "checkAppValid: context为空,跳过校验");
|
||||
return;
|
||||
}
|
||||
// 1. 校验包名
|
||||
String currentPkg = context.getPackageName();
|
||||
LogUtils.d(TAG, "checkAppValid: 当前应用包名=" + currentPkg + ",目标包名=" + TARGET_PACKAGE_NAME);
|
||||
if (!TARGET_PACKAGE_NAME.equals(currentPkg)) {
|
||||
LogUtils.e(TAG, "checkAppValid: 应用包名不匹配,非法环境");
|
||||
return;
|
||||
}
|
||||
// 2. 校验签名指纹
|
||||
String currentSign = getAppSignFingerprint(context);
|
||||
LogUtils.d(TAG, "checkAppValid: 当前应用签名指纹=" + currentSign + ",目标指纹=" + TARGET_SIGN_FINGERPRINT);
|
||||
if (currentSign == null || !TARGET_SIGN_FINGERPRINT.equals(currentSign)) {
|
||||
LogUtils.e(TAG, "checkAppValid: 应用签名指纹不匹配,非法环境");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前应用签名SHA1指纹(BASE64编码,适配Java7)
|
||||
* @param context 上下文
|
||||
* @return 签名指纹字符串,失败返回null
|
||||
*/
|
||||
private static String getAppSignFingerprint(Context context) {
|
||||
try {
|
||||
PackageManager pm = context.getPackageManager();
|
||||
PackageInfo pkgInfo = pm.getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES);
|
||||
Signature[] signatures = pkgInfo.signatures;
|
||||
if (signatures == null || signatures.length == 0) {
|
||||
LogUtils.w(TAG, "getAppSignFingerprint: 未获取到应用签名");
|
||||
return null;
|
||||
}
|
||||
// SHA1摘要 + BASE64编码,和目标指纹格式统一
|
||||
MessageDigest md = MessageDigest.getInstance("SHA1");
|
||||
md.update(signatures[0].toByteArray());
|
||||
return Base64.encodeToString(md.digest(), Base64.NO_WRAP);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
LogUtils.e(TAG, "getAppSignFingerprint: 包名未找到", e);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
LogUtils.e(TAG, "getAppSignFingerprint: 不支持SHA1算法", e);
|
||||
} catch (Exception e) {
|
||||
LogUtils.e(TAG, "getAppSignFingerprint: 获取签名异常", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
package cc.winboll.studio.libappbase.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.Signature;
|
||||
import android.util.Base64;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
/**
|
||||
* @Author 豆包&ZhanGSKen<zhangsken@qq.com>
|
||||
* @Date 2026/01/20 19:50
|
||||
* @Describe 获取应用签名指纹(SHA1+Base64,直接复制用)
|
||||
*/
|
||||
public class SignGetUtils {
|
||||
private static final String TAG = "SignGetUtils";
|
||||
|
||||
/**
|
||||
* 一键获取当前应用签名指纹(直接调用,看日志复制结果)
|
||||
*/
|
||||
public static void getCurrentAppSign(Context context) {
|
||||
if (context == null) {
|
||||
LogUtils.e(TAG, "context不能为空");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
PackageManager pm = context.getPackageManager();
|
||||
PackageInfo pkgInfo = pm.getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES);
|
||||
Signature[] signatures = pkgInfo.signatures;
|
||||
if (signatures == null || signatures.length == 0) {
|
||||
LogUtils.e(TAG, "未获取到应用签名");
|
||||
return;
|
||||
}
|
||||
// 和APPUtils校验格式完全一致(SHA1+Base64 NO_WRAP)
|
||||
MessageDigest md = MessageDigest.getInstance("SHA1");
|
||||
md.update(signatures[0].toByteArray());
|
||||
String signBase64 = Base64.encodeToString(md.digest(), Base64.NO_WRAP);
|
||||
|
||||
// 关键日志:复制【】里的内容到APPUtils的TARGET_SIGN_FINGERPRINT
|
||||
LogUtils.d(TAG, "当前应用包名:" + context.getPackageName());
|
||||
LogUtils.d(TAG, "当前应用签名指纹(直接复制):【" + signBase64 + "】");
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
LogUtils.e(TAG, "获取签名失败:包名不存在", e);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
LogUtils.e(TAG, "获取签名失败:不支持SHA1", e);
|
||||
} catch (Exception e) {
|
||||
LogUtils.e(TAG, "获取签名失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
// 新增:直接返回签名字符串,供对话框调用
|
||||
public static String getSignStr(Context context) {
|
||||
if (context == null) return null;
|
||||
try {
|
||||
PackageManager pm = context.getPackageManager();
|
||||
PackageInfo pkgInfo = pm.getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES);
|
||||
Signature[] signatures = pkgInfo.signatures;
|
||||
if (signatures == null || signatures.length == 0) return null;
|
||||
|
||||
MessageDigest md = MessageDigest.getInstance("SHA1");
|
||||
md.update(signatures[0].toByteArray());
|
||||
return Base64.encodeToString(md.digest(), Base64.NO_WRAP);
|
||||
} catch (Exception e) {
|
||||
LogUtils.e(TAG, "获取签名字符串失败", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,21 +8,22 @@ import android.util.AttributeSet;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import cc.winboll.studio.libappbase.GlobalApplication;
|
||||
import cc.winboll.studio.libappbase.LogUtils;
|
||||
import cc.winboll.studio.libappbase.R;
|
||||
import cc.winboll.studio.libappbase.ToastUtils;
|
||||
import cc.winboll.studio.libappbase.dialogs.SignGetDialog;
|
||||
import cc.winboll.studio.libappbase.models.APPInfo;
|
||||
|
||||
/**
|
||||
* @Describe AboutView 原生实现关于页面,无第三方依赖,适配API30,抽象通用功能控件(邮件/网页跳转)
|
||||
* @Author 豆包&ZhanGSKen<zhangsken@qq.com>
|
||||
* @Date 2026/01/11 12:23:00
|
||||
* @LastEditTime 2026/01/12 01:05:30
|
||||
* @LastEditTime 2026/01/20 20:45:00
|
||||
*/
|
||||
public class AboutView extends LinearLayout {
|
||||
// 全局常量区(标识、回调标识)
|
||||
@@ -41,7 +42,6 @@ public class AboutView extends LinearLayout {
|
||||
private static final int PADDING_MID = 16;
|
||||
private static final int PADDING_SMALL = 8;
|
||||
private static final int ICON_SIZE = 48;
|
||||
private static final int LINE_HEIGHT = 1;
|
||||
private static final int ITEM_ICON_SIZE = 24;
|
||||
|
||||
// 成员属性区(按 核心依赖→业务配置→视图相关 归类排序,注释清晰)
|
||||
@@ -66,12 +66,19 @@ public class AboutView extends LinearLayout {
|
||||
private EditText metDevUserName; // 调试用户名输入框
|
||||
private EditText metDevUserPassword; // 调试密码输入框
|
||||
|
||||
// 视图绑定
|
||||
private ImageView ivAppIcon;
|
||||
private TextView tvAppNameVersion;
|
||||
private TextView tvAppDesc;
|
||||
private LinearLayout llFunctionContainer;
|
||||
|
||||
// 构造方法区(按 参数从少到多 排序,适配 代码创建+XML引用 场景)
|
||||
public AboutView(Context context) {
|
||||
super(context);
|
||||
LogUtils.d(TAG, "AboutView(Context) 构造方法调用,代码创建视图场景");
|
||||
this.mContext = context;
|
||||
initDefaultParams();
|
||||
initViewFromXml();
|
||||
}
|
||||
|
||||
public AboutView(Context context, APPInfo appInfo) {
|
||||
@@ -79,6 +86,7 @@ public class AboutView extends LinearLayout {
|
||||
LogUtils.d(TAG, "AboutView(Context,APPInfo) 构造调用,入参APPInfo:" + (appInfo == null ? "null" : appInfo.getAppName()));
|
||||
this.mContext = context;
|
||||
this.mAPPInfo = appInfo;
|
||||
initViewFromXml();
|
||||
initAll();
|
||||
}
|
||||
|
||||
@@ -87,6 +95,7 @@ public class AboutView extends LinearLayout {
|
||||
LogUtils.d(TAG, "AboutView(Context,AttributeSet) 构造调用,XML布局引用场景");
|
||||
this.mContext = context;
|
||||
initDefaultParams();
|
||||
initViewFromXml();
|
||||
}
|
||||
|
||||
public AboutView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
@@ -94,8 +103,45 @@ public class AboutView extends LinearLayout {
|
||||
LogUtils.d(TAG, "AboutView(Context,AttributeSet,int) 构造调用,XML布局+样式配置,defStyleAttr:" + defStyleAttr);
|
||||
this.mContext = context;
|
||||
initDefaultParams();
|
||||
initViewFromXml();
|
||||
}
|
||||
|
||||
// 核心:加载xml布局并绑定视图
|
||||
// private void initViewFromXml() {
|
||||
// View.inflate(mContext, R.layout.layout_about_view, this);
|
||||
// ivAppIcon = findViewById(R.id.iv_app_icon);
|
||||
// tvAppNameVersion = findViewById(R.id.tv_app_name_version);
|
||||
// tvAppDesc = findViewById(R.id.tv_app_desc);
|
||||
// llFunctionContainer = findViewById(R.id.ll_function_container);
|
||||
// LogUtils.d(TAG, "initViewFromXml 布局加载+视图绑定完成");
|
||||
// }
|
||||
// 1. 新增视图绑定属性(加在原有视图属性后面)
|
||||
private ImageButton ibSigngetdialog;
|
||||
|
||||
// 2. 完善initViewFromXml方法,新增按钮绑定
|
||||
private void initViewFromXml() {
|
||||
View.inflate(mContext, R.layout.layout_about_view, this);
|
||||
ivAppIcon = findViewById(R.id.iv_app_icon);
|
||||
tvAppNameVersion = findViewById(R.id.tv_app_name_version);
|
||||
tvAppDesc = findViewById(R.id.tv_app_desc);
|
||||
llFunctionContainer = findViewById(R.id.ll_function_container);
|
||||
ibSigngetdialog = findViewById(R.id.ib_signgetdialog); // 新增按钮绑定
|
||||
setBtnClickListener(); // 新增绑定点击事件
|
||||
LogUtils.d(TAG, "initViewFromXml 布局加载+视图绑定完成");
|
||||
}
|
||||
|
||||
// 3. 新增按钮点击事件方法(放在initViewFromXml下面即可)
|
||||
private void setBtnClickListener() {
|
||||
ibSigngetdialog.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
LogUtils.d(TAG, "签名获取按钮点击,弹出SignGetDialog");
|
||||
new SignGetDialog(mContext).show(); // 弹出对话框
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// 对外公开方法区(供外部调用,职责单一,注释明确)
|
||||
/**
|
||||
* 一站式初始化所有关于页逻辑,包含参数、信息、视图全流程初始化
|
||||
@@ -106,10 +152,6 @@ public class AboutView extends LinearLayout {
|
||||
LogUtils.w(TAG, "initAll() 初始化终止:APPInfo 为 null,无法获取应用核心信息");
|
||||
return;
|
||||
}
|
||||
// 基础布局配置
|
||||
setOrientation(VERTICAL);
|
||||
setPadding(dp2px(PADDING_MID), dp2px(PADDING_LARGE), dp2px(PADDING_MID), dp2px(PADDING_LARGE));
|
||||
setGravity(Gravity.CENTER_HORIZONTAL);
|
||||
|
||||
// 按初始化流程执行,有序无冗余
|
||||
initDefaultParams();
|
||||
@@ -129,7 +171,7 @@ public class AboutView extends LinearLayout {
|
||||
public void setAPPInfoAndInit(APPInfo appInfo) {
|
||||
LogUtils.d(TAG, "setAPPInfoAndInit() 调用,传入新APPInfo:" + (appInfo == null ? "null" : appInfo.getAppName()));
|
||||
this.mAPPInfo = appInfo;
|
||||
removeAllViews();
|
||||
llFunctionContainer.removeAllViews();
|
||||
initAll();
|
||||
LogUtils.d(TAG, "setAPPInfoAndInit() 应用信息重置+页面重构完成");
|
||||
}
|
||||
@@ -141,7 +183,7 @@ public class AboutView extends LinearLayout {
|
||||
public void setAPPInfo(APPInfo appInfo) {
|
||||
LogUtils.d(TAG, "setAPPInfo() 调用,传入APPInfo:" + (appInfo == null ? "null" : appInfo.getAppName()));
|
||||
this.mAPPInfo = appInfo;
|
||||
removeAllViews();
|
||||
llFunctionContainer.removeAllViews();
|
||||
initAll();
|
||||
}
|
||||
|
||||
@@ -196,7 +238,7 @@ public class AboutView extends LinearLayout {
|
||||
LogUtils.d(TAG, "initAppVersionInfo() 获取版本号失败,默认赋值unknown", e);
|
||||
mszAppVersionName = "unknown";
|
||||
}
|
||||
mszCurrentAppPackageName = String.format("%s_%s.apk", mszAppAPKName, mszAppVersionName);
|
||||
mszCurrentAppPackageName = String.format("%s_%s.apk", mszAppVersionName, mszAppVersionName);
|
||||
LogUtils.d(TAG, "initAppVersionInfo() 完成,版本号:" + mszAppVersionName + ",当前APK名:" + mszCurrentAppPackageName);
|
||||
}
|
||||
|
||||
@@ -245,77 +287,37 @@ public class AboutView extends LinearLayout {
|
||||
}
|
||||
|
||||
/**
|
||||
* 核心视图组装:按 图标→应用信息→分割线→通用功能控件 顺序构建页面
|
||||
* 核心视图组装:赋值基础信息+添加功能项
|
||||
*/
|
||||
private void initAboutPageView() {
|
||||
LogUtils.d(TAG, "initAboutPageView() 开始组装关于页视图");
|
||||
addAppIcon();
|
||||
addAppInfoDesc();
|
||||
addLineSeparator();
|
||||
// 基础信息赋值
|
||||
ivAppIcon.setImageResource(mnAppIcon);
|
||||
tvAppNameVersion.setText(String.format("%s %s", mszAppName, mszAppVersionName));
|
||||
if (mszAppDescription.isEmpty()) {
|
||||
tvAppDesc.setVisibility(GONE);
|
||||
} else {
|
||||
tvAppDesc.setVisibility(VISIBLE);
|
||||
tvAppDesc.setText(mszAppDescription);
|
||||
}
|
||||
|
||||
// 通用功能控件:网页跳转类+邮件类,复用抽象控件
|
||||
addView(new WebJumpFunctionItemView(mContext, "WinBoLL 主页", WINBOLL_OFFICIAL_HOME, R.drawable.ic_winboll));
|
||||
addView(new EmailFunctionItemView(mContext, "联系邮箱", "WinBoLLStudio<studio@winboll.cc>", R.drawable.ic_winboll));
|
||||
addFunctionView(new WebJumpFunctionItemView(mContext, "WinBoLL 主页", WINBOLL_OFFICIAL_HOME, R.drawable.ic_winboll));
|
||||
addFunctionView(new EmailFunctionItemView(mContext, "联系邮箱", "WinBoLLStudio<studio@winboll.cc>", R.drawable.ic_winboll));
|
||||
if (!mszHomePage.isEmpty()) {
|
||||
addView(new WebJumpFunctionItemView(mContext, "应用APK下载地址", mszHomePage, R.drawable.ic_winboll));
|
||||
addFunctionView(new WebJumpFunctionItemView(mContext, "应用APK下载地址", mszHomePage, R.drawable.ic_winboll));
|
||||
}
|
||||
if (!mszGitea.isEmpty()) {
|
||||
addView(new WebJumpFunctionItemView(mContext, "应用Git源码地址", mszGitea, R.drawable.ic_winboll));
|
||||
addFunctionView(new WebJumpFunctionItemView(mContext, "应用Git源码地址", mszGitea, R.drawable.ic_winboll));
|
||||
}
|
||||
LogUtils.d(TAG, "initAboutPageView() 视图组装完成,功能项加载完毕");
|
||||
}
|
||||
|
||||
// 视图构建辅助方法区(基础视图组件)
|
||||
/**
|
||||
* 添加应用图标组件,居中展示
|
||||
*/
|
||||
private void addAppIcon() {
|
||||
ImageView ivIcon = new ImageView(mContext);
|
||||
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(dp2px(ICON_SIZE), dp2px(ICON_SIZE));
|
||||
params.bottomMargin = dp2px(PADDING_MID);
|
||||
ivIcon.setLayoutParams(params);
|
||||
ivIcon.setImageResource(mnAppIcon);
|
||||
ivIcon.setScaleType(ImageView.ScaleType.CENTER_CROP);
|
||||
addView(ivIcon);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加应用名称+版本号+描述信息组件,垂直居中展示
|
||||
*/
|
||||
private void addAppInfoDesc() {
|
||||
LinearLayout llDesc = new LinearLayout(mContext);
|
||||
llDesc.setOrientation(VERTICAL);
|
||||
llDesc.setGravity(Gravity.CENTER);
|
||||
llDesc.setPadding(0, 0, 0, dp2px(PADDING_MID));
|
||||
|
||||
TextView tvAppName = new TextView(mContext);
|
||||
tvAppName.setText(String.format("%s %s", mszAppName, mszAppVersionName));
|
||||
tvAppName.setTextSize(18);
|
||||
tvAppName.setTextColor(mContext.getResources().getColor(R.color.gray_900));
|
||||
llDesc.addView(tvAppName);
|
||||
|
||||
if (!mszAppDescription.isEmpty()) {
|
||||
TextView tvDesc = new TextView(mContext);
|
||||
tvDesc.setText(mszAppDescription);
|
||||
tvDesc.setTextSize(14);
|
||||
tvDesc.setTextColor(mContext.getResources().getColor(R.color.gray_500));
|
||||
tvDesc.setPadding(0, dp2px(PADDING_SMALL), 0, 0);
|
||||
llDesc.addView(tvDesc);
|
||||
}
|
||||
addView(llDesc);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加视图分割线,区分不同功能模块
|
||||
*/
|
||||
private void addLineSeparator() {
|
||||
View line = new View(mContext);
|
||||
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, dp2px(LINE_HEIGHT));
|
||||
// 添加功能项到容器
|
||||
private void addFunctionView(View view) {
|
||||
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
|
||||
params.topMargin = dp2px(PADDING_SMALL);
|
||||
params.bottomMargin = dp2px(PADDING_MID);
|
||||
line.setLayoutParams(params);
|
||||
line.setBackgroundColor(mContext.getResources().getColor(R.color.gray_200));
|
||||
addView(line);
|
||||
llFunctionContainer.addView(view, params);
|
||||
}
|
||||
|
||||
// 工具方法区(通用工具+业务工具,静态优先,便于复用)
|
||||
|
||||
11
libappbase/src/main/res/drawable/ic_key.xml
Normal file
11
libappbase/src/main/res/drawable/ic_key.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportHeight="24"
|
||||
android:viewportWidth="24">
|
||||
<path
|
||||
android:fillColor="#ff000000"
|
||||
android:pathData="M7,14C5.9,14 5,13.1 5,12S5.9,10 7,10 9,10.9 9,12 8.1,14 7,14M12.6,10C11.8,7.7 9.6,6 7,6C3.7,6 1,8.7 1,12S3.7,18 7,18C9.6,18 11.8,16.3 12.6,14H16V18H20V14H23V10H12.6Z"/>
|
||||
|
||||
</vector>
|
||||
52
libappbase/src/main/res/layout/dialog_sign_get.xml
Normal file
52
libappbase/src/main/res/layout/dialog_sign_get.xml
Normal file
@@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp"
|
||||
android:gravity="center"
|
||||
android:background="#FFDCDCDC">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="应用指纹校验"
|
||||
android:textSize="16sp"
|
||||
android:textColor="@color/gray_900"
|
||||
android:textStyle="bold"
|
||||
android:layout_marginBottom="12dp"/>
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_sign_fingerprint"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@android:drawable/edit_text"
|
||||
android:textSize="12sp"
|
||||
android:gravity="top"
|
||||
android:hint="签名获取中..."
|
||||
android:singleLine="false"
|
||||
android:scrollHorizontally="false"
|
||||
android:scrollbars="vertical"
|
||||
android:overScrollMode="always"
|
||||
android:typeface="monospace"
|
||||
android:paddingLeft="10dp"
|
||||
android:paddingRight="10dp"/>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_auth_result"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:textSize="11sp"
|
||||
android:gravity="center"
|
||||
android:textColor="@color/gray_900"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
69
libappbase/src/main/res/layout/layout_about_view.xml
Normal file
69
libappbase/src/main/res/layout/layout_about_view.xml
Normal file
@@ -0,0 +1,69 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center_horizontal"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingTop="32dp"
|
||||
android:paddingRight="16dp"
|
||||
android:paddingBottom="32dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_app_icon"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:scaleType="centerCrop"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_app_name_version"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="18sp"
|
||||
android:textColor="@color/gray_900"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_app_desc"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@color/gray_500"/>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1px"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:background="@color/gray_200"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/ll_function_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"/>
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ImageButton
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_key"
|
||||
android:id="@+id/ib_signgetdialog"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
@@ -11,5 +11,10 @@
|
||||
<item name="colorText">#FF00B322</item>
|
||||
<item name="colorTextBackgound">#FF000000</item>
|
||||
</style>
|
||||
|
||||
<style name="DialogStyle" parent="@android:style/Theme.Dialog">
|
||||
<item name="android:windowBackground">@android:color/transparent</item>
|
||||
<item name="android:windowNoTitle">true</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
|
||||
Reference in New Issue
Block a user