1.多渠道打包
2.app更新页面
2
.idea/deploymentTargetSelector.xml
generated
@@ -4,7 +4,7 @@
|
|||||||
<selectionStates>
|
<selectionStates>
|
||||||
<SelectionState runConfigName="app">
|
<SelectionState runConfigName="app">
|
||||||
<option name="selectionMode" value="DROPDOWN" />
|
<option name="selectionMode" value="DROPDOWN" />
|
||||||
<DropdownSelection timestamp="2025-09-27T07:43:19.842817300Z">
|
<DropdownSelection timestamp="2025-09-18T12:45:46.137835600Z">
|
||||||
<Target type="DEFAULT_BOOT">
|
<Target type="DEFAULT_BOOT">
|
||||||
<handle>
|
<handle>
|
||||||
<DeviceId pluginId="PhysicalDevice" identifier="serial=6705124a" />
|
<DeviceId pluginId="PhysicalDevice" identifier="serial=6705124a" />
|
||||||
|
|||||||
@@ -33,8 +33,7 @@ android {
|
|||||||
javaCompileOptions {
|
javaCompileOptions {
|
||||||
annotationProcessorOptions {
|
annotationProcessorOptions {
|
||||||
arguments = [
|
arguments = [
|
||||||
// AROUTER_MODULE_NAME: project.getName()
|
AROUTER_MODULE_NAME: project.getName()
|
||||||
AROUTER_MODULE_NAME: android.defaultConfig.applicationId
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -102,7 +101,7 @@ android {
|
|||||||
}
|
}
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
minifyEnabled false
|
minifyEnabled true
|
||||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||||
signingConfig signingConfigs.release
|
signingConfig signingConfigs.release
|
||||||
|
|
||||||
@@ -124,9 +123,7 @@ android {
|
|||||||
|
|
||||||
debug {
|
debug {
|
||||||
debuggable true
|
debuggable true
|
||||||
minifyEnabled false
|
minifyEnabled true
|
||||||
// applicationIdSuffix ".test" // 为测试包添加包名后缀
|
|
||||||
// resValue("string", "app_name", "秘地测试版")
|
|
||||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||||
signingConfig signingConfigs.debug
|
signingConfig signingConfigs.debug
|
||||||
|
|
||||||
@@ -165,7 +162,7 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = '11'
|
jvmTarget = '17'
|
||||||
}
|
}
|
||||||
dexOptions {
|
dexOptions {
|
||||||
dexInProcess true
|
dexInProcess true
|
||||||
@@ -193,7 +190,13 @@ dependencies {
|
|||||||
implementation files('libs/logger-2.2.2-release.aar')
|
implementation files('libs/logger-2.2.2-release.aar')
|
||||||
implementation files('libs/main-2.2.3-release.aar')
|
implementation files('libs/main-2.2.3-release.aar')
|
||||||
|
|
||||||
|
implementation files('libs/WbCloudFaceLiveSdk-face-v6.6.2-8e4718fc.aar')
|
||||||
|
implementation files('libs/WbCloudNormal-v5.1.10-4e3e198.aar')
|
||||||
|
|
||||||
|
|
||||||
|
implementation(libs.arouter.api.v150)
|
||||||
|
//annotationProcessor
|
||||||
|
annotationProcessor libs.arouter.compiler
|
||||||
implementation project(':modulevocal') // 必须
|
implementation project(':modulevocal') // 必须
|
||||||
annotationProcessor project(':modulevocal') // 关键!
|
annotationProcessor project(':modulevocal') // 关键!
|
||||||
|
|
||||||
@@ -201,10 +204,6 @@ dependencies {
|
|||||||
api project(":moduleLogin")
|
api project(":moduleLogin")
|
||||||
implementation project(':modulemain')
|
implementation project(':modulemain')
|
||||||
|
|
||||||
implementation(libs.arouter.api.v150)
|
|
||||||
//annotationProcessor
|
|
||||||
annotationProcessor libs.arouter.compiler
|
|
||||||
|
|
||||||
//aar的名称,例如:WbCloudFaceLiveSdk-v6.0.0-1234567.aar,填入'WbCloudFaceLiveSdk-v6.0.0-1234567'
|
//aar的名称,例如:WbCloudFaceLiveSdk-v6.0.0-1234567.aar,填入'WbCloudFaceLiveSdk-v6.0.0-1234567'
|
||||||
// implementation(name: 'WbCloudFaceLiveSdk-face-v6.6.2-8e4718fc', ext: 'aar')
|
// implementation(name: 'WbCloudFaceLiveSdk-face-v6.6.2-8e4718fc', ext: 'aar')
|
||||||
////2. 云normal SDK,
|
////2. 云normal SDK,
|
||||||
|
|||||||
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_app_bate.png
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_app_bate.png
Normal file
|
After Width: | Height: | Size: 789 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_app_bate.png
Normal file
|
After Width: | Height: | Size: 2.7 MiB |
BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher_app_bate.png
Normal file
|
After Width: | Height: | Size: 5.9 MiB |
BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher_app_bate.png
Normal file
|
After Width: | Height: | Size: 11 MiB |
@@ -51,7 +51,7 @@ public class EnvironmentPrefs {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
// 默认使用生产环境
|
// 默认使用生产环境
|
||||||
String envName = sharedPreferences.getString(KEY_ENV, EnvironmentEnum.PRODUCTION.name());
|
String envName = sharedPreferences.getString(KEY_ENV, EnvironmentEnum.TEST.name());
|
||||||
try {
|
try {
|
||||||
return EnvironmentEnum.valueOf(envName);
|
return EnvironmentEnum.valueOf(envName);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
|
|||||||
@@ -0,0 +1,207 @@
|
|||||||
|
package com.xscm.moduleutil.view
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.graphics.Typeface
|
||||||
|
import android.text.Html
|
||||||
|
import android.text.Spannable
|
||||||
|
import android.text.SpannableStringBuilder
|
||||||
|
import android.text.TextPaint
|
||||||
|
import android.text.method.LinkMovementMethod
|
||||||
|
import android.text.style.*
|
||||||
|
import android.util.Log
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.annotation.ColorInt
|
||||||
|
import androidx.annotation.StringRes
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 封装了富文本展示功能的自定义TextView
|
||||||
|
* 支持HTML格式、自定义样式文本和点击事件
|
||||||
|
*/
|
||||||
|
class RichTextView @JvmOverloads constructor(
|
||||||
|
context: Context,
|
||||||
|
attrs: AttributeSet? = null,
|
||||||
|
defStyleAttr: Int = 0
|
||||||
|
) : androidx.appcompat.widget.AppCompatTextView(context, attrs, defStyleAttr) {
|
||||||
|
|
||||||
|
// 富文本构建器
|
||||||
|
private val spannableBuilder = SpannableStringBuilder()
|
||||||
|
|
||||||
|
init {
|
||||||
|
// 初始化配置
|
||||||
|
movementMethod = LinkMovementMethod.getInstance()
|
||||||
|
highlightColor = Color.TRANSPARENT // 移除点击高亮
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置HTML格式的富文本
|
||||||
|
*/
|
||||||
|
fun setHtmlText(html: String) {
|
||||||
|
val spanned = if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
|
||||||
|
Html.fromHtml(html, Html.FROM_HTML_MODE_COMPACT)
|
||||||
|
} else {
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
Html.fromHtml(html)
|
||||||
|
}
|
||||||
|
text = spanned
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从资源文件设置HTML富文本
|
||||||
|
*/
|
||||||
|
fun setHtmlText(@StringRes resId: Int) {
|
||||||
|
setHtmlText(context.getString(resId))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开始构建富文本
|
||||||
|
*/
|
||||||
|
fun beginBuild(): RichTextBuilder {
|
||||||
|
spannableBuilder.clear()
|
||||||
|
return RichTextBuilder()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 富文本构建器
|
||||||
|
* 支持链式调用添加各种样式的文本
|
||||||
|
*/
|
||||||
|
inner class RichTextBuilder {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加普通文本
|
||||||
|
*/
|
||||||
|
fun addText(text: String): RichTextBuilder {
|
||||||
|
spannableBuilder.append(text)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加普通文本(从资源文件)
|
||||||
|
*/
|
||||||
|
fun addText(@StringRes resId: Int): RichTextBuilder {
|
||||||
|
return addText(context.getString(resId))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加加粗文本
|
||||||
|
*/
|
||||||
|
fun addBoldText(text: String): RichTextBuilder {
|
||||||
|
return addStyledText(text, StyleSpan(Typeface.BOLD))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加斜体文本
|
||||||
|
*/
|
||||||
|
fun addItalicText(text: String): RichTextBuilder {
|
||||||
|
return addStyledText(text, StyleSpan(Typeface.ITALIC))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加下划线文本
|
||||||
|
*/
|
||||||
|
fun addUnderlineText(text: String): RichTextBuilder {
|
||||||
|
return addStyledText(text, UnderlineSpan())
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加删除线文本
|
||||||
|
*/
|
||||||
|
fun addStrikethroughText(text: String): RichTextBuilder {
|
||||||
|
return addStyledText(text, StrikethroughSpan())
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加指定颜色的文本
|
||||||
|
*/
|
||||||
|
fun addColoredText(text: String, @ColorInt color: Int): RichTextBuilder {
|
||||||
|
return addStyledText(text, ForegroundColorSpan(color))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加指定背景色的文本
|
||||||
|
*/
|
||||||
|
fun addBackgroundColoredText(text: String, @ColorInt color: Int): RichTextBuilder {
|
||||||
|
return addStyledText(text, BackgroundColorSpan(color))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加指定大小的文本
|
||||||
|
* @param proportion 相对于默认大小的比例
|
||||||
|
*/
|
||||||
|
fun addSizedText(text: String, proportion: Float): RichTextBuilder {
|
||||||
|
return addStyledText(text, RelativeSizeSpan(proportion))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加带有点击事件的文本
|
||||||
|
*/
|
||||||
|
fun addClickableText(
|
||||||
|
text: String,
|
||||||
|
@ColorInt linkColor: Int = Color.BLUE,
|
||||||
|
isUnderline: Boolean = false,
|
||||||
|
onClick: () -> Unit
|
||||||
|
): RichTextBuilder {
|
||||||
|
val start = spannableBuilder.length
|
||||||
|
spannableBuilder.append(text)
|
||||||
|
val end = spannableBuilder.length
|
||||||
|
|
||||||
|
val clickableSpan = object : ClickableSpan() {
|
||||||
|
override fun onClick(widget: View) {
|
||||||
|
onClick.invoke()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateDrawState(ds: TextPaint) {
|
||||||
|
super.updateDrawState(ds)
|
||||||
|
ds.color = linkColor
|
||||||
|
ds.isUnderlineText = isUnderline
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
spannableBuilder.setSpan(
|
||||||
|
clickableSpan,
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
|
||||||
|
)
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加换行
|
||||||
|
*/
|
||||||
|
fun addLineBreak(): RichTextBuilder {
|
||||||
|
spannableBuilder.append("\n")
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加自定义样式的文本
|
||||||
|
*/
|
||||||
|
fun addStyledText(text: String, vararg spans: Any): RichTextBuilder {
|
||||||
|
val start = spannableBuilder.length
|
||||||
|
spannableBuilder.append(text)
|
||||||
|
val end = spannableBuilder.length
|
||||||
|
|
||||||
|
spans.forEach { span ->
|
||||||
|
spannableBuilder.setSpan(
|
||||||
|
span,
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 完成构建并应用到TextView
|
||||||
|
*/
|
||||||
|
fun build() {
|
||||||
|
text = spannableBuilder
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
8
moduleUtil/src/main/res/drawable/bg_bttom_fff.xml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<corners
|
||||||
|
android:bottomLeftRadius="@dimen/dp_16"
|
||||||
|
android:bottomRightRadius="@dimen/dp_16"
|
||||||
|
/>
|
||||||
|
<solid android:color="@color/white" />
|
||||||
|
</shape>
|
||||||
@@ -52,7 +52,7 @@
|
|||||||
android:layout_height="@dimen/dp_150"
|
android:layout_height="@dimen/dp_150"
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
<TextView
|
<com.xscm.moduleutil.view.RichTextView
|
||||||
android:id="@+id/tv_content"
|
android:id="@+id/tv_content"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 403 KiB |