mirror of
https://github.com/pppscn/SmsForwarder
synced 2025-08-03 01:17:41 +08:00
Compare commits
49 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
751f1b3163 | ||
![]() |
45dc37aea9 | ||
![]() |
de9509fead | ||
![]() |
114052d1c6 | ||
![]() |
0391868790 | ||
![]() |
44728b858a | ||
![]() |
23acf01c61 | ||
![]() |
b733fc2d4c | ||
![]() |
992cabe323 | ||
![]() |
8b37862121 | ||
![]() |
f49310027e | ||
![]() |
cc86c0718f | ||
![]() |
2a910fe504 | ||
![]() |
0a3f9f53f1 | ||
![]() |
a77f630524 | ||
![]() |
7c33566696 | ||
![]() |
f029048d09 | ||
![]() |
b05d856f26 | ||
![]() |
3a341f6c4e | ||
![]() |
c86f20c6de | ||
![]() |
aa8ab646f5 | ||
![]() |
8e7c425fdc | ||
![]() |
dc3726d0de | ||
![]() |
3adfffee4f | ||
![]() |
c56ac0e425 | ||
![]() |
3cc2311600 | ||
![]() |
5c19c10121 | ||
![]() |
785a3a2364 | ||
![]() |
66831865cb | ||
![]() |
d4ed59b37f | ||
![]() |
573174feea | ||
![]() |
a83f0da45a | ||
![]() |
b35ba17beb | ||
![]() |
ff83a8a5f7 | ||
![]() |
9436e3498b | ||
![]() |
e3df9bada6 | ||
![]() |
3fccec54b1 | ||
![]() |
9e28c2922c | ||
![]() |
9c03e30e5d | ||
![]() |
d5f476bc32 | ||
![]() |
f7d2544ee9 | ||
![]() |
8cc4c76735 | ||
![]() |
9dbb2572fa | ||
![]() |
505c719b4a | ||
![]() |
40c8c5be6e | ||
![]() |
b80b1f9620 | ||
![]() |
4e8d8283c2 | ||
![]() |
894155df22 | ||
![]() |
b0e1ce76cf |
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
@ -1,3 +1,3 @@
|
|||||||
# These are supported funding model platforms
|
# These are supported funding model platforms
|
||||||
|
|
||||||
custom: ["https://foruda.gitee.com/images/1705068554951915754/89c6e226_16273.png", "https://afdian.net/a/pppscn", "https://github.com/pppscn/SmsForwarder/wiki/%E6%89%93%E8%B5%8F%E5%90%8D%E5%8D%95", "https://gitee.com/pp/SmsForwarder/wikis/pages?sort_id=4912193&doc_id=1821427"]
|
custom: ["https://foruda.gitee.com/images/1730529431184709105/20bfc86c_16273.gif", "https://ifdian.net/a/pppscn", "https://github.com/pppscn/SmsForwarder/wiki/%E6%89%93%E8%B5%8F%E5%90%8D%E5%8D%95", "https://gitee.com/pp/SmsForwarder/wikis/pages?sort_id=4912193&doc_id=1821427"]
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -28,3 +28,4 @@
|
|||||||
/pic/*.drawio
|
/pic/*.drawio
|
||||||
/pic/*.vsdx
|
/pic/*.vsdx
|
||||||
/psd
|
/psd
|
||||||
|
/pic/*.psd
|
||||||
|
@ -101,7 +101,7 @@
|
|||||||
+ https://github.com/yanzhenjie/AndServer (HttpServer)
|
+ https://github.com/yanzhenjie/AndServer (HttpServer)
|
||||||
+ https://github.com/jenly1314/Location (Location)
|
+ https://github.com/jenly1314/Location (Location)
|
||||||
+ https://gitee.com/xuankaicat/kmnkt (socket通信)
|
+ https://gitee.com/xuankaicat/kmnkt (socket通信)
|
||||||
+ [<img src="https://resources.jetbrains.com/storage/products/company/brand/logos/jb_beam.svg?_ga=2.126618957.1361252949.1638261367-1417196221.1635638144&_gl=1*1pfl3dq*_ga*MTQxNzE5NjIyMS4xNjM1NjM4MTQ0*_ga_V0XZL7QHEB*MTYzODMzMjA4OC43LjAuMTYzODMzMjA5Ny4w" alt="GitHub license" style="width:96px" width="96" />](https://jb.gg/OpenSourceSupport) (License Certificate for JetBrains All Products Pack)
|
+ [<img src="https://resources.jetbrains.com/storage/products/company/brand/logos/jetbrains.svg" alt="GitHub license" style="width:159px; height: 32px" width="159" height="32" />](https://jb.gg/OpenSourceSupport) (License Certificate for JetBrains All Products Pack)
|
||||||
|
|
||||||
--------
|
--------
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ See more screenshots:https://github.com/pppscn/SmsForwarder/wiki
|
|||||||
+ https://github.com/yanzhenjie/AndServer (HttpServer)
|
+ https://github.com/yanzhenjie/AndServer (HttpServer)
|
||||||
+ https://github.com/jenly1314/Location (Location)
|
+ https://github.com/jenly1314/Location (Location)
|
||||||
+ https://gitee.com/xuankaicat/kmnkt (socket)
|
+ https://gitee.com/xuankaicat/kmnkt (socket)
|
||||||
+ [<img src="https://resources.jetbrains.com/storage/products/company/brand/logos/jb_beam.svg?_ga=2.126618957.1361252949.1638261367-1417196221.1635638144&_gl=1*1pfl3dq*_ga*MTQxNzE5NjIyMS4xNjM1NjM4MTQ0*_ga_V0XZL7QHEB*MTYzODMzMjA4OC43LjAuMTYzODMzMjA5Ny4w" alt="GitHub license" style="width:96px" width="96" />](https://jb.gg/OpenSourceSupport) (License Certificate for JetBrains All Products Pack)
|
+ [<img src="https://resources.jetbrains.com/storage/products/company/brand/logos/jetbrains.svg" alt="GitHub license" style="width:159px; height: 32px" width="159" height="32" />](https://jb.gg/OpenSourceSupport) (License Certificate for JetBrains All Products Pack)
|
||||||
|
|
||||||
--------
|
--------
|
||||||
|
|
||||||
|
@ -277,8 +277,8 @@ dependencies {
|
|||||||
//vLayout:https://github.com/alibaba/vlayout
|
//vLayout:https://github.com/alibaba/vlayout
|
||||||
implementation 'com.alibaba.android:vlayout:1.3.0'
|
implementation 'com.alibaba.android:vlayout:1.3.0'
|
||||||
//下拉刷新
|
//下拉刷新
|
||||||
implementation 'com.github.xuexiangjys.SmartRefreshLayout:refresh-header:1.1.5'
|
implementation 'com.github.xuexiangjys.SmartRefreshLayout:refresh-header:1.1.4'
|
||||||
implementation 'com.github.xuexiangjys.SmartRefreshLayout:refresh-layout:1.1.5'
|
implementation 'com.github.xuexiangjys.SmartRefreshLayout:refresh-layout:1.1.4'
|
||||||
//WebView
|
//WebView
|
||||||
implementation 'com.github.xuexiangjys.AgentWeb:agentweb-core:1.0.1'
|
implementation 'com.github.xuexiangjys.AgentWeb:agentweb-core:1.0.1'
|
||||||
implementation 'com.github.xuexiangjys.AgentWeb:agentweb-download:1.0.1'//选填
|
implementation 'com.github.xuexiangjys.AgentWeb:agentweb-download:1.0.1'//选填
|
||||||
@ -286,7 +286,7 @@ dependencies {
|
|||||||
implementation 'me.jessyan:autosize:1.2.1'
|
implementation 'me.jessyan:autosize:1.2.1'
|
||||||
//友盟统计
|
//友盟统计
|
||||||
implementation 'com.umeng.umsdk:common:9.6.8'
|
implementation 'com.umeng.umsdk:common:9.6.8'
|
||||||
implementation 'com.umeng.umsdk:asms:1.8.2'
|
implementation 'com.umeng.umsdk:asms:1.8.6'
|
||||||
|
|
||||||
//预加载占位控件
|
//预加载占位控件
|
||||||
implementation 'me.samlss:broccoli:1.0.0'
|
implementation 'me.samlss:broccoli:1.0.0'
|
||||||
@ -323,8 +323,8 @@ dependencies {
|
|||||||
implementation 'io.github.jeremyliao:live-event-bus-x:1.8.0'
|
implementation 'io.github.jeremyliao:live-event-bus-x:1.8.0'
|
||||||
|
|
||||||
//MarkdownView:https://github.com/tiagohm/MarkdownView
|
//MarkdownView:https://github.com/tiagohm/MarkdownView
|
||||||
implementation 'com.github.tiagohm.MarkdownView:library:0.19.0'
|
implementation 'com.github.pppscn.MarkdownView:library:0.19.0'
|
||||||
//implementation 'com.github.tiagohm.MarkdownView:emoji:0.19.0'
|
//implementation 'com.github.pppscn.MarkdownView:emoji:0.19.0'
|
||||||
|
|
||||||
def retrofit2_version = '2.9.0'
|
def retrofit2_version = '2.9.0'
|
||||||
//noinspection GradleDependency
|
//noinspection GradleDependency
|
||||||
@ -342,13 +342,14 @@ dependencies {
|
|||||||
testImplementation "androidx.paging:paging-common-ktx:$paging_version"
|
testImplementation "androidx.paging:paging-common-ktx:$paging_version"
|
||||||
|
|
||||||
//权限请求框架:https://github.com/getActivity/XXPermissions
|
//权限请求框架:https://github.com/getActivity/XXPermissions
|
||||||
implementation 'com.github.getActivity:XXPermissions:18.62'
|
implementation 'com.github.getActivity:XXPermissions:20.0'
|
||||||
//语种切换框架:https://github.com/getActivity/MultiLanguages
|
//语种切换框架:https://github.com/getActivity/MultiLanguages
|
||||||
implementation 'com.github.getActivity:MultiLanguages:b47f7be' //9.3
|
implementation 'com.github.getActivity:MultiLanguages:b47f7be' //9.3
|
||||||
|
|
||||||
def mail_version = '1.6.7'
|
// https://jakartaee.github.io/mail-api/Android
|
||||||
implementation "com.sun.mail:android-mail:$mail_version"
|
def mail_version = '2.0.1'
|
||||||
implementation "com.sun.mail:android-activation:$mail_version"
|
implementation "com.sun.mail:jakarta.mail:$mail_version"
|
||||||
|
implementation "com.sun.activation:jakarta.activation:$mail_version"
|
||||||
|
|
||||||
//国密算法SM4 的JAVA实现(基于BC实现)
|
//国密算法SM4 的JAVA实现(基于BC实现)
|
||||||
def bouncycastle_version = '1.77'
|
def bouncycastle_version = '1.77'
|
||||||
|
@ -6,7 +6,12 @@
|
|||||||
<uses-feature
|
<uses-feature
|
||||||
android:name="android.hardware.telephony"
|
android:name="android.hardware.telephony"
|
||||||
android:required="false" />
|
android:required="false" />
|
||||||
|
<uses-feature android:name="android.hardware.camera" />
|
||||||
|
<uses-feature
|
||||||
|
android:name="android.hardware.camera.flash"
|
||||||
|
android:required="false" />
|
||||||
|
|
||||||
|
<uses-permission android:name="com.android.permission.GET_INSTALLED_APPS" />
|
||||||
<uses-permission
|
<uses-permission
|
||||||
android:name="android.permission.QUERY_ALL_PACKAGES"
|
android:name="android.permission.QUERY_ALL_PACKAGES"
|
||||||
tools:ignore="QueryAllPackagesPermission" />
|
tools:ignore="QueryAllPackagesPermission" />
|
||||||
@ -72,6 +77,8 @@
|
|||||||
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
||||||
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
||||||
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
|
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
|
||||||
|
<uses-permission android:name="android.permission.VIBRATE" />
|
||||||
|
<uses-permission android:name="android.permission.CAMERA" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name=".App"
|
android:name=".App"
|
||||||
@ -156,10 +163,6 @@
|
|||||||
<data android:scheme="https" />
|
<data android:scheme="https" />
|
||||||
<data android:scheme="about" />
|
<data android:scheme="about" />
|
||||||
<data android:scheme="javascript" />
|
<data android:scheme="javascript" />
|
||||||
<!-- 设置自己的deeplink -->
|
|
||||||
<!-- <data-->
|
|
||||||
<!-- android:host="xxx.com"-->
|
|
||||||
<!-- android:scheme="xui"/>-->
|
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
<!-- AppLink -->
|
<!-- AppLink -->
|
||||||
<intent-filter
|
<intent-filter
|
||||||
|
@ -1,13 +1,21 @@
|
|||||||
{
|
{
|
||||||
"Code": 0,
|
"Code": 0,
|
||||||
"Data": [
|
"Data": [
|
||||||
|
{
|
||||||
|
"title": "短信转发器",
|
||||||
|
"content": "本软件用于监控Android手机短信、来电、APP通知,并根据指定规则转发到其他设备!<br />\n请确认您是否清楚该软件的用途?!<br />\n否则,请立即卸载!"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "防诈提醒",
|
||||||
|
"content": "本软件不参与任何刷单返利担保!请您远离刷单返利陷阱,谨防网络诈骗!<br />\n请再次确认是否出于本人自用需要自愿安装?!<br />\n否则,请立即卸载!"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"title": "新用户必读",
|
"title": "新用户必读",
|
||||||
"content": "开始设置之前,请您认真地看一遍 <a href=\"https://gitee.com/pp/SmsForwarder/wikis/pages\"><font color=\"#800080\">Wiki</font></a> !<br />\n遇到问题,请按照 <a href=\"https://gitee.com/pp/SmsForwarder/wikis/pages?sort_id=4877445&doc_id=1821427\"><font color=\"#0000FF\">常见问题</font></a> 章节进行排查!<br />\n没找到答案的,再加入互助交流群提问,请清楚地描述问题,并给出对应的配置截图与相关日志,方便大家直观的判断问题! "
|
"content": "开始设置之前,请您认真地看一遍 <a href=\"https://gitee.com/pp/SmsForwarder/wikis/pages\"><font color=\"#800080\">Wiki</font></a> !<br />\n遇到问题,请按照 <a href=\"https://gitee.com/pp/SmsForwarder/wikis/pages?sort_id=4877445&doc_id=1821427\"><font color=\"#0000FF\">常见问题</font></a> 章节进行排查!<br />\n没找到答案的,再加入互助交流群提问,请清楚地描述问题,并给出对应的配置截图与相关日志,方便大家直观的判断问题! "
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "SmsF 互助交流群",
|
"title": "SmsF 互助交流群",
|
||||||
"content": "<a href=\"https://qun.qq.com/qqweb/qunpro/share?_wv=3&_wwv=128&appChannel=share&inviteCode=1W5aewP&appChannel=share&businessType=9&from=246610&biz=ka\">QQ频道号: q7oofwp13s</a><br /><a href=\"https://t.me/+QBZgnL_fxYM0NjE9\">Telegram 群组</a><br />钉钉群号: 29760014208"
|
"content": "<a href=\"https://t.me/+QBZgnL_fxYM0NjE9\">Telegram 群组</a>"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "打赏名单",
|
"title": "打赏名单",
|
||||||
|
@ -93,6 +93,15 @@ class App : Application(), CactusCallback, Configuration.Provider by Core {
|
|||||||
@SuppressLint("StaticFieldLeak")
|
@SuppressLint("StaticFieldLeak")
|
||||||
lateinit var context: Context
|
lateinit var context: Context
|
||||||
|
|
||||||
|
//自定义模板可用变量标签
|
||||||
|
var COMMON_TAG_MAP: MutableMap<String, String> = mutableMapOf()
|
||||||
|
var SMS_TAG_MAP: MutableMap<String, String> = mutableMapOf()
|
||||||
|
var CALL_TAG_MAP: MutableMap<String, String> = mutableMapOf()
|
||||||
|
var APP_TAG_MAP: MutableMap<String, String> = mutableMapOf()
|
||||||
|
var LOCATION_TAG_MAP: MutableMap<String, String> = mutableMapOf()
|
||||||
|
var BATTERY_TAG_MAP: MutableMap<String, String> = mutableMapOf()
|
||||||
|
var NETWORK_TAG_MAP: MutableMap<String, String> = mutableMapOf()
|
||||||
|
|
||||||
//通话类型:1.来电挂机 2.去电挂机 3.未接来电 4.来电提醒 5.来电接通 6.去电拨出
|
//通话类型:1.来电挂机 2.去电挂机 3.未接来电 4.来电提醒 5.来电接通 6.去电拨出
|
||||||
var CALL_TYPE_MAP: MutableMap<String, String> = mutableMapOf()
|
var CALL_TYPE_MAP: MutableMap<String, String> = mutableMapOf()
|
||||||
var FILED_MAP: MutableMap<String, String> = mutableMapOf()
|
var FILED_MAP: MutableMap<String, String> = mutableMapOf()
|
||||||
@ -290,7 +299,7 @@ class App : Application(), CactusCallback, Configuration.Provider by Core {
|
|||||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P && SettingUtils.enableOnePixelActivity) {
|
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P && SettingUtils.enableOnePixelActivity) {
|
||||||
setOnePixEnabled(true)
|
setOnePixEnabled(true)
|
||||||
}
|
}
|
||||||
//奔溃是否可以重启用户界面
|
//崩溃是否可以重启用户界面
|
||||||
setCrashRestartUIEnabled(true)
|
setCrashRestartUIEnabled(true)
|
||||||
addCallback({
|
addCallback({
|
||||||
Log.d(TAG, "Cactus保活:onStop回调")
|
Log.d(TAG, "Cactus保活:onStop回调")
|
||||||
@ -390,6 +399,78 @@ class App : Application(), CactusCallback, Configuration.Provider by Core {
|
|||||||
private fun switchLanguage(newLocale: Locale) {
|
private fun switchLanguage(newLocale: Locale) {
|
||||||
isNeedSpaceBetweenWords = !newLocale.language.contains("zh")
|
isNeedSpaceBetweenWords = !newLocale.language.contains("zh")
|
||||||
|
|
||||||
|
//自定义模板可用变量标签
|
||||||
|
COMMON_TAG_MAP.clear()
|
||||||
|
COMMON_TAG_MAP.putAll(
|
||||||
|
mapOf(
|
||||||
|
getString(R.string.tag_receive_time) to getString(R.string.insert_tag_receive_time),
|
||||||
|
getString(R.string.tag_current_time) to getString(R.string.insert_tag_current_time),
|
||||||
|
getString(R.string.tag_device_name) to getString(R.string.insert_tag_device_name),
|
||||||
|
getString(R.string.tag_app_version) to getString(R.string.insert_tag_app_version),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
SMS_TAG_MAP.clear()
|
||||||
|
SMS_TAG_MAP.putAll(
|
||||||
|
mapOf(
|
||||||
|
getString(R.string.tag_from) to getString(R.string.insert_tag_from),
|
||||||
|
getString(R.string.tag_sms) to getString(R.string.insert_tag_sms),
|
||||||
|
getString(R.string.tag_card_slot) to getString(R.string.insert_tag_card_slot),
|
||||||
|
getString(R.string.tag_card_subid) to getString(R.string.insert_tag_card_subid),
|
||||||
|
getString(R.string.tag_contact_name) to getString(R.string.insert_tag_contact_name),
|
||||||
|
getString(R.string.tag_phone_area) to getString(R.string.insert_tag_phone_area),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
CALL_TAG_MAP.clear()
|
||||||
|
CALL_TAG_MAP.putAll(
|
||||||
|
mapOf(
|
||||||
|
getString(R.string.tag_from) to getString(R.string.insert_tag_from),
|
||||||
|
getString(R.string.tag_sms) to getString(R.string.insert_tag_msg),
|
||||||
|
getString(R.string.tag_card_slot) to getString(R.string.insert_tag_card_slot),
|
||||||
|
getString(R.string.tag_card_subid) to getString(R.string.insert_tag_card_subid),
|
||||||
|
getString(R.string.tag_call_type) to getString(R.string.insert_tag_call_type),
|
||||||
|
getString(R.string.tag_contact_name) to getString(R.string.insert_tag_contact_name),
|
||||||
|
getString(R.string.tag_phone_area) to getString(R.string.insert_tag_phone_area),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
APP_TAG_MAP.clear()
|
||||||
|
APP_TAG_MAP.putAll(
|
||||||
|
mapOf(
|
||||||
|
getString(R.string.tag_uid) to getString(R.string.insert_tag_uid),
|
||||||
|
getString(R.string.tag_package_name) to getString(R.string.insert_tag_package_name),
|
||||||
|
getString(R.string.tag_app_name) to getString(R.string.insert_tag_app_name),
|
||||||
|
getString(R.string.tag_title) to getString(R.string.insert_tag_title),
|
||||||
|
getString(R.string.tag_msg) to getString(R.string.insert_tag_msg),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
LOCATION_TAG_MAP.clear()
|
||||||
|
LOCATION_TAG_MAP.putAll(
|
||||||
|
mapOf(
|
||||||
|
getString(R.string.tag_location) to getString(R.string.insert_tag_location),
|
||||||
|
getString(R.string.tag_location_longitude) to getString(R.string.insert_tag_location_longitude),
|
||||||
|
getString(R.string.tag_location_latitude) to getString(R.string.insert_tag_location_latitude),
|
||||||
|
getString(R.string.tag_location_address) to getString(R.string.insert_tag_location_address),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
BATTERY_TAG_MAP.clear()
|
||||||
|
BATTERY_TAG_MAP.putAll(
|
||||||
|
mapOf(
|
||||||
|
getString(R.string.tag_battery_pct) to getString(R.string.insert_tag_battery_pct),
|
||||||
|
getString(R.string.tag_battery_status) to getString(R.string.insert_tag_battery_status),
|
||||||
|
getString(R.string.tag_battery_plugged) to getString(R.string.insert_tag_battery_plugged),
|
||||||
|
getString(R.string.tag_battery_info) to getString(R.string.insert_tag_battery_info),
|
||||||
|
getString(R.string.tag_battery_info_simple) to getString(R.string.insert_tag_battery_info_simple),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
NETWORK_TAG_MAP.clear()
|
||||||
|
NETWORK_TAG_MAP.putAll(
|
||||||
|
mapOf(
|
||||||
|
getString(R.string.tag_ipv4) to getString(R.string.insert_tag_ipv4),
|
||||||
|
getString(R.string.tag_ipv6) to getString(R.string.insert_tag_ipv6),
|
||||||
|
getString(R.string.tag_ip_list) to getString(R.string.insert_tag_ip_list),
|
||||||
|
getString(R.string.tag_net_type) to getString(R.string.insert_tag_net_type),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
CALL_TYPE_MAP.clear()
|
CALL_TYPE_MAP.clear()
|
||||||
CALL_TYPE_MAP.putAll(
|
CALL_TYPE_MAP.putAll(
|
||||||
mapOf(
|
mapOf(
|
||||||
|
@ -51,6 +51,7 @@ import com.jeremyliao.liveeventbus.LiveEventBus
|
|||||||
import com.xuexiang.xhttp2.XHttp
|
import com.xuexiang.xhttp2.XHttp
|
||||||
import com.xuexiang.xhttp2.callback.DownloadProgressCallBack
|
import com.xuexiang.xhttp2.callback.DownloadProgressCallBack
|
||||||
import com.xuexiang.xhttp2.exception.ApiException
|
import com.xuexiang.xhttp2.exception.ApiException
|
||||||
|
import com.xuexiang.xui.XUI.getContext
|
||||||
import com.xuexiang.xui.utils.ResUtils
|
import com.xuexiang.xui.utils.ResUtils
|
||||||
import com.xuexiang.xui.utils.ThemeUtils
|
import com.xuexiang.xui.utils.ThemeUtils
|
||||||
import com.xuexiang.xui.utils.ViewUtils
|
import com.xuexiang.xui.utils.ViewUtils
|
||||||
@ -207,10 +208,6 @@ class MainActivity : BaseActivity<ActivityMainBinding?>(), DrawerAdapter.OnItemS
|
|||||||
private fun initSlidingMenu(savedInstanceState: Bundle?) {
|
private fun initSlidingMenu(savedInstanceState: Bundle?) {
|
||||||
mSlidingRootNav = SlidingRootNavBuilder(this).withGravity(if (ResUtils.isRtl(this)) SlideGravity.RIGHT else SlideGravity.LEFT).withMenuOpened(false).withContentClickableWhenMenuOpened(false).withSavedState(savedInstanceState).withMenuLayout(R.layout.menu_left_drawer).inject()
|
mSlidingRootNav = SlidingRootNavBuilder(this).withGravity(if (ResUtils.isRtl(this)) SlideGravity.RIGHT else SlideGravity.LEFT).withMenuOpened(false).withContentClickableWhenMenuOpened(false).withSavedState(savedInstanceState).withMenuLayout(R.layout.menu_left_drawer).inject()
|
||||||
mLLMenu = mSlidingRootNav.layout.findViewById(R.id.ll_menu)
|
mLLMenu = mSlidingRootNav.layout.findViewById(R.id.ll_menu)
|
||||||
//val ivQrcode = mSlidingRootNav.layout.findViewById<AppCompatImageView>(R.id.iv_qrcode)
|
|
||||||
//ivQrcode.setOnClickListener { openNewPage(SettingsFragment::class.java) }
|
|
||||||
//val ivSetting = mSlidingRootNav.layout.findViewById<AppCompatImageView>(R.id.iv_setting)
|
|
||||||
//ivSetting.setOnClickListener { openNewPage(SettingsFragment::class.java) }
|
|
||||||
ViewUtils.setVisibility(mLLMenu, false)
|
ViewUtils.setVisibility(mLLMenu, false)
|
||||||
mAdapter = DrawerAdapter(
|
mAdapter = DrawerAdapter(
|
||||||
mutableListOf(
|
mutableListOf(
|
||||||
@ -243,25 +240,6 @@ class MainActivity : BaseActivity<ActivityMainBinding?>(), DrawerAdapter.OnItemS
|
|||||||
|
|
||||||
override fun onDragEnd(isMenuOpened: Boolean) {
|
override fun onDragEnd(isMenuOpened: Boolean) {
|
||||||
ViewUtils.setVisibility(mLLMenu, isMenuOpened)
|
ViewUtils.setVisibility(mLLMenu, isMenuOpened)
|
||||||
/*if (isMenuOpened) {
|
|
||||||
if (!GuideCaseView.isShowOnce(this@MainActivity, getString(R.string.guide_key_sliding_root_navigation))) {
|
|
||||||
val guideStep1 = GuideCaseView.Builder(this@MainActivity)
|
|
||||||
.title("点击进入,可切换主题样式哦~~")
|
|
||||||
.titleSize(18, TypedValue.COMPLEX_UNIT_SP)
|
|
||||||
.focusOn(ivSetting)
|
|
||||||
.build()
|
|
||||||
val guideStep2 = GuideCaseView.Builder(this@MainActivity)
|
|
||||||
.title("点击进入,扫码关注哦~~")
|
|
||||||
.titleSize(18, TypedValue.COMPLEX_UNIT_SP)
|
|
||||||
.focusOn(ivQrcode)
|
|
||||||
.build()
|
|
||||||
GuideCaseQueue()
|
|
||||||
.add(guideStep1)
|
|
||||||
.add(guideStep2)
|
|
||||||
.show()
|
|
||||||
GuideCaseView.setShowOnce(this@MainActivity, getString(R.string.guide_key_sliding_root_navigation))
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -302,16 +280,28 @@ class MainActivity : BaseActivity<ActivityMainBinding?>(), DrawerAdapter.OnItemS
|
|||||||
}
|
}
|
||||||
|
|
||||||
POS_APPS -> {
|
POS_APPS -> {
|
||||||
|
//检查读取应用列表权限是否获取
|
||||||
|
XXPermissions.with(this).permission(Permission.GET_INSTALLED_APPS).request(object : OnPermissionCallback {
|
||||||
|
override fun onGranted(permissions: MutableList<String>, allGranted: Boolean) {
|
||||||
if (App.UserAppList.isEmpty() && App.SystemAppList.isEmpty()) {
|
if (App.UserAppList.isEmpty() && App.SystemAppList.isEmpty()) {
|
||||||
XToastUtils.info(getString(R.string.loading_app_list))
|
XToastUtils.info(getString(R.string.loading_app_list))
|
||||||
val request = OneTimeWorkRequestBuilder<LoadAppListWorker>().build()
|
val request = OneTimeWorkRequestBuilder<LoadAppListWorker>().build()
|
||||||
WorkManager.getInstance(this).enqueue(request)
|
WorkManager.getInstance(getContext()).enqueue(request)
|
||||||
needToAppListFragment = true
|
needToAppListFragment = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
openNewPage(AppListFragment::class.java)
|
openNewPage(AppListFragment::class.java)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onDenied(permissions: MutableList<String>, doNotAskAgain: Boolean) {
|
||||||
|
XToastUtils.error(R.string.tips_get_installed_apps)
|
||||||
|
if (doNotAskAgain) {
|
||||||
|
XXPermissions.startPermissionActivity(getContext(), permissions)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
POS_HELP -> AgentWebActivity.goWeb(this, getString(R.string.url_help))
|
POS_HELP -> AgentWebActivity.goWeb(this, getString(R.string.url_help))
|
||||||
POS_ABOUT -> openNewPage(AboutFragment::class.java)
|
POS_ABOUT -> openNewPage(AboutFragment::class.java)
|
||||||
}
|
}
|
||||||
@ -348,6 +338,7 @@ class MainActivity : BaseActivity<ActivityMainBinding?>(), DrawerAdapter.OnItemS
|
|||||||
.build()
|
.build()
|
||||||
|
|
||||||
XHttp.downLoad(downloadUrl)
|
XHttp.downLoad(downloadUrl)
|
||||||
|
.ignoreHttpsCert()
|
||||||
.savePath(cacheDir.absolutePath)
|
.savePath(cacheDir.absolutePath)
|
||||||
.execute(object : DownloadProgressCallBack<String?>() {
|
.execute(object : DownloadProgressCallBack<String?>() {
|
||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
package com.idormy.sms.forwarder.core.http.api
|
|
||||||
|
|
||||||
import com.idormy.sms.forwarder.core.http.entity.TipInfo
|
|
||||||
import com.xuexiang.xhttp2.model.ApiResult
|
|
||||||
import io.reactivex.Observable
|
|
||||||
import retrofit2.http.GET
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author xuexiang
|
|
||||||
* @since 2021/1/9 7:01 PM
|
|
||||||
*/
|
|
||||||
@Suppress("unused")
|
|
||||||
class ApiService {
|
|
||||||
/**
|
|
||||||
* 使用的是retrofit的接口定义
|
|
||||||
*/
|
|
||||||
interface IGetService {
|
|
||||||
/**
|
|
||||||
* 获得小贴士
|
|
||||||
*/
|
|
||||||
@get:GET("/pp/SmsForwarder.wiki/raw/master/tips.json")
|
|
||||||
val tips: Observable<ApiResult<List<TipInfo?>?>>
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
package com.idormy.sms.forwarder.core.http.callback
|
|
||||||
|
|
||||||
import com.xuexiang.xhttp2.callback.SimpleCallBack
|
|
||||||
import com.xuexiang.xhttp2.exception.ApiException
|
|
||||||
import com.xuexiang.xhttp2.model.XHttpRequest
|
|
||||||
import com.xuexiang.xutil.common.StringUtils
|
|
||||||
import com.xuexiang.xutil.common.logger.Logger
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 不带错误提示的网络请求回调
|
|
||||||
*
|
|
||||||
* @author xuexiang
|
|
||||||
* @since 2019-11-18 23:02
|
|
||||||
*/
|
|
||||||
@Suppress("unused")
|
|
||||||
abstract class NoTipCallBack<T> : SimpleCallBack<T> {
|
|
||||||
/**
|
|
||||||
* 记录一下请求的url,确定出错的请求是哪个请求
|
|
||||||
*/
|
|
||||||
private var mUrl: String? = null
|
|
||||||
|
|
||||||
constructor()
|
|
||||||
constructor(req: XHttpRequest) : this(req.url)
|
|
||||||
constructor(url: String?) {
|
|
||||||
mUrl = url
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onError(e: ApiException) {
|
|
||||||
if (!StringUtils.isEmpty(mUrl)) {
|
|
||||||
Logger.e("Request Url: $mUrl", e)
|
|
||||||
} else {
|
|
||||||
Logger.e(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
package com.idormy.sms.forwarder.core.http.callback
|
|
||||||
|
|
||||||
import com.idormy.sms.forwarder.utils.XToastUtils
|
|
||||||
import com.xuexiang.xhttp2.callback.SimpleCallBack
|
|
||||||
import com.xuexiang.xhttp2.exception.ApiException
|
|
||||||
import com.xuexiang.xhttp2.model.XHttpRequest
|
|
||||||
import com.xuexiang.xutil.common.StringUtils
|
|
||||||
import com.xuexiang.xutil.common.logger.Logger
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 带错误toast提示的网络请求回调
|
|
||||||
*
|
|
||||||
* @author xuexiang
|
|
||||||
* @since 2019-11-18 23:02
|
|
||||||
*/
|
|
||||||
@Suppress("unused")
|
|
||||||
abstract class TipCallBack<T> : SimpleCallBack<T> {
|
|
||||||
/**
|
|
||||||
* 记录一下请求的url,确定出错的请求是哪个请求
|
|
||||||
*/
|
|
||||||
private var mUrl: String? = null
|
|
||||||
|
|
||||||
constructor()
|
|
||||||
constructor(req: XHttpRequest) : this(req.url)
|
|
||||||
constructor(url: String?) {
|
|
||||||
mUrl = url
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onError(e: ApiException) {
|
|
||||||
XToastUtils.error(e)
|
|
||||||
if (!StringUtils.isEmpty(mUrl)) {
|
|
||||||
Logger.e("Request Url: $mUrl", e)
|
|
||||||
} else {
|
|
||||||
Logger.e(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
package com.idormy.sms.forwarder.core.http.callback
|
|
||||||
|
|
||||||
import com.idormy.sms.forwarder.core.BaseFragment
|
|
||||||
import com.idormy.sms.forwarder.utils.XToastUtils
|
|
||||||
import com.xuexiang.xhttp2.callback.ProgressLoadingCallBack
|
|
||||||
import com.xuexiang.xhttp2.exception.ApiException
|
|
||||||
import com.xuexiang.xhttp2.model.XHttpRequest
|
|
||||||
import com.xuexiang.xhttp2.subsciber.impl.IProgressLoader
|
|
||||||
import com.xuexiang.xutil.common.StringUtils
|
|
||||||
import com.xuexiang.xutil.common.logger.Logger
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 带错误toast提示和加载进度条的网络请求回调
|
|
||||||
*
|
|
||||||
* @author xuexiang
|
|
||||||
* @since 2019-11-18 23:16
|
|
||||||
*/
|
|
||||||
@Suppress("unused")
|
|
||||||
abstract class TipProgressLoadingCallBack<T> : ProgressLoadingCallBack<T> {
|
|
||||||
/**
|
|
||||||
* 记录一下请求的url,确定出错的请求是哪个请求
|
|
||||||
*/
|
|
||||||
private var mUrl: String? = null
|
|
||||||
|
|
||||||
constructor(fragment: BaseFragment<*>) : super(fragment.progressLoader)
|
|
||||||
constructor(iProgressLoader: IProgressLoader?) : super(iProgressLoader)
|
|
||||||
constructor(req: XHttpRequest, iProgressLoader: IProgressLoader?) : this(
|
|
||||||
req.url,
|
|
||||||
iProgressLoader
|
|
||||||
)
|
|
||||||
|
|
||||||
constructor(url: String?, iProgressLoader: IProgressLoader?) : super(iProgressLoader) {
|
|
||||||
mUrl = url
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onError(e: ApiException) {
|
|
||||||
super.onError(e)
|
|
||||||
XToastUtils.error(e)
|
|
||||||
if (!StringUtils.isEmpty(mUrl)) {
|
|
||||||
Logger.e("Request Url: $mUrl", e)
|
|
||||||
} else {
|
|
||||||
Logger.e(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -28,7 +28,7 @@ import com.idormy.sms.forwarder.utils.TAG_LIST
|
|||||||
@Database(
|
@Database(
|
||||||
entities = [Frpc::class, Msg::class, Logs::class, Rule::class, Sender::class, Task::class],
|
entities = [Frpc::class, Msg::class, Logs::class, Rule::class, Sender::class, Task::class],
|
||||||
views = [LogsDetail::class],
|
views = [LogsDetail::class],
|
||||||
version = 19,
|
version = 20,
|
||||||
exportSchema = false
|
exportSchema = false
|
||||||
)
|
)
|
||||||
@TypeConverters(ConvertersDate::class)
|
@TypeConverters(ConvertersDate::class)
|
||||||
@ -110,6 +110,7 @@ custom_domains = smsf.demo.com
|
|||||||
MIGRATION_16_17,
|
MIGRATION_16_17,
|
||||||
MIGRATION_17_18,
|
MIGRATION_17_18,
|
||||||
MIGRATION_18_19,
|
MIGRATION_18_19,
|
||||||
|
MIGRATION_19_20,
|
||||||
)
|
)
|
||||||
|
|
||||||
/*if (BuildConfig.DEBUG) {
|
/*if (BuildConfig.DEBUG) {
|
||||||
@ -452,6 +453,13 @@ CREATE TABLE "Task" (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//免打扰星期段
|
||||||
|
private val MIGRATION_19_20 = object : Migration(19, 20) {
|
||||||
|
override fun migrate(database: SupportSQLiteDatabase) {
|
||||||
|
database.execSQL("Alter table rule add column silent_day_of_week TEXT NOT NULL DEFAULT '' ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -27,9 +27,6 @@ interface MsgDao {
|
|||||||
@Query("DELETE FROM Msg where id=:id")
|
@Query("DELETE FROM Msg where id=:id")
|
||||||
fun delete(id: Long)
|
fun delete(id: Long)
|
||||||
|
|
||||||
@Query("DELETE FROM Msg where type=:type")
|
|
||||||
fun deleteAll(type: String): Completable
|
|
||||||
|
|
||||||
@RawQuery
|
@RawQuery
|
||||||
fun deleteAll(sql: SupportSQLiteQuery): Int
|
fun deleteAll(sql: SupportSQLiteQuery): Int
|
||||||
|
|
||||||
|
@ -54,15 +54,16 @@ data class Rule(
|
|||||||
//免打扰(禁用转发)时间段
|
//免打扰(禁用转发)时间段
|
||||||
@ColumnInfo(name = "silent_period_start", defaultValue = "0") var silentPeriodStart: Int = 0,
|
@ColumnInfo(name = "silent_period_start", defaultValue = "0") var silentPeriodStart: Int = 0,
|
||||||
@ColumnInfo(name = "silent_period_end", defaultValue = "0") var silentPeriodEnd: Int = 0,
|
@ColumnInfo(name = "silent_period_end", defaultValue = "0") var silentPeriodEnd: Int = 0,
|
||||||
|
@ColumnInfo(name = "silent_day_of_week", defaultValue = "") var silentDayOfWeek: String = "",
|
||||||
) : Parcelable {
|
) : Parcelable {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val TAG: String = Rule::class.java.simpleName
|
val TAG: String = Rule::class.java.simpleName
|
||||||
|
|
||||||
fun getRuleMatch(filed: String?, check: String?, value: String?, simSlot: String?, senderList: List<Sender>? = null): String {
|
fun getRuleMatch(type: String?, filed: String?, check: String?, value: String?, simSlot: String?, senderList: List<Sender>? = null): String {
|
||||||
val blank = if (App.isNeedSpaceBetweenWords) " " else ""
|
val blank = if (App.isNeedSpaceBetweenWords) " " else ""
|
||||||
val sb = StringBuilder()
|
val sb = StringBuilder()
|
||||||
sb.append(SIM_SLOT_MAP[simSlot]).append(blank).append(getString(R.string.rule_card)).append(blank)
|
if (type != "app") sb.append(SIM_SLOT_MAP[simSlot]).append(blank).append(getString(R.string.rule_card)).append(blank)
|
||||||
when (filed) {
|
when (filed) {
|
||||||
null, FILED_TRANSPOND_ALL -> sb.append(getString(R.string.rule_all_fw_to))
|
null, FILED_TRANSPOND_ALL -> sb.append(getString(R.string.rule_all_fw_to))
|
||||||
FILED_CALL_TYPE -> sb.append(getString(R.string.rule_when))
|
FILED_CALL_TYPE -> sb.append(getString(R.string.rule_when))
|
||||||
@ -127,9 +128,9 @@ data class Rule(
|
|||||||
|
|
||||||
fun getName(appendSenderList: Boolean = true): String {
|
fun getName(appendSenderList: Boolean = true): String {
|
||||||
return if (appendSenderList) {
|
return if (appendSenderList) {
|
||||||
getRuleMatch(filed, check, value, simSlot, senderList)
|
getRuleMatch(type, filed, check, value, simSlot, senderList)
|
||||||
} else {
|
} else {
|
||||||
getRuleMatch(filed, check, value, simSlot, null)
|
getRuleMatch(type, filed, check, value, simSlot, null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,47 +215,49 @@ data class Rule(
|
|||||||
|
|
||||||
//内容分支
|
//内容分支
|
||||||
private fun checkValue(msgValue: String?): Boolean {
|
private fun checkValue(msgValue: String?): Boolean {
|
||||||
var checked = false
|
if (msgValue == null) return false
|
||||||
when (this.check) {
|
|
||||||
CHECK_IS -> checked = this.value == msgValue
|
|
||||||
CHECK_NOT_IS -> checked = this.value != msgValue
|
|
||||||
CHECK_CONTAIN -> if (msgValue != null) {
|
|
||||||
checked = msgValue.contains(this.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
CHECK_NOT_CONTAIN -> if (msgValue != null) {
|
fun evaluateCondition(condition: String): Boolean {
|
||||||
checked = !msgValue.contains(this.value)
|
return when (check) {
|
||||||
}
|
CHECK_IS -> msgValue == condition
|
||||||
|
CHECK_NOT_IS -> msgValue != condition
|
||||||
CHECK_START_WITH -> if (msgValue != null) {
|
CHECK_CONTAIN -> msgValue.contains(condition)
|
||||||
checked = msgValue.startsWith(this.value)
|
CHECK_NOT_CONTAIN -> !msgValue.contains(condition)
|
||||||
}
|
CHECK_START_WITH -> msgValue.startsWith(condition)
|
||||||
|
CHECK_END_WITH -> msgValue.endsWith(condition)
|
||||||
CHECK_END_WITH -> if (msgValue != null) {
|
CHECK_REGEX -> try {
|
||||||
checked = msgValue.endsWith(this.value)
|
val pattern = Pattern.compile(condition, Pattern.CASE_INSENSITIVE)
|
||||||
}
|
|
||||||
|
|
||||||
CHECK_REGEX -> if (msgValue != null) {
|
|
||||||
try {
|
|
||||||
//checked = Pattern.matches(this.value, msgValue);
|
|
||||||
val pattern = Pattern.compile(this.value, Pattern.CASE_INSENSITIVE)
|
|
||||||
val matcher = pattern.matcher(msgValue)
|
val matcher = pattern.matcher(msgValue)
|
||||||
while (matcher.find()) {
|
matcher.find()
|
||||||
checked = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
} catch (e: PatternSyntaxException) {
|
} catch (e: PatternSyntaxException) {
|
||||||
Log.d(TAG, "PatternSyntaxException: ")
|
Log.i(TAG, "PatternSyntaxException: ${e.description}, Index: ${e.index}, Message: ${e.message}, Pattern: ${e.pattern}")
|
||||||
Log.d(TAG, "Description: " + e.description)
|
false
|
||||||
Log.d(TAG, "Index: " + e.index)
|
}
|
||||||
Log.d(TAG, "Message: " + e.message)
|
|
||||||
Log.d(TAG, "Pattern: " + e.pattern)
|
else -> false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {}
|
fun parseAndEvaluate(expression: String): Boolean {
|
||||||
|
// Split by "||" and evaluate each segment joined by "&&"
|
||||||
|
val orGroups = expression.split("||")
|
||||||
|
return orGroups.any { orGroup ->
|
||||||
|
val andGroups = orGroup.split("&&")
|
||||||
|
andGroups.all { andGroup ->
|
||||||
|
val trimmedCondition = andGroup.trim()
|
||||||
|
evaluateCondition(trimmedCondition)
|
||||||
}
|
}
|
||||||
Log.i(TAG, "checkValue " + msgValue + " " + this.check + " " + this.value + " checked:" + checked)
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val checked = if (value.contains("&&") || value.contains("||")) {
|
||||||
|
parseAndEvaluate(value)
|
||||||
|
} else {
|
||||||
|
evaluateCondition(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.i(TAG, "checkValue $msgValue $check $value checked:$checked")
|
||||||
return checked
|
return checked
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -14,8 +14,6 @@ class MsgRepository(private val msgDao: MsgDao) {
|
|||||||
|
|
||||||
fun deleteAll() = msgDao.deleteAll()
|
fun deleteAll() = msgDao.deleteAll()
|
||||||
|
|
||||||
fun deleteAll(type: String) = msgDao.deleteAll(type)
|
|
||||||
|
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
fun deleteTimeAgo(time: Long) = msgDao.deleteTimeAgo(time)
|
fun deleteTimeAgo(time: Long) = msgDao.deleteTimeAgo(time)
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ import androidx.sqlite.db.SimpleSQLiteQuery
|
|||||||
import com.idormy.sms.forwarder.database.dao.MsgDao
|
import com.idormy.sms.forwarder.database.dao.MsgDao
|
||||||
import com.idormy.sms.forwarder.database.entity.MsgAndLogs
|
import com.idormy.sms.forwarder.database.entity.MsgAndLogs
|
||||||
import com.idormy.sms.forwarder.database.ext.ioThread
|
import com.idormy.sms.forwarder.database.ext.ioThread
|
||||||
|
import com.idormy.sms.forwarder.utils.Log
|
||||||
import com.xuexiang.xutil.data.DateUtils
|
import com.xuexiang.xutil.data.DateUtils
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
@ -55,19 +56,17 @@ class MsgViewModel(private val dao: MsgDao) : ViewModel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun deleteAll() = ioThread {
|
fun deleteAll() = ioThread {
|
||||||
if (filter.isEmpty()) {
|
|
||||||
dao.deleteAll(type)
|
|
||||||
} else {
|
|
||||||
val sb = StringBuilder().apply {
|
val sb = StringBuilder().apply {
|
||||||
append("DELETE FROM Msg WHERE type = '$type'")
|
append("DELETE FROM Msg WHERE type = '$type'")
|
||||||
|
if (filter.isNotEmpty()) {
|
||||||
append(getOtherCondition())
|
append(getOtherCondition())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Log.d("MsgViewModel", "sql: $sb")
|
Log.d("MsgViewModel", "sql: $sb")
|
||||||
val query = SimpleSQLiteQuery(sb.toString())
|
val query = SimpleSQLiteQuery(sb.toString())
|
||||||
dao.deleteAll(query)
|
dao.deleteAll(query)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private fun getOtherCondition(): String {
|
private fun getOtherCondition(): String {
|
||||||
return StringBuilder().apply {
|
return StringBuilder().apply {
|
||||||
|
@ -10,6 +10,7 @@ import com.idormy.sms.forwarder.utils.AppUtils
|
|||||||
import com.idormy.sms.forwarder.utils.BatteryUtils
|
import com.idormy.sms.forwarder.utils.BatteryUtils
|
||||||
import com.idormy.sms.forwarder.utils.HttpServerUtils
|
import com.idormy.sms.forwarder.utils.HttpServerUtils
|
||||||
import com.idormy.sms.forwarder.utils.Log
|
import com.idormy.sms.forwarder.utils.Log
|
||||||
|
import com.idormy.sms.forwarder.utils.PhoneUtils
|
||||||
import com.idormy.sms.forwarder.utils.SettingUtils
|
import com.idormy.sms.forwarder.utils.SettingUtils
|
||||||
import com.idormy.sms.forwarder.utils.SettingUtils.Companion.enableSmsTemplate
|
import com.idormy.sms.forwarder.utils.SettingUtils.Companion.enableSmsTemplate
|
||||||
import com.idormy.sms.forwarder.utils.SettingUtils.Companion.extraDeviceMark
|
import com.idormy.sms.forwarder.utils.SettingUtils.Companion.extraDeviceMark
|
||||||
@ -18,6 +19,7 @@ import com.idormy.sms.forwarder.utils.task.TaskUtils
|
|||||||
import com.xuexiang.xutil.net.NetworkUtils
|
import com.xuexiang.xutil.net.NetworkUtils
|
||||||
import com.xuexiang.xutil.resource.ResUtils.getString
|
import com.xuexiang.xutil.resource.ResUtils.getString
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
|
import java.net.URLEncoder
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
|
|
||||||
@ -74,49 +76,49 @@ data class MsgInfo(
|
|||||||
fun getContentFromJson(jsonTemplate: String): String {
|
fun getContentFromJson(jsonTemplate: String): String {
|
||||||
var template = jsonTemplate.replace("null", "")
|
var template = jsonTemplate.replace("null", "")
|
||||||
if (TextUtils.isEmpty(template)) template = getString(R.string.tag_from)
|
if (TextUtils.isEmpty(template)) template = getString(R.string.tag_from)
|
||||||
return replaceTemplate(template, "", true)
|
return replaceTemplate(template, "", "Gson")
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("SimpleDateFormat")
|
@SuppressLint("SimpleDateFormat")
|
||||||
fun replaceTemplate(template: String, regexReplace: String = "", needJson: Boolean = false): String {
|
fun replaceTemplate(template: String, regexReplace: String = "", encoderName: String = ""): String {
|
||||||
return template.replaceTag(getString(R.string.tag_from), from, needJson)
|
return template.replaceTag(getString(R.string.tag_from), from, encoderName)
|
||||||
.replaceTag(getString(R.string.tag_package_name), from, needJson)
|
.replaceTag(getString(R.string.tag_package_name), from, encoderName)
|
||||||
.replaceTag(getString(R.string.tag_sms), content, needJson)
|
.replaceTag(getString(R.string.tag_sms), content, encoderName)
|
||||||
.replaceTag(getString(R.string.tag_msg), content, needJson)
|
.replaceTag(getString(R.string.tag_msg), content, encoderName)
|
||||||
.replaceTag(getString(R.string.tag_card_slot), simInfo, needJson)
|
.replaceTag(getString(R.string.tag_card_slot), simInfo, encoderName)
|
||||||
.replaceTag(getString(R.string.tag_card_subid), subId.toString(), needJson)
|
.replaceTag(getString(R.string.tag_card_subid), subId.toString(), encoderName)
|
||||||
.replaceTag(getString(R.string.tag_title), simInfo, needJson)
|
.replaceTag(getString(R.string.tag_title), simInfo, encoderName)
|
||||||
.replaceTag(getString(R.string.tag_uid), uid.toString(), needJson)
|
.replaceTag(getString(R.string.tag_uid), uid.toString(), encoderName)
|
||||||
.replaceTag(
|
.replaceTag(
|
||||||
getString(R.string.tag_receive_time),
|
getString(R.string.tag_receive_time),
|
||||||
SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date),
|
SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date),
|
||||||
needJson
|
encoderName
|
||||||
)
|
)
|
||||||
.replaceTag(
|
.replaceTag(
|
||||||
getString(R.string.tag_current_time),
|
getString(R.string.tag_current_time),
|
||||||
SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Date()),
|
SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Date()),
|
||||||
needJson
|
encoderName
|
||||||
)
|
)
|
||||||
.replaceTag(getString(R.string.tag_device_name), extraDeviceMark.trim(), needJson)
|
.replaceTag(getString(R.string.tag_device_name), extraDeviceMark.trim(), encoderName)
|
||||||
.replaceTag(getString(R.string.tag_app_version), AppUtils.getAppVersionName(), needJson)
|
.replaceTag(getString(R.string.tag_app_version), AppUtils.getAppVersionName(), encoderName)
|
||||||
.replaceTag(
|
.replaceTag(
|
||||||
getString(R.string.tag_call_type),
|
getString(R.string.tag_call_type),
|
||||||
CALL_TYPE_MAP[callType.toString()] ?: getString(R.string.unknown_call), needJson
|
CALL_TYPE_MAP[callType.toString()] ?: getString(R.string.unknown_call), encoderName
|
||||||
)
|
)
|
||||||
.replaceTag(getString(R.string.tag_ipv4), TaskUtils.ipv4, needJson)
|
.replaceTag(getString(R.string.tag_ipv4), TaskUtils.ipv4, encoderName)
|
||||||
.replaceTag(getString(R.string.tag_ipv6), TaskUtils.ipv6, needJson)
|
.replaceTag(getString(R.string.tag_ipv6), TaskUtils.ipv6, encoderName)
|
||||||
.replaceTag(getString(R.string.tag_ip_list), TaskUtils.ipList, needJson)
|
.replaceTag(getString(R.string.tag_ip_list), TaskUtils.ipList, encoderName)
|
||||||
.replaceTag(getString(R.string.tag_battery_pct), "%.0f%%".format(TaskUtils.batteryPct), needJson)
|
.replaceTag(getString(R.string.tag_battery_pct), "%.0f%%".format(TaskUtils.batteryPct), encoderName)
|
||||||
.replaceTag(getString(R.string.tag_battery_status), BatteryUtils.getStatus(TaskUtils.batteryStatus), needJson)
|
.replaceTag(getString(R.string.tag_battery_status), BatteryUtils.getStatus(TaskUtils.batteryStatus), encoderName)
|
||||||
.replaceTag(getString(R.string.tag_battery_plugged), BatteryUtils.getPlugged(TaskUtils.batteryPlugged), needJson)
|
.replaceTag(getString(R.string.tag_battery_plugged), BatteryUtils.getPlugged(TaskUtils.batteryPlugged), encoderName)
|
||||||
.replaceTag(getString(R.string.tag_battery_info), TaskUtils.batteryInfo, needJson)
|
.replaceTag(getString(R.string.tag_battery_info), TaskUtils.batteryInfo, encoderName)
|
||||||
.replaceTag(
|
.replaceTag(
|
||||||
getString(R.string.tag_battery_info_simple),
|
getString(R.string.tag_battery_info_simple),
|
||||||
"%.0f%%".format(TaskUtils.batteryPct)
|
"%.0f%%".format(TaskUtils.batteryPct)
|
||||||
+ with(BatteryUtils.getPlugged(TaskUtils.batteryPlugged)) {
|
+ with(BatteryUtils.getPlugged(TaskUtils.batteryPlugged)) {
|
||||||
if (this == getString(R.string.battery_unknown)) "" else " - $this"
|
if (this == getString(R.string.battery_unknown)) "" else " - $this"
|
||||||
},
|
},
|
||||||
needJson
|
encoderName
|
||||||
)
|
)
|
||||||
.replaceTag(
|
.replaceTag(
|
||||||
getString(R.string.tag_net_type), with(NetworkUtils.getNetStateType()) {
|
getString(R.string.tag_net_type), with(NetworkUtils.getNetStateType()) {
|
||||||
@ -124,10 +126,12 @@ data class MsgInfo(
|
|||||||
this.name
|
this.name
|
||||||
this.name.removePrefix("NET_")
|
this.name.removePrefix("NET_")
|
||||||
},
|
},
|
||||||
needJson
|
encoderName
|
||||||
)
|
)
|
||||||
.replaceAppNameTag(from, needJson)
|
.replaceAppNameTag(from, encoderName)
|
||||||
.replaceLocationTag(needJson)
|
.replaceLocationTag(encoderName)
|
||||||
|
.replaceContactNameTag(encoderName)
|
||||||
|
.replacePhoneAreaTag(encoderName)
|
||||||
.regexReplace(regexReplace)
|
.regexReplace(regexReplace)
|
||||||
.trim()
|
.trim()
|
||||||
}
|
}
|
||||||
@ -155,11 +159,11 @@ data class MsgInfo(
|
|||||||
}
|
}
|
||||||
|
|
||||||
//替换标签(支持正则替换)
|
//替换标签(支持正则替换)
|
||||||
private fun String.replaceTag(tag: String, info: String, needJson: Boolean = false, ignoreCase: Boolean = true): String {
|
private fun String.replaceTag(tag: String, info: String, encoderName: String = "", ignoreCase: Boolean = true): String {
|
||||||
var result = if (needJson) {
|
var result = when (encoderName) {
|
||||||
this.replace(tag, toJsonStr(info), ignoreCase)
|
"Gson" -> this.replace(tag, toJsonStr(info), ignoreCase)
|
||||||
} else {
|
"URLEncoder" -> this.replace(tag, URLEncoder.encode(info, "UTF-8"), ignoreCase)
|
||||||
this.replace(tag, info, ignoreCase)
|
else -> this.replace(tag, info, ignoreCase)
|
||||||
}
|
}
|
||||||
|
|
||||||
val tagName = tag.removePrefix("{{").removeSuffix("}}")
|
val tagName = tag.removePrefix("{{").removeSuffix("}}")
|
||||||
@ -171,10 +175,10 @@ data class MsgInfo(
|
|||||||
val replacement = it.groupValues[2]
|
val replacement = it.groupValues[2]
|
||||||
val temp = info.replace(regex.toRegex(), replacement)
|
val temp = info.replace(regex.toRegex(), replacement)
|
||||||
Log.d("MsgInfo", "tagRegex: regex=$regex, replacement=$replacement, temp=$temp")
|
Log.d("MsgInfo", "tagRegex: regex=$regex, replacement=$replacement, temp=$temp")
|
||||||
result = if (needJson) {
|
result = when (encoderName) {
|
||||||
result.replace(it.value, toJsonStr(temp))
|
"Gson" -> this.replace(it.value, toJsonStr(temp), ignoreCase)
|
||||||
} else {
|
"URLEncoder" -> this.replace(it.value, URLEncoder.encode(temp, "UTF-8"), ignoreCase)
|
||||||
result.replace(it.value, temp)
|
else -> this.replace(it.value, temp, ignoreCase)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e("MsgInfo", "Failed to replace tagRegex: ${e.message}")
|
Log.e("MsgInfo", "Failed to replace tagRegex: ${e.message}")
|
||||||
@ -184,8 +188,35 @@ data class MsgInfo(
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//替换{{CONTACT_NAME}}标签
|
||||||
|
private fun String.replaceContactNameTag(encoderName: String = ""): String {
|
||||||
|
if (TextUtils.isEmpty(this)) return this
|
||||||
|
if (this.indexOf(getString(R.string.tag_contact_name)) == -1) return this
|
||||||
|
|
||||||
|
val contacts = PhoneUtils.getContactByNumber(from)
|
||||||
|
var contactName = if (contacts.isNotEmpty()) contacts[0].name else getString(R.string.unknown_number)
|
||||||
|
when (encoderName) {
|
||||||
|
"Gson" -> contactName = toJsonStr(contactName)
|
||||||
|
"URLEncoder" -> contactName = URLEncoder.encode(contactName, "UTF-8")
|
||||||
|
}
|
||||||
|
return this.replaceTag(getString(R.string.tag_contact_name), contactName)
|
||||||
|
}
|
||||||
|
|
||||||
|
//替换{{PHONE_AREA}}标签
|
||||||
|
private fun String.replacePhoneAreaTag(encoderName: String = ""): String {
|
||||||
|
if (TextUtils.isEmpty(this)) return this
|
||||||
|
if (this.indexOf(getString(R.string.tag_phone_area)) == -1) return this
|
||||||
|
|
||||||
|
var phoneArea = PhoneUtils.getPhoneArea(from)
|
||||||
|
when (encoderName) {
|
||||||
|
"Gson" -> phoneArea = toJsonStr(phoneArea)
|
||||||
|
"URLEncoder" -> phoneArea = URLEncoder.encode(phoneArea, "UTF-8")
|
||||||
|
}
|
||||||
|
return this.replaceTag(getString(R.string.tag_phone_area), phoneArea)
|
||||||
|
}
|
||||||
|
|
||||||
//替换{{APP名称}}标签
|
//替换{{APP名称}}标签
|
||||||
private fun String.replaceAppNameTag(packageName: String, needJson: Boolean = false): String {
|
private fun String.replaceAppNameTag(packageName: String, encoderName: String = ""): String {
|
||||||
if (TextUtils.isEmpty(this)) return this
|
if (TextUtils.isEmpty(this)) return this
|
||||||
if (this.indexOf(getString(R.string.tag_app_name)) == -1) return this
|
if (this.indexOf(getString(R.string.tag_app_name)) == -1) return this
|
||||||
|
|
||||||
@ -206,23 +237,33 @@ data class MsgInfo(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (needJson) {
|
|
||||||
appName = toJsonStr(appName)
|
when (encoderName) {
|
||||||
|
"Gson" -> appName = toJsonStr(appName)
|
||||||
|
"URLEncoder" -> appName = URLEncoder.encode(appName, "UTF-8")
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.replaceTag(getString(R.string.tag_app_name), appName)
|
return this.replaceTag(getString(R.string.tag_app_name), appName)
|
||||||
}
|
}
|
||||||
|
|
||||||
//替换 {{定位信息}} 标签
|
//替换 {{定位信息}} 标签
|
||||||
private fun String.replaceLocationTag(needJson: Boolean = false): String {
|
private fun String.replaceLocationTag(encoderName: String = ""): String {
|
||||||
if (TextUtils.isEmpty(this)) return this
|
if (TextUtils.isEmpty(this)) return this
|
||||||
|
|
||||||
val location = HttpServerUtils.apiLocationCache
|
val location = HttpServerUtils.apiLocationCache
|
||||||
var locationStr = location.toString()
|
var locationStr = location.toString()
|
||||||
var address = location.address
|
var address = location.address
|
||||||
if (needJson) {
|
when (encoderName) {
|
||||||
|
"Gson" -> {
|
||||||
locationStr = toJsonStr(locationStr)
|
locationStr = toJsonStr(locationStr)
|
||||||
address = toJsonStr(address)
|
address = toJsonStr(address)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"URLEncoder" -> {
|
||||||
|
locationStr = URLEncoder.encode(locationStr, "UTF-8")
|
||||||
|
address = URLEncoder.encode(address, "UTF-8")
|
||||||
|
}
|
||||||
|
}
|
||||||
return this.replaceTag(getString(R.string.tag_location), locationStr)
|
return this.replaceTag(getString(R.string.tag_location), locationStr)
|
||||||
.replaceTag(getString(R.string.tag_location_longitude), location.longitude.toString())
|
.replaceTag(getString(R.string.tag_location_longitude), location.longitude.toString())
|
||||||
.replaceTag(getString(R.string.tag_location_latitude), location.latitude.toString())
|
.replaceTag(getString(R.string.tag_location_latitude), location.latitude.toString())
|
||||||
|
@ -5,7 +5,11 @@ import java.io.Serializable
|
|||||||
data class AlarmSetting(
|
data class AlarmSetting(
|
||||||
var description: String = "", //描述
|
var description: String = "", //描述
|
||||||
var action: String = "stop", //动作: start=启动警报, stop=停止警报
|
var action: String = "stop", //动作: start=启动警报, stop=停止警报
|
||||||
var volume: Int = 80, //播放音量
|
var volume: Int = 80, //播放音量,0-100
|
||||||
var playTimes: Int = 1, //播放次数,0=无限循环
|
var playTimes: Int = 1, //播放次数,0=无限循环,-1=禁用
|
||||||
var music: String = "", //音乐文件
|
var music: String = "", //音乐文件
|
||||||
|
var repeatTimes: Int = 5, //振动重复次数,0=无限循环,-1=禁用
|
||||||
|
var vibrate: String = "---___===___", //振动律动:=强振动, -弱震动, _不振动, 时长都是100ms
|
||||||
|
var flashTimes: Int = 5, //闪烁次数,0=无限循环,-1=禁用
|
||||||
|
var flash: String = "XXOOXXOO", //闪烁律动:X亮灯, O灭灯, 时长都是100ms
|
||||||
) : Serializable
|
) : Serializable
|
||||||
|
@ -25,4 +25,8 @@ data class BarkSetting(
|
|||||||
val key: String = "",
|
val key: String = "",
|
||||||
//初始偏移向量
|
//初始偏移向量
|
||||||
val iv: String = "",
|
val iv: String = "",
|
||||||
|
//持续提醒
|
||||||
|
val call: String = "",
|
||||||
|
//自动复制模板
|
||||||
|
val autoCopy: String = "",
|
||||||
) : Serializable
|
) : Serializable
|
@ -14,6 +14,7 @@ data class TelegramSetting(
|
|||||||
val proxyAuthenticator: Boolean = false,
|
val proxyAuthenticator: Boolean = false,
|
||||||
val proxyUsername: String = "",
|
val proxyUsername: String = "",
|
||||||
val proxyPassword: String = "",
|
val proxyPassword: String = "",
|
||||||
|
val parseMode: String = "HTML",
|
||||||
) : Serializable {
|
) : Serializable {
|
||||||
|
|
||||||
fun getMethodCheckId(): Int {
|
fun getMethodCheckId(): Int {
|
||||||
@ -27,4 +28,12 @@ data class TelegramSetting(
|
|||||||
else -> R.id.rb_proxyNone
|
else -> R.id.rb_proxyNone
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getParseModeCheckId(): Int {
|
||||||
|
return when (parseMode) {
|
||||||
|
"TEXT" -> R.id.rb_parse_mode_text
|
||||||
|
"MarkdownV2" -> R.id.rb_parse_mode_markdown
|
||||||
|
else -> R.id.rb_parse_mode_html
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -9,6 +9,9 @@ import androidx.appcompat.app.AppCompatActivity
|
|||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
import androidx.work.OneTimeWorkRequestBuilder
|
import androidx.work.OneTimeWorkRequestBuilder
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
|
import com.hjq.permissions.OnPermissionCallback
|
||||||
|
import com.hjq.permissions.Permission
|
||||||
|
import com.hjq.permissions.XXPermissions
|
||||||
import com.idormy.sms.forwarder.App
|
import com.idormy.sms.forwarder.App
|
||||||
import com.idormy.sms.forwarder.R
|
import com.idormy.sms.forwarder.R
|
||||||
import com.idormy.sms.forwarder.adapter.AppListAdapter
|
import com.idormy.sms.forwarder.adapter.AppListAdapter
|
||||||
@ -24,11 +27,11 @@ import com.scwang.smartrefresh.layout.api.RefreshLayout
|
|||||||
import com.scwang.smartrefresh.layout.listener.OnRefreshLoadMoreListener
|
import com.scwang.smartrefresh.layout.listener.OnRefreshLoadMoreListener
|
||||||
import com.xuexiang.xaop.annotation.SingleClick
|
import com.xuexiang.xaop.annotation.SingleClick
|
||||||
import com.xuexiang.xpage.annotation.Page
|
import com.xuexiang.xpage.annotation.Page
|
||||||
|
import com.xuexiang.xui.XUI
|
||||||
import com.xuexiang.xui.utils.DensityUtils
|
import com.xuexiang.xui.utils.DensityUtils
|
||||||
import com.xuexiang.xui.utils.ThemeUtils
|
import com.xuexiang.xui.utils.ThemeUtils
|
||||||
import com.xuexiang.xui.utils.WidgetUtils
|
import com.xuexiang.xui.utils.WidgetUtils
|
||||||
import com.xuexiang.xui.widget.actionbar.TitleBar
|
import com.xuexiang.xui.widget.actionbar.TitleBar
|
||||||
import com.xuexiang.xutil.XUtil
|
|
||||||
import com.xuexiang.xutil.resource.ResUtils.getStringArray
|
import com.xuexiang.xutil.resource.ResUtils.getStringArray
|
||||||
|
|
||||||
@Suppress("PrivatePropertyName", "DEPRECATION")
|
@Suppress("PrivatePropertyName", "DEPRECATION")
|
||||||
@ -91,10 +94,10 @@ class AppListFragment : BaseFragment<FragmentAppListBinding?>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onRefresh(refreshLayout: RefreshLayout) {
|
override fun onRefresh(refreshLayout: RefreshLayout) {
|
||||||
refreshLayout.layout.postDelayed({
|
|
||||||
appListAdapter?.refresh(getAppsList(true))
|
appListAdapter?.refresh(getAppsList(true))
|
||||||
|
refreshLayout.layout.postDelayed({
|
||||||
refreshLayout.finishRefresh()
|
refreshLayout.finishRefresh()
|
||||||
}, 3000)
|
}, 1000)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
appListAdapter?.setOnItemClickListener { _, item, _ ->
|
appListAdapter?.setOnItemClickListener { _, item, _ ->
|
||||||
@ -120,9 +123,21 @@ class AppListFragment : BaseFragment<FragmentAppListBinding?>() {
|
|||||||
|
|
||||||
private fun getAppsList(refresh: Boolean): MutableList<AppInfo> {
|
private fun getAppsList(refresh: Boolean): MutableList<AppInfo> {
|
||||||
if (refresh || (currentType == "user" && App.UserAppList.isEmpty()) || (currentType == "system" && App.SystemAppList.isEmpty())) {
|
if (refresh || (currentType == "user" && App.UserAppList.isEmpty()) || (currentType == "system" && App.SystemAppList.isEmpty())) {
|
||||||
|
//检查读取应用列表权限是否获取
|
||||||
|
XXPermissions.with(this).permission(Permission.GET_INSTALLED_APPS).request(object : OnPermissionCallback {
|
||||||
|
override fun onGranted(permissions: MutableList<String>, allGranted: Boolean) {
|
||||||
XToastUtils.info(getString(R.string.loading_app_list))
|
XToastUtils.info(getString(R.string.loading_app_list))
|
||||||
val request = OneTimeWorkRequestBuilder<LoadAppListWorker>().build()
|
val request = OneTimeWorkRequestBuilder<LoadAppListWorker>().build()
|
||||||
WorkManager.getInstance(XUtil.getContext()).enqueue(request)
|
WorkManager.getInstance(XUI.getContext()).enqueue(request)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDenied(permissions: MutableList<String>, doNotAskAgain: Boolean) {
|
||||||
|
XToastUtils.error(R.string.tips_get_installed_apps)
|
||||||
|
if (doNotAskAgain) {
|
||||||
|
XXPermissions.startPermissionActivity(XUI.getContext(), permissions)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return if (currentType == "system") App.SystemAppList else App.UserAppList
|
return if (currentType == "system") App.SystemAppList else App.UserAppList
|
||||||
|
@ -85,6 +85,7 @@ class LogsFragment : BaseFragment<FragmentLogsBinding?>(), MsgPagingAdapter.OnIt
|
|||||||
.negativeText(R.string.lab_no)
|
.negativeText(R.string.lab_no)
|
||||||
.onPositive { _: MaterialDialog?, _: DialogAction? ->
|
.onPositive { _: MaterialDialog?, _: DialogAction? ->
|
||||||
try {
|
try {
|
||||||
|
Log.d(TAG, "deleteAll, currentType:$currentType, currentFilter:$currentFilter")
|
||||||
viewModel.setType(currentType).setFilter(currentFilter).deleteAll()
|
viewModel.setType(currentType).setFilter(currentFilter).deleteAll()
|
||||||
reloadData()
|
reloadData()
|
||||||
XToastUtils.success(if (currentFilter.isEmpty()) R.string.delete_type_log_toast else R.string.delete_filter_log_toast)
|
XToastUtils.success(if (currentFilter.isEmpty()) R.string.delete_type_log_toast else R.string.delete_filter_log_toast)
|
||||||
@ -187,7 +188,7 @@ class LogsFragment : BaseFragment<FragmentLogsBinding?>(), MsgPagingAdapter.OnIt
|
|||||||
override fun onLogsClicked(view: View?, item: LogsDetail) {
|
override fun onLogsClicked(view: View?, item: LogsDetail) {
|
||||||
Log.d(TAG, "item: $item")
|
Log.d(TAG, "item: $item")
|
||||||
val ruleStr = StringBuilder()
|
val ruleStr = StringBuilder()
|
||||||
ruleStr.append(Rule.getRuleMatch(item.ruleFiled, item.ruleCheck, item.ruleValue, item.ruleSimSlot)).append(item.senderName)
|
ruleStr.append(Rule.getRuleMatch(item.type, item.ruleFiled, item.ruleCheck, item.ruleValue, item.ruleSimSlot)).append(item.senderName)
|
||||||
val detailStr = StringBuilder()
|
val detailStr = StringBuilder()
|
||||||
detailStr.append(getString(R.string.rule)).append(ruleStr.toString()).append("\n\n")
|
detailStr.append(getString(R.string.rule)).append(ruleStr.toString()).append("\n\n")
|
||||||
@SuppressLint("SimpleDateFormat") val utcFormatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
|
@SuppressLint("SimpleDateFormat") val utcFormatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
|
||||||
|
@ -87,6 +87,7 @@ import io.reactivex.SingleObserver
|
|||||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.disposables.Disposable
|
import io.reactivex.disposables.Disposable
|
||||||
import io.reactivex.schedulers.Schedulers
|
import io.reactivex.schedulers.Schedulers
|
||||||
|
import java.util.Calendar
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
|
|
||||||
@Page(name = "转发规则·编辑器")
|
@Page(name = "转发规则·编辑器")
|
||||||
@ -165,9 +166,6 @@ class RulesEditFragment : BaseFragment<FragmentRulesEditBinding?>(), View.OnClic
|
|||||||
binding!!.rbCallType.visibility = View.GONE
|
binding!!.rbCallType.visibility = View.GONE
|
||||||
binding!!.rbContent.visibility = View.GONE
|
binding!!.rbContent.visibility = View.GONE
|
||||||
binding!!.tvMuRuleTips.setText(R.string.mu_rule_app_tips)
|
binding!!.tvMuRuleTips.setText(R.string.mu_rule_app_tips)
|
||||||
binding!!.btInsertExtra.visibility = View.GONE
|
|
||||||
binding!!.btInsertSender.visibility = View.GONE
|
|
||||||
binding!!.btInsertContent.visibility = View.GONE
|
|
||||||
//初始化APP下拉列表
|
//初始化APP下拉列表
|
||||||
initAppSpinner()
|
initAppSpinner()
|
||||||
//监听已安装App信息列表加载完成事件
|
//监听已安装App信息列表加载完成事件
|
||||||
@ -182,11 +180,6 @@ class RulesEditFragment : BaseFragment<FragmentRulesEditBinding?>(), View.OnClic
|
|||||||
binding!!.rbInformContent.visibility = View.GONE
|
binding!!.rbInformContent.visibility = View.GONE
|
||||||
//binding!!.rbMultiMatch.visibility = View.GONE
|
//binding!!.rbMultiMatch.visibility = View.GONE
|
||||||
binding!!.tvMuRuleTips.setText(R.string.mu_rule_call_tips)
|
binding!!.tvMuRuleTips.setText(R.string.mu_rule_call_tips)
|
||||||
binding!!.btInsertContent.visibility = View.GONE
|
|
||||||
binding!!.btInsertSenderApp.visibility = View.GONE
|
|
||||||
binding!!.btInsertUid.visibility = View.GONE
|
|
||||||
binding!!.btInsertTitleApp.visibility = View.GONE
|
|
||||||
binding!!.btInsertContentApp.visibility = View.GONE
|
|
||||||
|
|
||||||
//通话类型:1.来电挂机 2.去电挂机 3.未接来电 4.来电提醒 5.来电接通 6.去电拨出
|
//通话类型:1.来电挂机 2.去电挂机 3.未接来电 4.来电提醒 5.来电接通 6.去电拨出
|
||||||
binding!!.spCallType.setItems(CALL_TYPE_MAP.values.toList())
|
binding!!.spCallType.setItems(CALL_TYPE_MAP.values.toList())
|
||||||
@ -209,13 +202,12 @@ class RulesEditFragment : BaseFragment<FragmentRulesEditBinding?>(), View.OnClic
|
|||||||
binding!!.rbPackageName.visibility = View.GONE
|
binding!!.rbPackageName.visibility = View.GONE
|
||||||
binding!!.rbUid.visibility = View.GONE
|
binding!!.rbUid.visibility = View.GONE
|
||||||
binding!!.rbInformContent.visibility = View.GONE
|
binding!!.rbInformContent.visibility = View.GONE
|
||||||
binding!!.btInsertSenderApp.visibility = View.GONE
|
|
||||||
binding!!.btInsertUid.visibility = View.GONE
|
|
||||||
binding!!.btInsertTitleApp.visibility = View.GONE
|
|
||||||
binding!!.btInsertContentApp.visibility = View.GONE
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//创建标签按钮
|
||||||
|
CommonUtils.createTagButtons(requireContext(), binding!!.glSmsTemplate, binding!!.etSmsTemplate, ruleType)
|
||||||
|
|
||||||
if (ruleId <= 0) { //新增
|
if (ruleId <= 0) { //新增
|
||||||
titleBar?.setSubTitle(getString(R.string.add_rule))
|
titleBar?.setSubTitle(getString(R.string.add_rule))
|
||||||
binding!!.btnDel.setText(R.string.discard)
|
binding!!.btnDel.setText(R.string.discard)
|
||||||
@ -229,15 +221,6 @@ class RulesEditFragment : BaseFragment<FragmentRulesEditBinding?>(), View.OnClic
|
|||||||
|
|
||||||
override fun initListeners() {
|
override fun initListeners() {
|
||||||
binding!!.btnSilentPeriod.setOnClickListener(this)
|
binding!!.btnSilentPeriod.setOnClickListener(this)
|
||||||
binding!!.btInsertSender.setOnClickListener(this)
|
|
||||||
binding!!.btInsertContent.setOnClickListener(this)
|
|
||||||
binding!!.btInsertSenderApp.setOnClickListener(this)
|
|
||||||
binding!!.btInsertUid.setOnClickListener(this)
|
|
||||||
binding!!.btInsertTitleApp.setOnClickListener(this)
|
|
||||||
binding!!.btInsertContentApp.setOnClickListener(this)
|
|
||||||
binding!!.btInsertExtra.setOnClickListener(this)
|
|
||||||
binding!!.btInsertTime.setOnClickListener(this)
|
|
||||||
binding!!.btInsertDeviceName.setOnClickListener(this)
|
|
||||||
binding!!.btnTest.setOnClickListener(this)
|
binding!!.btnTest.setOnClickListener(this)
|
||||||
binding!!.btnDel.setOnClickListener(this)
|
binding!!.btnDel.setOnClickListener(this)
|
||||||
binding!!.btnSave.setOnClickListener(this)
|
binding!!.btnSave.setOnClickListener(this)
|
||||||
@ -333,7 +316,6 @@ class RulesEditFragment : BaseFragment<FragmentRulesEditBinding?>(), View.OnClic
|
|||||||
@SingleClick
|
@SingleClick
|
||||||
override fun onClick(v: View) {
|
override fun onClick(v: View) {
|
||||||
try {
|
try {
|
||||||
val etSmsTemplate: EditText = binding!!.etSmsTemplate
|
|
||||||
when (v.id) {
|
when (v.id) {
|
||||||
R.id.btn_silent_period -> {
|
R.id.btn_silent_period -> {
|
||||||
OptionsPickerBuilder(context, OnOptionsSelectListener { _: View?, options1: Int, options2: Int, _: Int ->
|
OptionsPickerBuilder(context, OnOptionsSelectListener { _: View?, options1: Int, options2: Int, _: Int ->
|
||||||
@ -349,51 +331,6 @@ class RulesEditFragment : BaseFragment<FragmentRulesEditBinding?>(), View.OnClic
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.bt_insert_sender -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etSmsTemplate, getString(R.string.tag_from))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_content -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etSmsTemplate, getString(R.string.tag_sms))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_sender_app -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etSmsTemplate, getString(R.string.tag_package_name))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_uid -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etSmsTemplate, getString(R.string.tag_uid))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_title_app -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etSmsTemplate, getString(R.string.tag_title))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_content_app -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etSmsTemplate, getString(R.string.tag_msg))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_extra -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etSmsTemplate, getString(R.string.tag_card_slot))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_time -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etSmsTemplate, getString(R.string.tag_receive_time))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_device_name -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etSmsTemplate, getString(R.string.tag_device_name))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.btn_test -> {
|
R.id.btn_test -> {
|
||||||
val ruleNew = checkForm()
|
val ruleNew = checkForm()
|
||||||
testRule(ruleNew)
|
testRule(ruleNew)
|
||||||
@ -639,6 +576,21 @@ class RulesEditFragment : BaseFragment<FragmentRulesEditBinding?>(), View.OnClic
|
|||||||
silentPeriodEnd = rule.silentPeriodEnd
|
silentPeriodEnd = rule.silentPeriodEnd
|
||||||
//初始化发送通道下拉框
|
//初始化发送通道下拉框
|
||||||
initSenderSpinner()
|
initSenderSpinner()
|
||||||
|
|
||||||
|
//绑定免打扰日期
|
||||||
|
val silentPeriodDays = rule.silentDayOfWeek.split(",").filter { it.isNotEmpty() }.map { it.toInt() }
|
||||||
|
if (silentPeriodDays.isNotEmpty()) {
|
||||||
|
val map = mapOf(
|
||||||
|
Calendar.SUNDAY to binding!!.sun,
|
||||||
|
Calendar.MONDAY to binding!!.mon,
|
||||||
|
Calendar.TUESDAY to binding!!.tue,
|
||||||
|
Calendar.WEDNESDAY to binding!!.wed,
|
||||||
|
Calendar.THURSDAY to binding!!.thu,
|
||||||
|
Calendar.FRIDAY to binding!!.fri,
|
||||||
|
Calendar.SATURDAY to binding!!.sat,
|
||||||
|
)
|
||||||
|
silentPeriodDays.forEach { map[it]?.isChecked = true }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -715,6 +667,19 @@ class RulesEditFragment : BaseFragment<FragmentRulesEditBinding?>(), View.OnClic
|
|||||||
}
|
}
|
||||||
val status = if (binding!!.sbStatus.isChecked) STATUS_ON else STATUS_OFF
|
val status = if (binding!!.sbStatus.isChecked) STATUS_ON else STATUS_OFF
|
||||||
|
|
||||||
|
val map = mapOf(
|
||||||
|
Calendar.SUNDAY to binding!!.sun,
|
||||||
|
Calendar.MONDAY to binding!!.mon,
|
||||||
|
Calendar.TUESDAY to binding!!.tue,
|
||||||
|
Calendar.WEDNESDAY to binding!!.wed,
|
||||||
|
Calendar.THURSDAY to binding!!.thu,
|
||||||
|
Calendar.FRIDAY to binding!!.fri,
|
||||||
|
Calendar.SATURDAY to binding!!.sat,
|
||||||
|
)
|
||||||
|
|
||||||
|
val silentDayOfWeek = map.filter { it.value.isChecked }
|
||||||
|
.toList().map { it.first }.joinToString(",")
|
||||||
|
|
||||||
return Rule(
|
return Rule(
|
||||||
ruleId,
|
ruleId,
|
||||||
ruleType,
|
ruleType,
|
||||||
@ -730,7 +695,8 @@ class RulesEditFragment : BaseFragment<FragmentRulesEditBinding?>(), View.OnClic
|
|||||||
senderListSelected,
|
senderListSelected,
|
||||||
senderLogic,
|
senderLogic,
|
||||||
silentPeriodStart,
|
silentPeriodStart,
|
||||||
silentPeriodEnd
|
silentPeriodEnd,
|
||||||
|
silentDayOfWeek,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -852,7 +818,7 @@ class RulesEditFragment : BaseFragment<FragmentRulesEditBinding?>(), View.OnClic
|
|||||||
val contactName = if (contacts.isNotEmpty()) contacts[0].name else getString(R.string.unknown_number)
|
val contactName = if (contacts.isNotEmpty()) contacts[0].name else getString(R.string.unknown_number)
|
||||||
msg.append(getString(R.string.contact)).append(contactName).append("\n")
|
msg.append(getString(R.string.contact)).append(contactName).append("\n")
|
||||||
msg.append(getString(R.string.mandatory_type))
|
msg.append(getString(R.string.mandatory_type))
|
||||||
msg.append(CALL_TYPE_MAP[callType.toString()] ?: getString(R.string.unknown_call))
|
msg.append(CALL_TYPE_MAP[callTypeTest.toString()] ?: getString(R.string.unknown_call))
|
||||||
} else {
|
} else {
|
||||||
msg.append(etContent.text.toString())
|
msg.append(etContent.text.toString())
|
||||||
}
|
}
|
||||||
|
@ -180,12 +180,18 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
|
|||||||
editAddExtraDeviceMark(binding!!.etExtraDeviceMark)
|
editAddExtraDeviceMark(binding!!.etExtraDeviceMark)
|
||||||
//SIM1主键
|
//SIM1主键
|
||||||
editAddSubidSim1(binding!!.etSubidSim1)
|
editAddSubidSim1(binding!!.etSubidSim1)
|
||||||
//SIM2主键
|
|
||||||
editAddSubidSim2(binding!!.etSubidSim2)
|
|
||||||
//SIM1备注
|
//SIM1备注
|
||||||
editAddExtraSim1(binding!!.etExtraSim1)
|
editAddExtraSim1(binding!!.etExtraSim1)
|
||||||
|
|
||||||
|
// sim 槽只有一个的时候不显示 SIM2 设置
|
||||||
|
if (PhoneUtils.getSimSlotCount() != 1) {
|
||||||
|
//SIM2主键
|
||||||
|
editAddSubidSim2(binding!!.etSubidSim2)
|
||||||
//SIM2备注
|
//SIM2备注
|
||||||
editAddExtraSim2(binding!!.etExtraSim2)
|
editAddExtraSim2(binding!!.etExtraSim2)
|
||||||
|
} else {
|
||||||
|
binding!!.layoutSim2.visibility = View.GONE
|
||||||
|
}
|
||||||
//通知内容
|
//通知内容
|
||||||
editNotifyContent(binding!!.etNotifyContent)
|
editNotifyContent(binding!!.etNotifyContent)
|
||||||
//启用自定义模版
|
//启用自定义模版
|
||||||
@ -215,11 +221,6 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
|
|||||||
binding!!.btnExtraDeviceMark.setOnClickListener(this)
|
binding!!.btnExtraDeviceMark.setOnClickListener(this)
|
||||||
binding!!.btnExtraSim1.setOnClickListener(this)
|
binding!!.btnExtraSim1.setOnClickListener(this)
|
||||||
binding!!.btnExtraSim2.setOnClickListener(this)
|
binding!!.btnExtraSim2.setOnClickListener(this)
|
||||||
binding!!.btInsertSender.setOnClickListener(this)
|
|
||||||
binding!!.btInsertContent.setOnClickListener(this)
|
|
||||||
binding!!.btInsertExtra.setOnClickListener(this)
|
|
||||||
binding!!.btInsertTime.setOnClickListener(this)
|
|
||||||
binding!!.btInsertDeviceName.setOnClickListener(this)
|
|
||||||
binding!!.btnExportLog.setOnClickListener(this)
|
binding!!.btnExportLog.setOnClickListener(this)
|
||||||
|
|
||||||
//监听已安装App信息列表加载完成事件
|
//监听已安装App信息列表加载完成事件
|
||||||
@ -229,7 +230,6 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
|
|||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
@SingleClick
|
@SingleClick
|
||||||
override fun onClick(v: View) {
|
override fun onClick(v: View) {
|
||||||
val etSmsTemplate: EditText = binding!!.etSmsTemplate
|
|
||||||
when (v.id) {
|
when (v.id) {
|
||||||
R.id.btn_silent_period -> {
|
R.id.btn_silent_period -> {
|
||||||
OptionsPickerBuilder(context, OnOptionsSelectListener { _: View?, options1: Int, options2: Int, _: Int ->
|
OptionsPickerBuilder(context, OnOptionsSelectListener { _: View?, options1: Int, options2: Int, _: Int ->
|
||||||
@ -298,37 +298,6 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.bt_insert_sender -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etSmsTemplate, getString(R.string.tag_from))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_content -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etSmsTemplate, getString(R.string.tag_sms))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_extra -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(
|
|
||||||
etSmsTemplate, getString(R.string.tag_card_slot)
|
|
||||||
)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_time -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(
|
|
||||||
etSmsTemplate, getString(R.string.tag_receive_time)
|
|
||||||
)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_device_name -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(
|
|
||||||
etSmsTemplate, getString(R.string.tag_device_name)
|
|
||||||
)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.btn_export_log -> {
|
R.id.btn_export_log -> {
|
||||||
XXPermissions.with(this)
|
XXPermissions.with(this)
|
||||||
// 申请储存权限
|
// 申请储存权限
|
||||||
@ -614,9 +583,9 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
|
|||||||
if (!initViewsFinished) return
|
if (!initViewsFinished) return
|
||||||
Log.d(TAG, "restartBluetoothService, action: $action")
|
Log.d(TAG, "restartBluetoothService, action: $action")
|
||||||
val serviceIntent = Intent(requireContext(), BluetoothScanService::class.java)
|
val serviceIntent = Intent(requireContext(), BluetoothScanService::class.java)
|
||||||
//如果定位功能已启用,但是系统定位功能不可用,则关闭定位功能
|
//如果蓝牙功能已启用,但是系统蓝牙功能不可用,则关闭蓝牙功能
|
||||||
if (SettingUtils.enableBluetooth && (!BluetoothUtils.isBluetoothEnabled() || !BluetoothUtils.hasBluetoothCapability(App.context))) {
|
if (SettingUtils.enableBluetooth && (!BluetoothUtils.isBluetoothEnabled() || !BluetoothUtils.hasBluetoothCapability(App.context))) {
|
||||||
XToastUtils.error(getString(R.string.toast_location_not_enabled))
|
XToastUtils.error(getString(R.string.toast_bluetooth_not_enabled))
|
||||||
SettingUtils.enableBluetooth = false
|
SettingUtils.enableBluetooth = false
|
||||||
binding!!.sbEnableBluetooth.isChecked = false
|
binding!!.sbEnableBluetooth.isChecked = false
|
||||||
binding!!.layoutBluetoothSetting.visibility = View.GONE
|
binding!!.layoutBluetoothSetting.visibility = View.GONE
|
||||||
@ -991,7 +960,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
|
|||||||
|
|
||||||
//设置SIM1主键
|
//设置SIM1主键
|
||||||
private fun editAddSubidSim1(etSubidSim1: EditText) {
|
private fun editAddSubidSim1(etSubidSim1: EditText) {
|
||||||
etSubidSim1.setText(SettingUtils.subidSim1.toString())
|
etSubidSim1.setText("${SettingUtils.subidSim1}")
|
||||||
etSubidSim1.addTextChangedListener(object : TextWatcher {
|
etSubidSim1.addTextChangedListener(object : TextWatcher {
|
||||||
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
||||||
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
|
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
|
||||||
@ -1008,7 +977,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
|
|||||||
|
|
||||||
//设置SIM2主键
|
//设置SIM2主键
|
||||||
private fun editAddSubidSim2(etSubidSim2: EditText) {
|
private fun editAddSubidSim2(etSubidSim2: EditText) {
|
||||||
etSubidSim2.setText(SettingUtils.subidSim2.toString())
|
etSubidSim2.setText("${SettingUtils.subidSim2}")
|
||||||
etSubidSim2.addTextChangedListener(object : TextWatcher {
|
etSubidSim2.addTextChangedListener(object : TextWatcher {
|
||||||
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
||||||
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
|
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
|
||||||
@ -1092,6 +1061,8 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
|
|||||||
|
|
||||||
//设置转发信息模版
|
//设置转发信息模版
|
||||||
private fun editSmsTemplate(textSmsTemplate: EditText) {
|
private fun editSmsTemplate(textSmsTemplate: EditText) {
|
||||||
|
//创建标签按钮
|
||||||
|
CommonUtils.createTagButtons(requireContext(), binding!!.glSmsTemplate, textSmsTemplate, "all")
|
||||||
textSmsTemplate.setText(SettingUtils.smsTemplate)
|
textSmsTemplate.setText(SettingUtils.smsTemplate)
|
||||||
textSmsTemplate.addTextChangedListener(object : TextWatcher {
|
textSmsTemplate.addTextChangedListener(object : TextWatcher {
|
||||||
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
||||||
@ -1206,6 +1177,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
|
|||||||
"huawei" -> getString(R.string.auto_start_huawei)
|
"huawei" -> getString(R.string.auto_start_huawei)
|
||||||
"honor" -> getString(R.string.auto_start_honor)
|
"honor" -> getString(R.string.auto_start_honor)
|
||||||
"xiaomi" -> getString(R.string.auto_start_xiaomi)
|
"xiaomi" -> getString(R.string.auto_start_xiaomi)
|
||||||
|
"redmi" -> getString(R.string.auto_start_redmi)
|
||||||
"oppo" -> getString(R.string.auto_start_oppo)
|
"oppo" -> getString(R.string.auto_start_oppo)
|
||||||
"vivo" -> getString(R.string.auto_start_vivo)
|
"vivo" -> getString(R.string.auto_start_vivo)
|
||||||
"meizu" -> getString(R.string.auto_start_meizu)
|
"meizu" -> getString(R.string.auto_start_meizu)
|
||||||
|
@ -20,6 +20,7 @@ import com.idormy.sms.forwarder.databinding.FragmentTasksActionAlarmBinding
|
|||||||
import com.idormy.sms.forwarder.entity.MsgInfo
|
import com.idormy.sms.forwarder.entity.MsgInfo
|
||||||
import com.idormy.sms.forwarder.entity.TaskSetting
|
import com.idormy.sms.forwarder.entity.TaskSetting
|
||||||
import com.idormy.sms.forwarder.entity.action.AlarmSetting
|
import com.idormy.sms.forwarder.entity.action.AlarmSetting
|
||||||
|
import com.idormy.sms.forwarder.utils.CommonUtils
|
||||||
import com.idormy.sms.forwarder.utils.KEY_BACK_DATA_ACTION
|
import com.idormy.sms.forwarder.utils.KEY_BACK_DATA_ACTION
|
||||||
import com.idormy.sms.forwarder.utils.KEY_BACK_DESCRIPTION_ACTION
|
import com.idormy.sms.forwarder.utils.KEY_BACK_DESCRIPTION_ACTION
|
||||||
import com.idormy.sms.forwarder.utils.KEY_EVENT_DATA_ACTION
|
import com.idormy.sms.forwarder.utils.KEY_EVENT_DATA_ACTION
|
||||||
@ -37,6 +38,7 @@ import com.xuexiang.xui.widget.actionbar.TitleBar
|
|||||||
import com.xuexiang.xui.widget.dialog.materialdialog.MaterialDialog
|
import com.xuexiang.xui.widget.dialog.materialdialog.MaterialDialog
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
@Page(name = "Alarm")
|
@Page(name = "Alarm")
|
||||||
@Suppress("PrivatePropertyName", "DEPRECATION")
|
@Suppress("PrivatePropertyName", "DEPRECATION")
|
||||||
@ -84,24 +86,45 @@ class AlarmFragment : BaseFragment<FragmentTasksActionAlarmBinding?>(), View.OnC
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
binding!!.sbEnableMusic.setOnCheckedChangeListener { _, isChecked ->
|
||||||
|
binding!!.layoutAlarmSettingsContent.visibility = if (isChecked) View.VISIBLE else View.GONE
|
||||||
|
checkSetting(true)
|
||||||
|
}
|
||||||
|
binding!!.sbEnableVibrate.setOnCheckedChangeListener { _, isChecked ->
|
||||||
|
binding!!.layoutVibrateSettingsContent.visibility = if (isChecked) View.VISIBLE else View.GONE
|
||||||
|
checkSetting(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
var settingVo = AlarmSetting()
|
||||||
Log.d(TAG, "initViews eventData:$eventData")
|
Log.d(TAG, "initViews eventData:$eventData")
|
||||||
if (eventData != null) {
|
if (eventData != null) {
|
||||||
val settingVo = Gson().fromJson(eventData, AlarmSetting::class.java)
|
settingVo = Gson().fromJson(eventData, AlarmSetting::class.java)
|
||||||
Log.d(TAG, "initViews settingVo:$settingVo")
|
Log.d(TAG, "initViews settingVo:$settingVo")
|
||||||
if (settingVo.action == "start") {
|
if (settingVo.action == "start") {
|
||||||
binding!!.rgAlarmState.check(R.id.rb_start_alarm)
|
binding!!.rgAlarmState.check(R.id.rb_start_alarm)
|
||||||
binding!!.layoutAlarmSettings.visibility = View.VISIBLE
|
binding!!.layoutAlarmSettings.visibility = View.VISIBLE
|
||||||
|
binding!!.layoutVibrateSettings.visibility = View.VISIBLE
|
||||||
|
binding!!.layoutFlashSettings.visibility = View.VISIBLE
|
||||||
} else {
|
} else {
|
||||||
binding!!.rgAlarmState.check(R.id.rb_stop_alarm)
|
binding!!.rgAlarmState.check(R.id.rb_stop_alarm)
|
||||||
binding!!.layoutAlarmSettings.visibility = View.GONE
|
binding!!.layoutAlarmSettings.visibility = View.GONE
|
||||||
|
binding!!.layoutVibrateSettings.visibility = View.GONE
|
||||||
|
binding!!.layoutFlashSettings.visibility = View.GONE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
binding!!.xsbVolume.setDefaultValue(settingVo.volume)
|
binding!!.xsbVolume.setDefaultValue(settingVo.volume)
|
||||||
binding!!.xsbLoopTimes.setDefaultValue(settingVo.playTimes)
|
binding!!.xsbPlayTimes.setDefaultValue(if (settingVo.playTimes >= 0) settingVo.playTimes else 0)
|
||||||
binding!!.etMusicPath.setText(settingVo.music)
|
binding!!.etMusicPath.setText(settingVo.music)
|
||||||
} else {
|
binding!!.xsbRepeatTimes.setDefaultValue(if (settingVo.repeatTimes >= 0) settingVo.repeatTimes else 0)
|
||||||
binding!!.xsbVolume.setDefaultValue(80)
|
binding!!.etVibrationEffect.setText(settingVo.vibrate)
|
||||||
binding!!.xsbLoopTimes.setDefaultValue(1)
|
binding!!.xsbFlashTimes.setDefaultValue(if (settingVo.flashTimes >= 0) settingVo.flashTimes else 0)
|
||||||
}
|
binding!!.etFlashEffect.setText(settingVo.flash)
|
||||||
|
binding!!.sbEnableMusic.isChecked = settingVo.playTimes >= 0
|
||||||
|
binding!!.sbEnableVibrate.isChecked = settingVo.repeatTimes >= 0
|
||||||
|
binding!!.sbEnableFlash.isChecked = settingVo.flashTimes >= 0
|
||||||
|
binding!!.layoutAlarmSettingsContent.visibility = if (settingVo.playTimes >= 0) View.VISIBLE else View.GONE
|
||||||
|
binding!!.layoutVibrateSettingsContent.visibility = if (settingVo.repeatTimes >= 0) View.VISIBLE else View.GONE
|
||||||
|
binding!!.layoutFlashSettingsContent.visibility = if (settingVo.flashTimes >= 0) View.VISIBLE else View.GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
@ -118,19 +141,53 @@ class AlarmFragment : BaseFragment<FragmentTasksActionAlarmBinding?>(), View.OnC
|
|||||||
binding!!.xsbVolume.setOnSeekBarListener { _, _ ->
|
binding!!.xsbVolume.setOnSeekBarListener { _, _ ->
|
||||||
checkSetting(true)
|
checkSetting(true)
|
||||||
}
|
}
|
||||||
binding!!.xsbLoopTimes.setOnSeekBarListener { _, _ ->
|
binding!!.xsbPlayTimes.setOnSeekBarListener { _, _ ->
|
||||||
|
checkSetting(true)
|
||||||
|
}
|
||||||
|
binding!!.xsbRepeatTimes.setOnSeekBarListener { _, _ ->
|
||||||
checkSetting(true)
|
checkSetting(true)
|
||||||
}
|
}
|
||||||
binding!!.rgAlarmState.setOnCheckedChangeListener { _, checkedId ->
|
binding!!.rgAlarmState.setOnCheckedChangeListener { _, checkedId ->
|
||||||
binding!!.layoutAlarmSettings.visibility = if (checkedId == R.id.rb_start_alarm) View.VISIBLE else View.GONE
|
binding!!.layoutAlarmSettings.visibility = if (checkedId == R.id.rb_start_alarm) View.VISIBLE else View.GONE
|
||||||
|
binding!!.layoutVibrateSettings.visibility = if (checkedId == R.id.rb_start_alarm) View.VISIBLE else View.GONE
|
||||||
|
binding!!.layoutFlashSettings.visibility = if (checkedId == R.id.rb_start_alarm) View.VISIBLE else View.GONE
|
||||||
checkSetting(true)
|
checkSetting(true)
|
||||||
}
|
}
|
||||||
|
binding!!.btInsertVibrationEffect1.setOnClickListener(this)
|
||||||
|
binding!!.btInsertVibrationEffect2.setOnClickListener(this)
|
||||||
|
binding!!.btInsertVibrationEffect3.setOnClickListener(this)
|
||||||
|
binding!!.btInsertFlashEffect1.setOnClickListener(this)
|
||||||
|
binding!!.btInsertFlashEffect2.setOnClickListener(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
@SingleClick
|
@SingleClick
|
||||||
override fun onClick(v: View) {
|
override fun onClick(v: View) {
|
||||||
try {
|
try {
|
||||||
when (v.id) {
|
when (v.id) {
|
||||||
|
R.id.bt_insert_vibration_effect_1 -> {
|
||||||
|
CommonUtils.insertOrReplaceText2Cursor(binding!!.etVibrationEffect, "=")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.bt_insert_vibration_effect_2 -> {
|
||||||
|
CommonUtils.insertOrReplaceText2Cursor(binding!!.etVibrationEffect, "-")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.bt_insert_vibration_effect_3 -> {
|
||||||
|
CommonUtils.insertOrReplaceText2Cursor(binding!!.etVibrationEffect, "_")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.bt_insert_flash_effect_1 -> {
|
||||||
|
CommonUtils.insertOrReplaceText2Cursor(binding!!.etFlashEffect, "X")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.bt_insert_flash_effect_2 -> {
|
||||||
|
CommonUtils.insertOrReplaceText2Cursor(binding!!.etFlashEffect, "O")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
R.id.btn_file_picker -> {
|
R.id.btn_file_picker -> {
|
||||||
// 申请储存权限
|
// 申请储存权限
|
||||||
@ -165,14 +222,23 @@ class AlarmFragment : BaseFragment<FragmentTasksActionAlarmBinding?>(), View.OnC
|
|||||||
}
|
}
|
||||||
|
|
||||||
R.id.btn_test -> {
|
R.id.btn_test -> {
|
||||||
|
val permissions = arrayListOf<String>()
|
||||||
|
permissions.add(Permission.WRITE_SETTINGS)
|
||||||
|
if (binding!!.sbEnableFlash.isChecked) {
|
||||||
|
permissions.add(Permission.CAMERA)
|
||||||
|
}
|
||||||
// 申请修改系统设置权限
|
// 申请修改系统设置权限
|
||||||
XXPermissions.with(this).permission(Permission.WRITE_SETTINGS).request(object : OnPermissionCallback {
|
XXPermissions.with(this).permission(permissions).request(object : OnPermissionCallback {
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
override fun onGranted(permissions: List<String>, all: Boolean) {
|
override fun onGranted(permissions: List<String>, all: Boolean) {
|
||||||
mCountDownHelper?.start()
|
mCountDownHelper?.start()
|
||||||
try {
|
try {
|
||||||
val settingVo = checkSetting()
|
val settingVo = checkSetting()
|
||||||
Log.d(TAG, settingVo.toString())
|
Log.d(TAG, settingVo.toString())
|
||||||
|
if (settingVo.playTimes < 0 && settingVo.repeatTimes < 0 && settingVo.flashTimes < 0) {
|
||||||
|
XToastUtils.error(getString(R.string.alarm_settings_error))
|
||||||
|
return
|
||||||
|
}
|
||||||
val taskAction = TaskSetting(TASK_ACTION_ALARM, getString(R.string.task_alarm), settingVo.description, Gson().toJson(settingVo), requestCode)
|
val taskAction = TaskSetting(TASK_ACTION_ALARM, getString(R.string.task_alarm), settingVo.description, Gson().toJson(settingVo), requestCode)
|
||||||
val taskActionsJson = Gson().toJson(arrayListOf(taskAction))
|
val taskActionsJson = Gson().toJson(arrayListOf(taskAction))
|
||||||
val msgInfo = MsgInfo("task", getString(R.string.task_alarm), settingVo.description, Date(), getString(R.string.task_alarm))
|
val msgInfo = MsgInfo("task", getString(R.string.task_alarm), settingVo.description, Date(), getString(R.string.task_alarm))
|
||||||
@ -207,11 +273,20 @@ class AlarmFragment : BaseFragment<FragmentTasksActionAlarmBinding?>(), View.OnC
|
|||||||
}
|
}
|
||||||
|
|
||||||
R.id.btn_save -> {
|
R.id.btn_save -> {
|
||||||
|
val permissions = arrayListOf<String>()
|
||||||
|
permissions.add(Permission.WRITE_SETTINGS)
|
||||||
|
if (binding!!.sbEnableFlash.isChecked) {
|
||||||
|
permissions.add(Permission.CAMERA)
|
||||||
|
}
|
||||||
// 申请修改系统设置权限
|
// 申请修改系统设置权限
|
||||||
XXPermissions.with(this).permission(Permission.WRITE_SETTINGS).request(object : OnPermissionCallback {
|
XXPermissions.with(this).permission(permissions).request(object : OnPermissionCallback {
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
override fun onGranted(permissions: List<String>, all: Boolean) {
|
override fun onGranted(permissions: List<String>, all: Boolean) {
|
||||||
val settingVo = checkSetting()
|
val settingVo = checkSetting()
|
||||||
|
if (settingVo.playTimes < 0 && settingVo.repeatTimes < 0 && settingVo.flashTimes < 0) {
|
||||||
|
XToastUtils.error(getString(R.string.alarm_settings_error))
|
||||||
|
return
|
||||||
|
}
|
||||||
val intent = Intent()
|
val intent = Intent()
|
||||||
intent.putExtra(KEY_BACK_DESCRIPTION_ACTION, settingVo.description)
|
intent.putExtra(KEY_BACK_DESCRIPTION_ACTION, settingVo.description)
|
||||||
intent.putExtra(KEY_BACK_DATA_ACTION, Gson().toJson(settingVo))
|
intent.putExtra(KEY_BACK_DATA_ACTION, Gson().toJson(settingVo))
|
||||||
@ -244,17 +319,43 @@ class AlarmFragment : BaseFragment<FragmentTasksActionAlarmBinding?>(), View.OnC
|
|||||||
@Suppress("SameParameterValue")
|
@Suppress("SameParameterValue")
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
private fun checkSetting(updateView: Boolean = false): AlarmSetting {
|
private fun checkSetting(updateView: Boolean = false): AlarmSetting {
|
||||||
|
val enableMusic = binding!!.sbEnableMusic.isChecked
|
||||||
|
val enableVibrate = binding!!.sbEnableVibrate.isChecked
|
||||||
|
val enableFlash = binding!!.sbEnableFlash.isChecked
|
||||||
val volume = binding!!.xsbVolume.selectedNumber
|
val volume = binding!!.xsbVolume.selectedNumber
|
||||||
val loopTimes = binding!!.xsbLoopTimes.selectedNumber
|
var playTimes = binding!!.xsbPlayTimes.selectedNumber
|
||||||
val music = binding!!.etMusicPath.text.toString().trim()
|
val music = binding!!.etMusicPath.text.toString().trim()
|
||||||
|
var repeatTimes = binding!!.xsbRepeatTimes.selectedNumber
|
||||||
|
val vibrationEffect = binding!!.etVibrationEffect.text.toString().trim()
|
||||||
|
var flashTimes = binding!!.xsbFlashTimes.selectedNumber
|
||||||
|
var flashEffect = binding!!.etFlashEffect.text.toString().trim()
|
||||||
val description = StringBuilder()
|
val description = StringBuilder()
|
||||||
val action = if (binding!!.rgAlarmState.checkedRadioButtonId == R.id.rb_start_alarm) {
|
val action = if (binding!!.rgAlarmState.checkedRadioButtonId == R.id.rb_start_alarm) {
|
||||||
description.append(getString(R.string.start_alarm))
|
description.append(getString(R.string.start_alarm))
|
||||||
|
if (enableMusic) {
|
||||||
description.append(", ").append(getString(R.string.alarm_volume)).append(":").append(volume).append("%")
|
description.append(", ").append(getString(R.string.alarm_volume)).append(":").append(volume).append("%")
|
||||||
description.append(", ").append(getString(R.string.alarm_play_times)).append(":").append(loopTimes)
|
description.append(", ").append(getString(R.string.alarm_play_times)).append(":").append(playTimes)
|
||||||
if (music.isNotEmpty()) {
|
if (music.isNotEmpty()) {
|
||||||
description.append(", ").append(getString(R.string.alarm_music)).append(":").append(music)
|
description.append(", ").append(getString(R.string.alarm_music)).append(":").append(music)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
playTimes = -1
|
||||||
|
}
|
||||||
|
if (enableVibrate) {
|
||||||
|
vibrationEffect.ifEmpty { "---___===___".also { binding!!.etVibrationEffect.setText(it) } }
|
||||||
|
description.append(", ").append(getString(R.string.alarm_vibration_effect)).append(":").append(vibrationEffect)
|
||||||
|
description.append(", ").append(getString(R.string.alarm_repeat_times)).append(":").append(repeatTimes)
|
||||||
|
} else {
|
||||||
|
repeatTimes = -1
|
||||||
|
}
|
||||||
|
if (enableFlash) {
|
||||||
|
flashEffect.ifEmpty { "XXOOXXOO".also { binding!!.etFlashEffect.setText(it) } }
|
||||||
|
flashEffect = flashEffect.toUpperCase(Locale.ROOT).replace("1", "X").replace("0", "O")
|
||||||
|
description.append(", ").append(getString(R.string.alarm_flash_effect)).append(":").append(flashEffect)
|
||||||
|
description.append(", ").append(getString(R.string.alarm_repeat_times)).append(":").append(flashTimes)
|
||||||
|
} else {
|
||||||
|
flashTimes = -1
|
||||||
|
}
|
||||||
"start"
|
"start"
|
||||||
} else {
|
} else {
|
||||||
description.append(getString(R.string.stop_alarm))
|
description.append(getString(R.string.stop_alarm))
|
||||||
@ -265,7 +366,7 @@ class AlarmFragment : BaseFragment<FragmentTasksActionAlarmBinding?>(), View.OnC
|
|||||||
binding!!.tvDescription.text = description.toString()
|
binding!!.tvDescription.text = description.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
return AlarmSetting(description.toString(), action, volume, loopTimes, music)
|
return AlarmSetting(description.toString(), action, volume, playTimes, music, repeatTimes, vibrationEffect, flashTimes, flashEffect)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findAudioFiles(directoryPath: String): List<String> {
|
private fun findAudioFiles(directoryPath: String): List<String> {
|
||||||
|
@ -7,7 +7,6 @@ import android.view.View
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.AdapterView
|
import android.widget.AdapterView
|
||||||
import android.widget.CompoundButton
|
import android.widget.CompoundButton
|
||||||
import android.widget.EditText
|
|
||||||
import androidx.recyclerview.widget.ItemTouchHelper
|
import androidx.recyclerview.widget.ItemTouchHelper
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
@ -156,6 +155,9 @@ class NotificationFragment : BaseFragment<FragmentTasksActionNotificationBinding
|
|||||||
|
|
||||||
//初始化发送通道下拉框
|
//初始化发送通道下拉框
|
||||||
initSenderSpinner()
|
initSenderSpinner()
|
||||||
|
|
||||||
|
//创建标签按钮
|
||||||
|
CommonUtils.createTagButtons(requireContext(), binding!!.glSmsTemplate, binding!!.etSmsTemplate, ruleType)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
@ -165,15 +167,6 @@ class NotificationFragment : BaseFragment<FragmentTasksActionNotificationBinding
|
|||||||
|
|
||||||
override fun initListeners() {
|
override fun initListeners() {
|
||||||
binding!!.btnSilentPeriod.setOnClickListener(this)
|
binding!!.btnSilentPeriod.setOnClickListener(this)
|
||||||
binding!!.btInsertSender.setOnClickListener(this)
|
|
||||||
binding!!.btInsertContent.setOnClickListener(this)
|
|
||||||
binding!!.btInsertSenderApp.setOnClickListener(this)
|
|
||||||
binding!!.btInsertUid.setOnClickListener(this)
|
|
||||||
binding!!.btInsertTitleApp.setOnClickListener(this)
|
|
||||||
binding!!.btInsertContentApp.setOnClickListener(this)
|
|
||||||
binding!!.btInsertExtra.setOnClickListener(this)
|
|
||||||
binding!!.btInsertTime.setOnClickListener(this)
|
|
||||||
binding!!.btInsertDeviceName.setOnClickListener(this)
|
|
||||||
binding!!.btnTest.setOnClickListener(this)
|
binding!!.btnTest.setOnClickListener(this)
|
||||||
binding!!.btnDel.setOnClickListener(this)
|
binding!!.btnDel.setOnClickListener(this)
|
||||||
binding!!.btnSave.setOnClickListener(this)
|
binding!!.btnSave.setOnClickListener(this)
|
||||||
@ -213,7 +206,6 @@ class NotificationFragment : BaseFragment<FragmentTasksActionNotificationBinding
|
|||||||
@SingleClick
|
@SingleClick
|
||||||
override fun onClick(v: View) {
|
override fun onClick(v: View) {
|
||||||
try {
|
try {
|
||||||
val etSmsTemplate: EditText = binding!!.etSmsTemplate
|
|
||||||
when (v.id) {
|
when (v.id) {
|
||||||
R.id.btn_silent_period -> {
|
R.id.btn_silent_period -> {
|
||||||
OptionsPickerBuilder(context, OnOptionsSelectListener { _: View?, options1: Int, options2: Int, _: Int ->
|
OptionsPickerBuilder(context, OnOptionsSelectListener { _: View?, options1: Int, options2: Int, _: Int ->
|
||||||
@ -229,51 +221,6 @@ class NotificationFragment : BaseFragment<FragmentTasksActionNotificationBinding
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.bt_insert_sender -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etSmsTemplate, getString(R.string.tag_from))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_content -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etSmsTemplate, getString(R.string.tag_sms))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_sender_app -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etSmsTemplate, getString(R.string.tag_package_name))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_uid -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etSmsTemplate, getString(R.string.tag_uid))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_title_app -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etSmsTemplate, getString(R.string.tag_title))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_content_app -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etSmsTemplate, getString(R.string.tag_msg))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_extra -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etSmsTemplate, getString(R.string.tag_card_slot))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_time -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etSmsTemplate, getString(R.string.tag_receive_time))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_device_name -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etSmsTemplate, getString(R.string.tag_device_name))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.btn_test -> {
|
R.id.btn_test -> {
|
||||||
mCountDownHelper?.start()
|
mCountDownHelper?.start()
|
||||||
try {
|
try {
|
||||||
|
@ -3,9 +3,7 @@ package com.idormy.sms.forwarder.fragment.action
|
|||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.location.Criteria
|
import android.location.Criteria
|
||||||
import android.text.Editable
|
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import android.text.TextWatcher
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
@ -273,31 +271,25 @@ class SettingsFragment : BaseFragment<FragmentTasksActionSettingsBinding?>(), Vi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
//设置位置更新最小时间间隔(单位:毫秒); 默认间隔:10000毫秒,最小间隔:1000毫秒
|
//设置位置更新最小时间间隔(单位:毫秒); 默认间隔:10000毫秒,最小间隔:1000毫秒
|
||||||
binding!!.etMinInterval.addTextChangedListener(object : TextWatcher {
|
binding!!.etMinInterval.setOnFocusChangeListener { _, hasFocus ->
|
||||||
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
if (!hasFocus) {
|
||||||
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
|
val inputText = binding!!.etMinInterval.text.toString()
|
||||||
override fun afterTextChanged(s: Editable) {
|
if (inputText.isEmpty() || inputText == "0") {
|
||||||
val changedText = s.toString()
|
|
||||||
if (changedText.isEmpty() || changedText == "0") {
|
|
||||||
binding!!.etMinInterval.setText("1")
|
binding!!.etMinInterval.setText("1")
|
||||||
binding!!.etMinInterval.setSelection(binding!!.etMinInterval.text.length) // 将光标移至文本末尾
|
binding!!.etMinInterval.setSelection(binding!!.etMinInterval.text.length) // 将光标移至文本末尾
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
//设置位置更新最小距离(单位:米);默认距离:0米
|
//设置位置更新最小距离(单位:米);默认距离:0米
|
||||||
binding!!.etMinDistance.addTextChangedListener(object : TextWatcher {
|
binding!!.etMinDistance.setOnFocusChangeListener { _, hasFocus ->
|
||||||
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
if (!hasFocus) {
|
||||||
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
|
val inputText = binding!!.etMinDistance.text.toString()
|
||||||
override fun afterTextChanged(s: Editable) {
|
if (inputText.isEmpty()) {
|
||||||
val changedText = s.toString()
|
|
||||||
if (changedText.isEmpty()) {
|
|
||||||
binding!!.etMinDistance.setText("0")
|
binding!!.etMinDistance.setText("0")
|
||||||
binding!!.etMinDistance.setSelection(binding!!.etMinInterval.text.length) // 将光标移至文本末尾
|
binding!!.etMinDistance.setSelection(binding!!.etMinDistance.text.length) // 将光标移至文本末尾
|
||||||
return
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
|
||||||
|
|
||||||
binding!!.sbEnableSmsCommand.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean ->
|
binding!!.sbEnableSmsCommand.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean ->
|
||||||
if (isChecked) {
|
if (isChecked) {
|
||||||
|
@ -2,8 +2,6 @@ package com.idormy.sms.forwarder.fragment.condition
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.text.Editable
|
|
||||||
import android.text.TextWatcher
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
@ -99,13 +97,11 @@ class LeaveAddressFragment : BaseFragment<FragmentTasksConditionLeaveAddressBind
|
|||||||
binding!!.btnDel.setOnClickListener(this)
|
binding!!.btnDel.setOnClickListener(this)
|
||||||
binding!!.btnSave.setOnClickListener(this)
|
binding!!.btnSave.setOnClickListener(this)
|
||||||
binding!!.btnCurrentCoordinates.setOnClickListener(this)
|
binding!!.btnCurrentCoordinates.setOnClickListener(this)
|
||||||
binding!!.etLongitude.addTextChangedListener(object : TextWatcher {
|
binding!!.etLongitude.setOnFocusChangeListener { _, hasFocus ->
|
||||||
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
|
if (!hasFocus) {
|
||||||
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
|
|
||||||
override fun afterTextChanged(s: Editable?) {
|
|
||||||
try {
|
try {
|
||||||
val changedText = s.toString()
|
val inputText = binding!!.etLongitude.text.toString()
|
||||||
if (changedText.isEmpty()) {
|
if (inputText.isEmpty()) {
|
||||||
binding!!.etLongitude.setText("0")
|
binding!!.etLongitude.setText("0")
|
||||||
binding!!.etLongitude.setSelection(binding!!.etLongitude.text.length) // 将光标移至文本末尾
|
binding!!.etLongitude.setSelection(binding!!.etLongitude.text.length) // 将光标移至文本末尾
|
||||||
} else {
|
} else {
|
||||||
@ -113,17 +109,15 @@ class LeaveAddressFragment : BaseFragment<FragmentTasksConditionLeaveAddressBind
|
|||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
Log.e(TAG, "afterTextChanged error:$e")
|
Log.e(TAG, "etLongitude error:$e")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
binding!!.etLatitude.addTextChangedListener(object : TextWatcher {
|
binding!!.etLatitude.setOnFocusChangeListener { _, hasFocus ->
|
||||||
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
|
if (!hasFocus) {
|
||||||
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
|
|
||||||
override fun afterTextChanged(s: Editable?) {
|
|
||||||
try {
|
try {
|
||||||
val changedText = s.toString()
|
val inputText = binding!!.etLatitude.text.toString()
|
||||||
if (changedText.isEmpty()) {
|
if (inputText.isEmpty()) {
|
||||||
binding!!.etLatitude.setText("0")
|
binding!!.etLatitude.setText("0")
|
||||||
binding!!.etLatitude.setSelection(binding!!.etLatitude.text.length) // 将光标移至文本末尾
|
binding!!.etLatitude.setSelection(binding!!.etLatitude.text.length) // 将光标移至文本末尾
|
||||||
} else {
|
} else {
|
||||||
@ -131,17 +125,15 @@ class LeaveAddressFragment : BaseFragment<FragmentTasksConditionLeaveAddressBind
|
|||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
Log.e(TAG, "afterTextChanged error:$e")
|
Log.e(TAG, "etLatitude error:$e")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
binding!!.etDistance.addTextChangedListener(object : TextWatcher {
|
binding!!.etDistance.setOnFocusChangeListener { _, hasFocus ->
|
||||||
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
|
if (!hasFocus) {
|
||||||
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
|
|
||||||
override fun afterTextChanged(s: Editable?) {
|
|
||||||
try {
|
try {
|
||||||
val changedText = s.toString()
|
val inputText = binding!!.etDistance.text.toString()
|
||||||
if (changedText.isEmpty()) {
|
if (inputText.isEmpty()) {
|
||||||
binding!!.etDistance.setText("1")
|
binding!!.etDistance.setText("1")
|
||||||
binding!!.etDistance.setSelection(binding!!.etDistance.text.length) // 将光标移至文本末尾
|
binding!!.etDistance.setSelection(binding!!.etDistance.text.length) // 将光标移至文本末尾
|
||||||
} else {
|
} else {
|
||||||
@ -149,22 +141,20 @@ class LeaveAddressFragment : BaseFragment<FragmentTasksConditionLeaveAddressBind
|
|||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
Log.e(TAG, "afterTextChanged error:$e")
|
Log.e(TAG, "etDistance error:$e")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
binding!!.etAddress.addTextChangedListener(object : TextWatcher {
|
binding!!.etAddress.setOnFocusChangeListener { _, hasFocus ->
|
||||||
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
|
if (!hasFocus) {
|
||||||
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
|
|
||||||
override fun afterTextChanged(s: Editable?) {
|
|
||||||
try {
|
try {
|
||||||
checkSetting(true)
|
checkSetting(true)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
Log.e(TAG, "afterTextChanged error:$e")
|
Log.e(TAG, "etAddress error:$e")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SingleClick
|
@SingleClick
|
||||||
|
@ -2,8 +2,6 @@ package com.idormy.sms.forwarder.fragment.condition
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.text.Editable
|
|
||||||
import android.text.TextWatcher
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
@ -99,13 +97,11 @@ class ToAddressFragment : BaseFragment<FragmentTasksConditionToAddressBinding?>(
|
|||||||
binding!!.btnDel.setOnClickListener(this)
|
binding!!.btnDel.setOnClickListener(this)
|
||||||
binding!!.btnSave.setOnClickListener(this)
|
binding!!.btnSave.setOnClickListener(this)
|
||||||
binding!!.btnCurrentCoordinates.setOnClickListener(this)
|
binding!!.btnCurrentCoordinates.setOnClickListener(this)
|
||||||
binding!!.etLongitude.addTextChangedListener(object : TextWatcher {
|
binding!!.etLongitude.setOnFocusChangeListener { _, hasFocus ->
|
||||||
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
|
if (!hasFocus) {
|
||||||
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
|
|
||||||
override fun afterTextChanged(s: Editable?) {
|
|
||||||
try {
|
try {
|
||||||
val changedText = s.toString()
|
val inputText = binding!!.etLongitude.text.toString()
|
||||||
if (changedText.isEmpty()) {
|
if (inputText.isEmpty()) {
|
||||||
binding!!.etLongitude.setText("0")
|
binding!!.etLongitude.setText("0")
|
||||||
binding!!.etLongitude.setSelection(binding!!.etLongitude.text.length) // 将光标移至文本末尾
|
binding!!.etLongitude.setSelection(binding!!.etLongitude.text.length) // 将光标移至文本末尾
|
||||||
} else {
|
} else {
|
||||||
@ -113,17 +109,15 @@ class ToAddressFragment : BaseFragment<FragmentTasksConditionToAddressBinding?>(
|
|||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
Log.e(TAG, "afterTextChanged error:$e")
|
Log.e(TAG, "etLongitude error:$e")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
binding!!.etLatitude.addTextChangedListener(object : TextWatcher {
|
binding!!.etLatitude.setOnFocusChangeListener { _, hasFocus ->
|
||||||
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
|
if (!hasFocus) {
|
||||||
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
|
|
||||||
override fun afterTextChanged(s: Editable?) {
|
|
||||||
try {
|
try {
|
||||||
val changedText = s.toString()
|
val inputText = binding!!.etLatitude.text.toString()
|
||||||
if (changedText.isEmpty()) {
|
if (inputText.isEmpty()) {
|
||||||
binding!!.etLatitude.setText("0")
|
binding!!.etLatitude.setText("0")
|
||||||
binding!!.etLatitude.setSelection(binding!!.etLatitude.text.length) // 将光标移至文本末尾
|
binding!!.etLatitude.setSelection(binding!!.etLatitude.text.length) // 将光标移至文本末尾
|
||||||
} else {
|
} else {
|
||||||
@ -131,17 +125,15 @@ class ToAddressFragment : BaseFragment<FragmentTasksConditionToAddressBinding?>(
|
|||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
Log.e(TAG, "afterTextChanged error:$e")
|
Log.e(TAG, "etLatitude error:$e")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
binding!!.etDistance.addTextChangedListener(object : TextWatcher {
|
binding!!.etDistance.setOnFocusChangeListener { _, hasFocus ->
|
||||||
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
|
if (!hasFocus) {
|
||||||
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
|
|
||||||
override fun afterTextChanged(s: Editable?) {
|
|
||||||
try {
|
try {
|
||||||
val changedText = s.toString()
|
val inputText = binding!!.etDistance.text.toString()
|
||||||
if (changedText.isEmpty()) {
|
if (inputText.isEmpty()) {
|
||||||
binding!!.etDistance.setText("1")
|
binding!!.etDistance.setText("1")
|
||||||
binding!!.etDistance.setSelection(binding!!.etDistance.text.length) // 将光标移至文本末尾
|
binding!!.etDistance.setSelection(binding!!.etDistance.text.length) // 将光标移至文本末尾
|
||||||
} else {
|
} else {
|
||||||
@ -149,22 +141,20 @@ class ToAddressFragment : BaseFragment<FragmentTasksConditionToAddressBinding?>(
|
|||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
Log.e(TAG, "afterTextChanged error:$e")
|
Log.e(TAG, "etDistance error:$e")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
binding!!.etAddress.addTextChangedListener(object : TextWatcher {
|
binding!!.etAddress.setOnFocusChangeListener { _, hasFocus ->
|
||||||
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
|
if (!hasFocus) {
|
||||||
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
|
|
||||||
override fun afterTextChanged(s: Editable?) {
|
|
||||||
try {
|
try {
|
||||||
checkSetting(true)
|
checkSetting(true)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
Log.e(TAG, "afterTextChanged error:$e")
|
Log.e(TAG, "etAddress error:$e")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SingleClick
|
@SingleClick
|
||||||
|
@ -4,7 +4,6 @@ import android.text.TextUtils
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.EditText
|
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.idormy.sms.forwarder.App.Companion.BARK_ENCRYPTION_ALGORITHM_MAP
|
import com.idormy.sms.forwarder.App.Companion.BARK_ENCRYPTION_ALGORITHM_MAP
|
||||||
@ -124,6 +123,10 @@ class BarkFragment : BaseFragment<FragmentSendersBarkBinding?>(), View.OnClickLi
|
|||||||
}
|
}
|
||||||
binding!!.spEncryptionAlgorithm.selectedIndex = 0
|
binding!!.spEncryptionAlgorithm.selectedIndex = 0
|
||||||
|
|
||||||
|
//创建标签按钮
|
||||||
|
CommonUtils.createTagButtons(requireContext(), binding!!.glTitleTemplate, binding!!.etTitleTemplate)
|
||||||
|
CommonUtils.createTagButtons(requireContext(), binding!!.glAutoCopyTemplate, binding!!.etAutoCopyTemplate)
|
||||||
|
|
||||||
//新增
|
//新增
|
||||||
if (senderId <= 0) {
|
if (senderId <= 0) {
|
||||||
titleBar?.setSubTitle(getString(R.string.add_sender))
|
titleBar?.setSubTitle(getString(R.string.add_sender))
|
||||||
@ -156,6 +159,7 @@ class BarkFragment : BaseFragment<FragmentSendersBarkBinding?>(), View.OnClickLi
|
|||||||
binding!!.etServer.setText(settingVo.server)
|
binding!!.etServer.setText(settingVo.server)
|
||||||
binding!!.etGroup.setText(settingVo.group)
|
binding!!.etGroup.setText(settingVo.group)
|
||||||
binding!!.etIcon.setText(settingVo.icon)
|
binding!!.etIcon.setText(settingVo.icon)
|
||||||
|
binding!!.sbCall.isChecked = settingVo.call == "1"
|
||||||
binding!!.etSound.setText(settingVo.sound)
|
binding!!.etSound.setText(settingVo.sound)
|
||||||
binding!!.etBadge.setText(settingVo.badge)
|
binding!!.etBadge.setText(settingVo.badge)
|
||||||
binding!!.etUrl.setText(settingVo.url)
|
binding!!.etUrl.setText(settingVo.url)
|
||||||
@ -178,10 +182,6 @@ class BarkFragment : BaseFragment<FragmentSendersBarkBinding?>(), View.OnClickLi
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun initListeners() {
|
override fun initListeners() {
|
||||||
binding!!.btInsertSender.setOnClickListener(this)
|
|
||||||
binding!!.btInsertExtra.setOnClickListener(this)
|
|
||||||
binding!!.btInsertTime.setOnClickListener(this)
|
|
||||||
binding!!.btInsertDeviceName.setOnClickListener(this)
|
|
||||||
binding!!.btnTest.setOnClickListener(this)
|
binding!!.btnTest.setOnClickListener(this)
|
||||||
binding!!.btnDel.setOnClickListener(this)
|
binding!!.btnDel.setOnClickListener(this)
|
||||||
binding!!.btnSave.setOnClickListener(this)
|
binding!!.btnSave.setOnClickListener(this)
|
||||||
@ -191,27 +191,7 @@ class BarkFragment : BaseFragment<FragmentSendersBarkBinding?>(), View.OnClickLi
|
|||||||
@SingleClick
|
@SingleClick
|
||||||
override fun onClick(v: View) {
|
override fun onClick(v: View) {
|
||||||
try {
|
try {
|
||||||
val etTitleTemplate: EditText = binding!!.etTitleTemplate
|
|
||||||
when (v.id) {
|
when (v.id) {
|
||||||
R.id.bt_insert_sender -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etTitleTemplate, getString(R.string.tag_from))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_extra -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etTitleTemplate, getString(R.string.tag_card_slot))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_time -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etTitleTemplate, getString(R.string.tag_receive_time))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_device_name -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etTitleTemplate, getString(R.string.tag_device_name))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.btn_test -> {
|
R.id.btn_test -> {
|
||||||
mCountDownHelper?.start()
|
mCountDownHelper?.start()
|
||||||
@ -281,6 +261,7 @@ class BarkFragment : BaseFragment<FragmentSendersBarkBinding?>(), View.OnClickLi
|
|||||||
if (!CommonUtils.checkUrl(icon, true)) {
|
if (!CommonUtils.checkUrl(icon, true)) {
|
||||||
throw Exception(getString(R.string.invalid_bark_icon))
|
throw Exception(getString(R.string.invalid_bark_icon))
|
||||||
}
|
}
|
||||||
|
val call = if (binding!!.sbCall.isChecked) "1" else "0"
|
||||||
val sound = binding!!.etSound.text.toString().trim()
|
val sound = binding!!.etSound.text.toString().trim()
|
||||||
val badge = binding!!.etBadge.text.toString().trim()
|
val badge = binding!!.etBadge.text.toString().trim()
|
||||||
val url = binding!!.etUrl.text.toString().trim()
|
val url = binding!!.etUrl.text.toString().trim()
|
||||||
@ -288,6 +269,7 @@ class BarkFragment : BaseFragment<FragmentSendersBarkBinding?>(), View.OnClickLi
|
|||||||
throw Exception(getString(R.string.invalid_bark_url))
|
throw Exception(getString(R.string.invalid_bark_url))
|
||||||
}
|
}
|
||||||
val title = binding!!.etTitleTemplate.text.toString().trim()
|
val title = binding!!.etTitleTemplate.text.toString().trim()
|
||||||
|
val autoCopy = binding!!.etAutoCopyTemplate.text.toString().trim()
|
||||||
val key = binding!!.etEncryptionKey.text.toString().trim()
|
val key = binding!!.etEncryptionKey.text.toString().trim()
|
||||||
val iv = binding!!.etEncryptionIv.text.toString().trim()
|
val iv = binding!!.etEncryptionIv.text.toString().trim()
|
||||||
if (transformation.startsWith("AES128") && key.length != 16) {
|
if (transformation.startsWith("AES128") && key.length != 16) {
|
||||||
@ -301,7 +283,7 @@ class BarkFragment : BaseFragment<FragmentSendersBarkBinding?>(), View.OnClickLi
|
|||||||
throw Exception(getString(R.string.bark_encryption_key_error4))
|
throw Exception(getString(R.string.bark_encryption_key_error4))
|
||||||
}
|
}
|
||||||
|
|
||||||
return BarkSetting(server, group, icon, sound, badge, url, barkLevel, title, transformation, key, iv)
|
return BarkSetting(server, group, icon, sound, badge, url, barkLevel, title, transformation, key, iv, call, autoCopy)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
|
@ -5,7 +5,6 @@ import android.view.LayoutInflater
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.CompoundButton
|
import android.widget.CompoundButton
|
||||||
import android.widget.EditText
|
|
||||||
import android.widget.RadioGroup
|
import android.widget.RadioGroup
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
@ -96,6 +95,9 @@ class DingtalkGroupRobotFragment : BaseFragment<FragmentSendersDingtalkGroupRobo
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
//创建标签按钮
|
||||||
|
CommonUtils.createTagButtons(requireContext(), binding!!.glTitleTemplate, binding!!.etTitleTemplate)
|
||||||
|
|
||||||
//新增
|
//新增
|
||||||
if (senderId <= 0) {
|
if (senderId <= 0) {
|
||||||
titleBar?.setSubTitle(getString(R.string.add_sender))
|
titleBar?.setSubTitle(getString(R.string.add_sender))
|
||||||
@ -138,10 +140,6 @@ class DingtalkGroupRobotFragment : BaseFragment<FragmentSendersDingtalkGroupRobo
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun initListeners() {
|
override fun initListeners() {
|
||||||
binding!!.btInsertSender.setOnClickListener(this)
|
|
||||||
binding!!.btInsertExtra.setOnClickListener(this)
|
|
||||||
binding!!.btInsertTime.setOnClickListener(this)
|
|
||||||
binding!!.btInsertDeviceName.setOnClickListener(this)
|
|
||||||
binding!!.btnTest.setOnClickListener(this)
|
binding!!.btnTest.setOnClickListener(this)
|
||||||
binding!!.btnDel.setOnClickListener(this)
|
binding!!.btnDel.setOnClickListener(this)
|
||||||
binding!!.btnSave.setOnClickListener(this)
|
binding!!.btnSave.setOnClickListener(this)
|
||||||
@ -168,27 +166,7 @@ class DingtalkGroupRobotFragment : BaseFragment<FragmentSendersDingtalkGroupRobo
|
|||||||
@SingleClick
|
@SingleClick
|
||||||
override fun onClick(v: View) {
|
override fun onClick(v: View) {
|
||||||
try {
|
try {
|
||||||
val etTitleTemplate: EditText = binding!!.etTitleTemplate
|
|
||||||
when (v.id) {
|
when (v.id) {
|
||||||
R.id.bt_insert_sender -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etTitleTemplate, getString(R.string.tag_from))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_extra -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etTitleTemplate, getString(R.string.tag_card_slot))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_time -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etTitleTemplate, getString(R.string.tag_receive_time))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_device_name -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etTitleTemplate, getString(R.string.tag_device_name))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.btn_test -> {
|
R.id.btn_test -> {
|
||||||
mCountDownHelper?.start()
|
mCountDownHelper?.start()
|
||||||
|
@ -6,7 +6,6 @@ import android.view.LayoutInflater
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.CompoundButton
|
import android.widget.CompoundButton
|
||||||
import android.widget.EditText
|
|
||||||
import android.widget.RadioGroup
|
import android.widget.RadioGroup
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
@ -19,7 +18,15 @@ import com.idormy.sms.forwarder.database.viewmodel.SenderViewModel
|
|||||||
import com.idormy.sms.forwarder.databinding.FragmentSendersDingtalkInnerRobotBinding
|
import com.idormy.sms.forwarder.databinding.FragmentSendersDingtalkInnerRobotBinding
|
||||||
import com.idormy.sms.forwarder.entity.MsgInfo
|
import com.idormy.sms.forwarder.entity.MsgInfo
|
||||||
import com.idormy.sms.forwarder.entity.setting.DingtalkInnerRobotSetting
|
import com.idormy.sms.forwarder.entity.setting.DingtalkInnerRobotSetting
|
||||||
import com.idormy.sms.forwarder.utils.*
|
import com.idormy.sms.forwarder.utils.CommonUtils
|
||||||
|
import com.idormy.sms.forwarder.utils.EVENT_TOAST_ERROR
|
||||||
|
import com.idormy.sms.forwarder.utils.KEY_SENDER_CLONE
|
||||||
|
import com.idormy.sms.forwarder.utils.KEY_SENDER_ID
|
||||||
|
import com.idormy.sms.forwarder.utils.KEY_SENDER_TEST
|
||||||
|
import com.idormy.sms.forwarder.utils.KEY_SENDER_TYPE
|
||||||
|
import com.idormy.sms.forwarder.utils.Log
|
||||||
|
import com.idormy.sms.forwarder.utils.SettingUtils
|
||||||
|
import com.idormy.sms.forwarder.utils.XToastUtils
|
||||||
import com.idormy.sms.forwarder.utils.sender.DingtalkInnerRobotUtils
|
import com.idormy.sms.forwarder.utils.sender.DingtalkInnerRobotUtils
|
||||||
import com.jeremyliao.liveeventbus.LiveEventBus
|
import com.jeremyliao.liveeventbus.LiveEventBus
|
||||||
import com.xuexiang.xaop.annotation.SingleClick
|
import com.xuexiang.xaop.annotation.SingleClick
|
||||||
@ -35,7 +42,7 @@ import io.reactivex.android.schedulers.AndroidSchedulers
|
|||||||
import io.reactivex.disposables.Disposable
|
import io.reactivex.disposables.Disposable
|
||||||
import io.reactivex.schedulers.Schedulers
|
import io.reactivex.schedulers.Schedulers
|
||||||
import java.net.Proxy
|
import java.net.Proxy
|
||||||
import java.util.*
|
import java.util.Date
|
||||||
|
|
||||||
@Page(name = "钉钉企业机器人")
|
@Page(name = "钉钉企业机器人")
|
||||||
@Suppress("PrivatePropertyName")
|
@Suppress("PrivatePropertyName")
|
||||||
@ -90,6 +97,9 @@ class DingtalkInnerRobotFragment : BaseFragment<FragmentSendersDingtalkInnerRobo
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
//创建标签按钮
|
||||||
|
CommonUtils.createTagButtons(requireContext(), binding!!.glTitleTemplate, binding!!.etTitleTemplate)
|
||||||
|
|
||||||
//新增
|
//新增
|
||||||
if (senderId <= 0) {
|
if (senderId <= 0) {
|
||||||
titleBar?.setSubTitle(getString(R.string.add_sender))
|
titleBar?.setSubTitle(getString(R.string.add_sender))
|
||||||
@ -137,10 +147,6 @@ class DingtalkInnerRobotFragment : BaseFragment<FragmentSendersDingtalkInnerRobo
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun initListeners() {
|
override fun initListeners() {
|
||||||
binding!!.btInsertSender.setOnClickListener(this)
|
|
||||||
binding!!.btInsertExtra.setOnClickListener(this)
|
|
||||||
binding!!.btInsertTime.setOnClickListener(this)
|
|
||||||
binding!!.btInsertDeviceName.setOnClickListener(this)
|
|
||||||
binding!!.btnTest.setOnClickListener(this)
|
binding!!.btnTest.setOnClickListener(this)
|
||||||
binding!!.btnDel.setOnClickListener(this)
|
binding!!.btnDel.setOnClickListener(this)
|
||||||
binding!!.btnSave.setOnClickListener(this)
|
binding!!.btnSave.setOnClickListener(this)
|
||||||
@ -176,27 +182,7 @@ class DingtalkInnerRobotFragment : BaseFragment<FragmentSendersDingtalkInnerRobo
|
|||||||
@SingleClick
|
@SingleClick
|
||||||
override fun onClick(v: View) {
|
override fun onClick(v: View) {
|
||||||
try {
|
try {
|
||||||
val etTitleTemplate: EditText = binding!!.etTitleTemplate
|
|
||||||
when (v.id) {
|
when (v.id) {
|
||||||
R.id.bt_insert_sender -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etTitleTemplate, getString(R.string.tag_from))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_extra -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etTitleTemplate, getString(R.string.tag_card_slot))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_time -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etTitleTemplate, getString(R.string.tag_receive_time))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_device_name -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etTitleTemplate, getString(R.string.tag_device_name))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.btn_test -> {
|
R.id.btn_test -> {
|
||||||
mCountDownHelper?.start()
|
mCountDownHelper?.start()
|
||||||
|
@ -166,6 +166,10 @@ class EmailFragment : BaseFragment<FragmentSendersEmailBinding?>(), View.OnClick
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//创建标签按钮
|
||||||
|
CommonUtils.createTagButtons(requireContext(), binding!!.glTitleTemplate, binding!!.etTitleTemplate)
|
||||||
|
CommonUtils.createTagButtons(requireContext(), binding!!.glNickname, binding!!.etNickname)
|
||||||
|
|
||||||
//新增
|
//新增
|
||||||
if (senderId <= 0) {
|
if (senderId <= 0) {
|
||||||
titleBar?.setSubTitle(getString(R.string.add_sender))
|
titleBar?.setSubTitle(getString(R.string.add_sender))
|
||||||
@ -237,14 +241,6 @@ class EmailFragment : BaseFragment<FragmentSendersEmailBinding?>(), View.OnClick
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun initListeners() {
|
override fun initListeners() {
|
||||||
binding!!.btInsertSenderToNickname.setOnClickListener(this)
|
|
||||||
binding!!.btInsertExtraToNickname.setOnClickListener(this)
|
|
||||||
binding!!.btInsertTimeToNickname.setOnClickListener(this)
|
|
||||||
binding!!.btInsertDeviceNameToNickname.setOnClickListener(this)
|
|
||||||
binding!!.btInsertSender.setOnClickListener(this)
|
|
||||||
binding!!.btInsertExtra.setOnClickListener(this)
|
|
||||||
binding!!.btInsertTime.setOnClickListener(this)
|
|
||||||
binding!!.btInsertDeviceName.setOnClickListener(this)
|
|
||||||
binding!!.btnTest.setOnClickListener(this)
|
binding!!.btnTest.setOnClickListener(this)
|
||||||
binding!!.btnDel.setOnClickListener(this)
|
binding!!.btnDel.setOnClickListener(this)
|
||||||
binding!!.btnSave.setOnClickListener(this)
|
binding!!.btnSave.setOnClickListener(this)
|
||||||
@ -260,48 +256,7 @@ class EmailFragment : BaseFragment<FragmentSendersEmailBinding?>(), View.OnClick
|
|||||||
@SingleClick
|
@SingleClick
|
||||||
override fun onClick(v: View) {
|
override fun onClick(v: View) {
|
||||||
try {
|
try {
|
||||||
val etNickname: EditText = binding!!.etNickname
|
|
||||||
val etTitleTemplate: EditText = binding!!.etTitleTemplate
|
|
||||||
when (v.id) {
|
when (v.id) {
|
||||||
R.id.bt_insert_sender_to_nickname -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etNickname, getString(R.string.tag_from))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_extra_to_nickname -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etNickname, getString(R.string.tag_card_slot))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_time_to_nickname -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etNickname, getString(R.string.tag_receive_time))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_device_name_to_nickname -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etNickname, getString(R.string.tag_device_name))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_sender -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etTitleTemplate, getString(R.string.tag_from))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_extra -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etTitleTemplate, getString(R.string.tag_card_slot))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_time -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etTitleTemplate, getString(R.string.tag_receive_time))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_device_name -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etTitleTemplate, getString(R.string.tag_device_name))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.btn_test -> {
|
R.id.btn_test -> {
|
||||||
mCountDownHelper?.start()
|
mCountDownHelper?.start()
|
||||||
|
@ -4,7 +4,6 @@ import android.text.TextUtils
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.EditText
|
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.google.gson.JsonParser
|
import com.google.gson.JsonParser
|
||||||
@ -105,6 +104,10 @@ class FeishuAppFragment : BaseFragment<FragmentSendersFeishuAppBinding?>(), View
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//创建标签按钮
|
||||||
|
CommonUtils.createTagButtons(requireContext(), binding!!.glTitleTemplate, binding!!.etTitleTemplate)
|
||||||
|
CommonUtils.createTagButtons(requireContext(), binding!!.glMessageCard, binding!!.etMessageCard)
|
||||||
|
|
||||||
//新增
|
//新增
|
||||||
if (senderId <= 0) {
|
if (senderId <= 0) {
|
||||||
titleBar?.setSubTitle(getString(R.string.add_sender))
|
titleBar?.setSubTitle(getString(R.string.add_sender))
|
||||||
@ -150,15 +153,6 @@ class FeishuAppFragment : BaseFragment<FragmentSendersFeishuAppBinding?>(), View
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun initListeners() {
|
override fun initListeners() {
|
||||||
binding!!.btInsertSenderToTitle.setOnClickListener(this)
|
|
||||||
binding!!.btInsertExtraToTitle.setOnClickListener(this)
|
|
||||||
binding!!.btInsertTimeToTitle.setOnClickListener(this)
|
|
||||||
binding!!.btInsertDeviceNameToTitle.setOnClickListener(this)
|
|
||||||
binding!!.btInsertSender.setOnClickListener(this)
|
|
||||||
binding!!.btInsertContent.setOnClickListener(this)
|
|
||||||
binding!!.btInsertExtra.setOnClickListener(this)
|
|
||||||
binding!!.btInsertTime.setOnClickListener(this)
|
|
||||||
binding!!.btInsertDeviceName.setOnClickListener(this)
|
|
||||||
binding!!.btnTest.setOnClickListener(this)
|
binding!!.btnTest.setOnClickListener(this)
|
||||||
binding!!.btnDel.setOnClickListener(this)
|
binding!!.btnDel.setOnClickListener(this)
|
||||||
binding!!.btnSave.setOnClickListener(this)
|
binding!!.btnSave.setOnClickListener(this)
|
||||||
@ -168,53 +162,7 @@ class FeishuAppFragment : BaseFragment<FragmentSendersFeishuAppBinding?>(), View
|
|||||||
@SingleClick
|
@SingleClick
|
||||||
override fun onClick(v: View) {
|
override fun onClick(v: View) {
|
||||||
try {
|
try {
|
||||||
val etTitleTemplate: EditText = binding!!.etTitleTemplate
|
|
||||||
val etMessageCard: EditText = binding!!.etMessageCard
|
|
||||||
when (v.id) {
|
when (v.id) {
|
||||||
R.id.bt_insert_sender_to_title -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etTitleTemplate, getString(R.string.tag_from))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_extra_to_title -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etTitleTemplate, getString(R.string.tag_card_slot))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_time_to_title -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etTitleTemplate, getString(R.string.tag_receive_time))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_device_name_to_title -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etTitleTemplate, getString(R.string.tag_device_name))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_sender -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etMessageCard, getString(R.string.tag_from))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_content -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etMessageCard, getString(R.string.tag_sms))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_extra -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etMessageCard, getString(R.string.tag_card_slot))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_time -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etMessageCard, getString(R.string.tag_receive_time))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_device_name -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etMessageCard, getString(R.string.tag_device_name))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.btn_test -> {
|
R.id.btn_test -> {
|
||||||
mCountDownHelper?.start()
|
mCountDownHelper?.start()
|
||||||
|
@ -4,7 +4,6 @@ import android.text.TextUtils
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.EditText
|
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.google.gson.JsonParser
|
import com.google.gson.JsonParser
|
||||||
@ -105,6 +104,10 @@ class FeishuFragment : BaseFragment<FragmentSendersFeishuBinding?>(), View.OnCli
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//创建标签按钮
|
||||||
|
CommonUtils.createTagButtons(requireContext(), binding!!.glTitleTemplate, binding!!.etTitleTemplate)
|
||||||
|
CommonUtils.createTagButtons(requireContext(), binding!!.glMessageCard, binding!!.etMessageCard)
|
||||||
|
|
||||||
//新增
|
//新增
|
||||||
if (senderId <= 0) {
|
if (senderId <= 0) {
|
||||||
titleBar?.setSubTitle(getString(R.string.add_sender))
|
titleBar?.setSubTitle(getString(R.string.add_sender))
|
||||||
@ -145,15 +148,6 @@ class FeishuFragment : BaseFragment<FragmentSendersFeishuBinding?>(), View.OnCli
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun initListeners() {
|
override fun initListeners() {
|
||||||
binding!!.btInsertSenderToTitle.setOnClickListener(this)
|
|
||||||
binding!!.btInsertExtraToTitle.setOnClickListener(this)
|
|
||||||
binding!!.btInsertTimeToTitle.setOnClickListener(this)
|
|
||||||
binding!!.btInsertDeviceNameToTitle.setOnClickListener(this)
|
|
||||||
binding!!.btInsertSender.setOnClickListener(this)
|
|
||||||
binding!!.btInsertContent.setOnClickListener(this)
|
|
||||||
binding!!.btInsertExtra.setOnClickListener(this)
|
|
||||||
binding!!.btInsertTime.setOnClickListener(this)
|
|
||||||
binding!!.btInsertDeviceName.setOnClickListener(this)
|
|
||||||
binding!!.btnTest.setOnClickListener(this)
|
binding!!.btnTest.setOnClickListener(this)
|
||||||
binding!!.btnDel.setOnClickListener(this)
|
binding!!.btnDel.setOnClickListener(this)
|
||||||
binding!!.btnSave.setOnClickListener(this)
|
binding!!.btnSave.setOnClickListener(this)
|
||||||
@ -163,53 +157,7 @@ class FeishuFragment : BaseFragment<FragmentSendersFeishuBinding?>(), View.OnCli
|
|||||||
@SingleClick
|
@SingleClick
|
||||||
override fun onClick(v: View) {
|
override fun onClick(v: View) {
|
||||||
try {
|
try {
|
||||||
val etTitleTemplate: EditText = binding!!.etTitleTemplate
|
|
||||||
val etMessageCard: EditText = binding!!.etMessageCard
|
|
||||||
when (v.id) {
|
when (v.id) {
|
||||||
R.id.bt_insert_sender_to_title -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etTitleTemplate, getString(R.string.tag_from))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_extra_to_title -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etTitleTemplate, getString(R.string.tag_card_slot))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_time_to_title -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etTitleTemplate, getString(R.string.tag_receive_time))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_device_name_to_title -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etTitleTemplate, getString(R.string.tag_device_name))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_sender -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etMessageCard, getString(R.string.tag_from))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_content -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etMessageCard, getString(R.string.tag_sms))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_extra -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etMessageCard, getString(R.string.tag_card_slot))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_time -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etMessageCard, getString(R.string.tag_receive_time))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_device_name -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etMessageCard, getString(R.string.tag_device_name))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.btn_test -> {
|
R.id.btn_test -> {
|
||||||
mCountDownHelper?.start()
|
mCountDownHelper?.start()
|
||||||
|
@ -4,7 +4,6 @@ import android.text.TextUtils
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.EditText
|
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.idormy.sms.forwarder.R
|
import com.idormy.sms.forwarder.R
|
||||||
@ -94,6 +93,9 @@ class GotifyFragment : BaseFragment<FragmentSendersGotifyBinding?>(), View.OnCli
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
//创建标签按钮
|
||||||
|
CommonUtils.createTagButtons(requireContext(), binding!!.glTitleTemplate, binding!!.etTitleTemplate)
|
||||||
|
|
||||||
//新增
|
//新增
|
||||||
if (senderId <= 0) {
|
if (senderId <= 0) {
|
||||||
titleBar?.setSubTitle(getString(R.string.add_sender))
|
titleBar?.setSubTitle(getString(R.string.add_sender))
|
||||||
@ -132,10 +134,6 @@ class GotifyFragment : BaseFragment<FragmentSendersGotifyBinding?>(), View.OnCli
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun initListeners() {
|
override fun initListeners() {
|
||||||
binding!!.btInsertSender.setOnClickListener(this)
|
|
||||||
binding!!.btInsertExtra.setOnClickListener(this)
|
|
||||||
binding!!.btInsertTime.setOnClickListener(this)
|
|
||||||
binding!!.btInsertDeviceName.setOnClickListener(this)
|
|
||||||
binding!!.btnTest.setOnClickListener(this)
|
binding!!.btnTest.setOnClickListener(this)
|
||||||
binding!!.btnDel.setOnClickListener(this)
|
binding!!.btnDel.setOnClickListener(this)
|
||||||
binding!!.btnSave.setOnClickListener(this)
|
binding!!.btnSave.setOnClickListener(this)
|
||||||
@ -145,27 +143,7 @@ class GotifyFragment : BaseFragment<FragmentSendersGotifyBinding?>(), View.OnCli
|
|||||||
@SingleClick
|
@SingleClick
|
||||||
override fun onClick(v: View) {
|
override fun onClick(v: View) {
|
||||||
try {
|
try {
|
||||||
val etTitleTemplate: EditText = binding!!.etTitleTemplate
|
|
||||||
when (v.id) {
|
when (v.id) {
|
||||||
R.id.bt_insert_sender -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etTitleTemplate, getString(R.string.tag_from))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_extra -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etTitleTemplate, getString(R.string.tag_card_slot))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_time -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etTitleTemplate, getString(R.string.tag_receive_time))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_device_name -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etTitleTemplate, getString(R.string.tag_device_name))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.btn_test -> {
|
R.id.btn_test -> {
|
||||||
mCountDownHelper?.start()
|
mCountDownHelper?.start()
|
||||||
|
@ -4,7 +4,6 @@ import android.text.TextUtils
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.EditText
|
|
||||||
import android.widget.RadioGroup
|
import android.widget.RadioGroup
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
@ -95,6 +94,9 @@ class PushplusFragment : BaseFragment<FragmentSendersPushplusBinding?>(), View.O
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
//创建标签按钮
|
||||||
|
CommonUtils.createTagButtons(requireContext(), binding!!.glTitleTemplate, binding!!.etTitleTemplate)
|
||||||
|
|
||||||
//新增
|
//新增
|
||||||
if (senderId <= 0) {
|
if (senderId <= 0) {
|
||||||
titleBar?.setSubTitle(getString(R.string.add_sender))
|
titleBar?.setSubTitle(getString(R.string.add_sender))
|
||||||
@ -143,10 +145,6 @@ class PushplusFragment : BaseFragment<FragmentSendersPushplusBinding?>(), View.O
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun initListeners() {
|
override fun initListeners() {
|
||||||
binding!!.btInsertSender.setOnClickListener(this)
|
|
||||||
binding!!.btInsertExtra.setOnClickListener(this)
|
|
||||||
binding!!.btInsertTime.setOnClickListener(this)
|
|
||||||
binding!!.btInsertDeviceName.setOnClickListener(this)
|
|
||||||
binding!!.btnTest.setOnClickListener(this)
|
binding!!.btnTest.setOnClickListener(this)
|
||||||
binding!!.btnDel.setOnClickListener(this)
|
binding!!.btnDel.setOnClickListener(this)
|
||||||
binding!!.btnSave.setOnClickListener(this)
|
binding!!.btnSave.setOnClickListener(this)
|
||||||
@ -165,27 +163,7 @@ class PushplusFragment : BaseFragment<FragmentSendersPushplusBinding?>(), View.O
|
|||||||
@SingleClick
|
@SingleClick
|
||||||
override fun onClick(v: View) {
|
override fun onClick(v: View) {
|
||||||
try {
|
try {
|
||||||
val etTitleTemplate: EditText = binding!!.etTitleTemplate
|
|
||||||
when (v.id) {
|
when (v.id) {
|
||||||
R.id.bt_insert_sender -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etTitleTemplate, getString(R.string.tag_from))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_extra -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etTitleTemplate, getString(R.string.tag_card_slot))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_time -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etTitleTemplate, getString(R.string.tag_receive_time))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.bt_insert_device_name -> {
|
|
||||||
CommonUtils.insertOrReplaceText2Cursor(etTitleTemplate, getString(R.string.tag_device_name))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.btn_test -> {
|
R.id.btn_test -> {
|
||||||
mCountDownHelper?.start()
|
mCountDownHelper?.start()
|
||||||
|
@ -133,6 +133,7 @@ class TelegramFragment : BaseFragment<FragmentSendersTelegramBinding?>(), View.O
|
|||||||
binding!!.sbProxyAuthenticator.isChecked = settingVo.proxyAuthenticator == true
|
binding!!.sbProxyAuthenticator.isChecked = settingVo.proxyAuthenticator == true
|
||||||
binding!!.etProxyUsername.setText(settingVo.proxyUsername)
|
binding!!.etProxyUsername.setText(settingVo.proxyUsername)
|
||||||
binding!!.etProxyPassword.setText(settingVo.proxyPassword)
|
binding!!.etProxyPassword.setText(settingVo.proxyPassword)
|
||||||
|
binding!!.rgParseMode.check(settingVo.getParseModeCheckId())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -251,8 +252,13 @@ class TelegramFragment : BaseFragment<FragmentSendersTelegramBinding?>(), View.O
|
|||||||
}
|
}
|
||||||
|
|
||||||
val method = if (binding!!.rgMethod.checkedRadioButtonId == R.id.rb_method_get) "GET" else "POST"
|
val method = if (binding!!.rgMethod.checkedRadioButtonId == R.id.rb_method_get) "GET" else "POST"
|
||||||
|
val parseMode = when (binding!!.rgParseMode.checkedRadioButtonId) {
|
||||||
|
R.id.rb_parse_mode_text -> "TEXT"
|
||||||
|
R.id.rb_parse_mode_markdown -> "MarkdownV2"
|
||||||
|
else -> "HTML"
|
||||||
|
}
|
||||||
|
|
||||||
return TelegramSetting(method, apiToken, chatId, proxyType, proxyHost, proxyPort, proxyAuthenticator, proxyUsername, proxyPassword)
|
return TelegramSetting(method, apiToken, chatId, proxyType, proxyHost, proxyPort, proxyAuthenticator, proxyUsername, proxyPassword, parseMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
|
@ -4,6 +4,7 @@ import android.content.BroadcastReceiver
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.BatteryManager
|
import android.os.BatteryManager
|
||||||
|
import androidx.work.ExistingWorkPolicy
|
||||||
import androidx.work.OneTimeWorkRequestBuilder
|
import androidx.work.OneTimeWorkRequestBuilder
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
import androidx.work.workDataOf
|
import androidx.work.workDataOf
|
||||||
@ -62,16 +63,26 @@ class BatteryReceiver : BroadcastReceiver() {
|
|||||||
//充电状态改变
|
//充电状态改变
|
||||||
if (isPluggedChanged || isStatusChanged) {
|
if (isPluggedChanged || isStatusChanged) {
|
||||||
Log.d(TAG, "充电状态改变")
|
Log.d(TAG, "充电状态改变")
|
||||||
val request = OneTimeWorkRequestBuilder<BatteryWorker>().setInputData(
|
val inputData = workDataOf(
|
||||||
workDataOf(
|
|
||||||
TaskWorker.CONDITION_TYPE to TASK_CONDITION_CHARGE,
|
TaskWorker.CONDITION_TYPE to TASK_CONDITION_CHARGE,
|
||||||
"status_new" to statusNew,
|
"status_new" to statusNew,
|
||||||
"status_old" to statusOld,
|
"status_old" to statusOld,
|
||||||
"plugged_new" to pluggedNew,
|
"plugged_new" to pluggedNew,
|
||||||
"plugged_old" to pluggedOld,
|
"plugged_old" to pluggedOld,
|
||||||
)
|
)
|
||||||
).build()
|
// 使用 hashcode 生成唯一的标识符
|
||||||
WorkManager.getInstance(context).enqueue(request)
|
val inputDataHash = inputData.hashCode().toString()
|
||||||
|
// 检查是否已经存在具有相同输入数据的工作
|
||||||
|
val existingWorkPolicy = if (WorkManager.getInstance(context).getWorkInfosByTag(inputDataHash).get().isEmpty()) {
|
||||||
|
ExistingWorkPolicy.REPLACE
|
||||||
|
} else {
|
||||||
|
ExistingWorkPolicy.KEEP
|
||||||
|
}
|
||||||
|
val request = OneTimeWorkRequestBuilder<BatteryWorker>()
|
||||||
|
.setInputData(inputData)
|
||||||
|
.addTag(inputDataHash)
|
||||||
|
.build()
|
||||||
|
WorkManager.getInstance(context).enqueueUniqueWork(inputDataHash, existingWorkPolicy, request)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -36,28 +36,42 @@ class BluetoothReceiver : BroadcastReceiver() {
|
|||||||
override fun onReceive(context: Context?, intent: Intent?) {
|
override fun onReceive(context: Context?, intent: Intent?) {
|
||||||
if (context == null || intent == null) return
|
if (context == null || intent == null) return
|
||||||
|
|
||||||
when (val action = intent.action) {
|
try {
|
||||||
// 发现设备
|
when (intent.action) {
|
||||||
BluetoothDevice.ACTION_FOUND -> {
|
BluetoothDevice.ACTION_FOUND -> handleActionFound(intent)
|
||||||
val device = intent.getParcelableExtra<BluetoothDevice>(BluetoothDevice.EXTRA_DEVICE)
|
BluetoothAdapter.ACTION_DISCOVERY_FINISHED -> handleDiscoveryFinished(context)
|
||||||
device?.let {
|
BluetoothAdapter.ACTION_STATE_CHANGED -> handleStateChanged(context, intent)
|
||||||
|
BluetoothAdapter.ACTION_SCAN_MODE_CHANGED -> handleScanModeChanged()
|
||||||
|
BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED -> handleLocalNameChanged()
|
||||||
|
BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED -> handleConnectionStateChanged()
|
||||||
|
BluetoothDevice.ACTION_BOND_STATE_CHANGED -> handleBondStateChanged()
|
||||||
|
BluetoothDevice.ACTION_ACL_CONNECTED -> handleAclConnected(context, intent)
|
||||||
|
BluetoothDevice.ACTION_ACL_DISCONNECTED -> handleAclDisconnected(context, intent)
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e(TAG, "Error handling Bluetooth action: ${intent.action}", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理发现设备
|
||||||
|
private fun handleActionFound(intent: Intent) {
|
||||||
|
val device = intent.getParcelableExtra<BluetoothDevice>(BluetoothDevice.EXTRA_DEVICE) ?: return
|
||||||
if (ActivityCompat.checkSelfPermission(App.context, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) return
|
if (ActivityCompat.checkSelfPermission(App.context, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) return
|
||||||
if (SettingUtils.bluetoothIgnoreAnonymous && it.name.isNullOrEmpty()) return
|
if (SettingUtils.bluetoothIgnoreAnonymous && device.name.isNullOrEmpty()) return
|
||||||
|
|
||||||
//TODO: 实测这里一台设备会收到两次广播
|
//TODO: 实测这里一台设备会收到两次广播
|
||||||
Log.d(TAG, "Discovered device: ${it.name} - ${it.address}")
|
Log.d(TAG, "Discovered device: ${device.name} - ${device.address}")
|
||||||
val discoveredDevices = TaskUtils.discoveredDevices
|
val discoveredDevices = TaskUtils.discoveredDevices
|
||||||
discoveredDevices[it.address] = it.name ?: ""
|
discoveredDevices[device.address] = device.name ?: ""
|
||||||
TaskUtils.discoveredDevices = discoveredDevices
|
TaskUtils.discoveredDevices = discoveredDevices
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// 扫描完成
|
// 处理扫描完成
|
||||||
BluetoothAdapter.ACTION_DISCOVERY_FINISHED -> {
|
private fun handleDiscoveryFinished(context: Context) {
|
||||||
//TODO: 放在这里去判断是否已经发现某个设备(避免 ACTION_FOUND 重复广播)
|
//TODO: 放在这里去判断是否已经发现某个设备(避免 ACTION_FOUND 重复广播)
|
||||||
Log.d(TAG, "Bluetooth scan finished, discoveredDevices: ${TaskUtils.discoveredDevices}")
|
Log.d(TAG, "Bluetooth scan finished, discoveredDevices: ${TaskUtils.discoveredDevices}")
|
||||||
if (TaskUtils.discoveredDevices.isNotEmpty()) {
|
if (TaskUtils.discoveredDevices.isNotEmpty()) {
|
||||||
handleWorkRequest(context, action, Gson().toJson(TaskUtils.discoveredDevices))
|
handleWorkRequest(context, BluetoothAdapter.ACTION_DISCOVERY_FINISHED, Gson().toJson(TaskUtils.discoveredDevices))
|
||||||
}
|
}
|
||||||
|
|
||||||
restartBluetoothService(ACTION_STOP)
|
restartBluetoothService(ACTION_STOP)
|
||||||
@ -69,52 +83,49 @@ class BluetoothReceiver : BroadcastReceiver() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 蓝牙状态变化
|
// 处理蓝牙状态变化
|
||||||
BluetoothAdapter.ACTION_STATE_CHANGED -> {
|
private fun handleStateChanged(context: Context, intent: Intent) {
|
||||||
val state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR)
|
val state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR)
|
||||||
handleBluetoothStateChanged(state)
|
handleBluetoothStateChanged(state)
|
||||||
handleWorkRequest(context, action, state.toString())
|
handleWorkRequest(context, BluetoothAdapter.ACTION_STATE_CHANGED, state.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
// 蓝牙扫描模式变化
|
// 处理蓝牙扫描模式变化
|
||||||
BluetoothAdapter.ACTION_SCAN_MODE_CHANGED -> {
|
private fun handleScanModeChanged() {
|
||||||
if (SettingUtils.enableBluetooth) {
|
if (SettingUtils.enableBluetooth) {
|
||||||
restartBluetoothService()
|
restartBluetoothService()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 本地蓝牙名称变化
|
// 处理本地蓝牙名称变化
|
||||||
BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED -> {
|
private fun handleLocalNameChanged() {
|
||||||
|
// handle local name changed logic
|
||||||
}
|
}
|
||||||
|
|
||||||
// 蓝牙连接状态变化
|
// 处理蓝牙连接状态变化
|
||||||
BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED -> {
|
private fun handleConnectionStateChanged() {
|
||||||
|
// handle connection state changed logic
|
||||||
}
|
}
|
||||||
|
|
||||||
// 蓝牙设备的配对状态变化
|
// 处理蓝牙设备的配对状态变化
|
||||||
BluetoothDevice.ACTION_BOND_STATE_CHANGED -> {
|
private fun handleBondStateChanged() {
|
||||||
|
// handle bond state changed logic
|
||||||
}
|
}
|
||||||
|
|
||||||
// 蓝牙设备连接
|
// 处理蓝牙设备连接
|
||||||
BluetoothDevice.ACTION_ACL_CONNECTED -> {
|
private fun handleAclConnected(context: Context, intent: Intent) {
|
||||||
val device = intent.getParcelableExtra<BluetoothDevice>(BluetoothDevice.EXTRA_DEVICE)
|
val device = intent.getParcelableExtra<BluetoothDevice>(BluetoothDevice.EXTRA_DEVICE) ?: return
|
||||||
if (device != null) {
|
|
||||||
Log.d(TAG, "Connected device: ${device.name} - ${device.address}")
|
Log.d(TAG, "Connected device: ${device.name} - ${device.address}")
|
||||||
TaskUtils.connectedDevices[device.address] = device.name
|
TaskUtils.connectedDevices[device.address] = device.name
|
||||||
handleWorkRequest(context, action, Gson().toJson(mutableMapOf(device.address to device.name)))
|
handleWorkRequest(context, BluetoothDevice.ACTION_ACL_CONNECTED, Gson().toJson(mutableMapOf(device.address to device.name)))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 蓝牙设备断开连接
|
// 处理蓝牙设备断开连接
|
||||||
BluetoothDevice.ACTION_ACL_DISCONNECTED -> {
|
private fun handleAclDisconnected(context: Context, intent: Intent) {
|
||||||
val device = intent.getParcelableExtra<BluetoothDevice>(BluetoothDevice.EXTRA_DEVICE)
|
val device = intent.getParcelableExtra<BluetoothDevice>(BluetoothDevice.EXTRA_DEVICE) ?: return
|
||||||
if (device != null) {
|
|
||||||
Log.d(TAG, "Disconnected device: ${device.name} - ${device.address}")
|
Log.d(TAG, "Disconnected device: ${device.name} - ${device.address}")
|
||||||
TaskUtils.connectedDevices.remove(device.address)
|
TaskUtils.connectedDevices.remove(device.address)
|
||||||
handleWorkRequest(context, action, Gson().toJson(mutableMapOf(device.address to device.name)))
|
handleWorkRequest(context, BluetoothDevice.ACTION_ACL_DISCONNECTED, Gson().toJson(mutableMapOf(device.address to device.name)))
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理蓝牙状态变化
|
// 处理蓝牙状态变化
|
||||||
@ -178,6 +189,7 @@ class BluetoothReceiver : BroadcastReceiver() {
|
|||||||
App.context.startService(serviceIntent)
|
App.context.startService(serviceIntent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 发送任务请求
|
||||||
private fun handleWorkRequest(context: Context, action: String, msg: String) {
|
private fun handleWorkRequest(context: Context, action: String, msg: String) {
|
||||||
val request = OneTimeWorkRequestBuilder<BluetoothWorker>()
|
val request = OneTimeWorkRequestBuilder<BluetoothWorker>()
|
||||||
.setInputData(
|
.setInputData(
|
||||||
|
@ -36,10 +36,12 @@ import com.idormy.sms.forwarder.utils.EXTRA_UPDATE_NOTIFICATION
|
|||||||
import com.idormy.sms.forwarder.utils.FRONT_CHANNEL_ID
|
import com.idormy.sms.forwarder.utils.FRONT_CHANNEL_ID
|
||||||
import com.idormy.sms.forwarder.utils.FRONT_CHANNEL_NAME
|
import com.idormy.sms.forwarder.utils.FRONT_CHANNEL_NAME
|
||||||
import com.idormy.sms.forwarder.utils.FRONT_NOTIFY_ID
|
import com.idormy.sms.forwarder.utils.FRONT_NOTIFY_ID
|
||||||
|
import com.idormy.sms.forwarder.utils.FlashUtils
|
||||||
import com.idormy.sms.forwarder.utils.INTENT_FRPC_APPLY_FILE
|
import com.idormy.sms.forwarder.utils.INTENT_FRPC_APPLY_FILE
|
||||||
import com.idormy.sms.forwarder.utils.Log
|
import com.idormy.sms.forwarder.utils.Log
|
||||||
import com.idormy.sms.forwarder.utils.SettingUtils
|
import com.idormy.sms.forwarder.utils.SettingUtils
|
||||||
import com.idormy.sms.forwarder.utils.TASK_CONDITION_CRON
|
import com.idormy.sms.forwarder.utils.TASK_CONDITION_CRON
|
||||||
|
import com.idormy.sms.forwarder.utils.VibrationUtils
|
||||||
import com.idormy.sms.forwarder.utils.task.CronJobScheduler
|
import com.idormy.sms.forwarder.utils.task.CronJobScheduler
|
||||||
import com.idormy.sms.forwarder.workers.LoadAppListWorker
|
import com.idormy.sms.forwarder.workers.LoadAppListWorker
|
||||||
import com.jeremyliao.liveeventbus.LiveEventBus
|
import com.jeremyliao.liveeventbus.LiveEventBus
|
||||||
@ -92,13 +94,33 @@ class ForegroundService : Service() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 振动控制
|
||||||
|
private lateinit var vibrationUtils: VibrationUtils
|
||||||
|
private var isVibrating = false
|
||||||
|
|
||||||
|
// 闪光灯控制
|
||||||
|
private lateinit var flashUtils: FlashUtils
|
||||||
|
private var isFlash = false
|
||||||
|
|
||||||
|
// 音乐播放器
|
||||||
private var alarmPlayer: MediaPlayer? = null
|
private var alarmPlayer: MediaPlayer? = null
|
||||||
private var alarmPlayTimes = 0
|
private var alarmPlayTimes = 0
|
||||||
private val alarmObserver = Observer<AlarmSetting> { alarm ->
|
private val alarmObserver = Observer<AlarmSetting> { alarm ->
|
||||||
Log.d(TAG, "Received alarm: $alarm")
|
Log.d(TAG, "Received alarm: $alarm")
|
||||||
|
//停止振动
|
||||||
|
if (vibrationUtils.isVibrating) {
|
||||||
|
vibrationUtils.stopVibration()
|
||||||
|
}
|
||||||
|
//停止闪光灯
|
||||||
|
if (flashUtils.isFlashing) {
|
||||||
|
flashUtils.stopFlashing()
|
||||||
|
}
|
||||||
|
//停止播放音乐
|
||||||
alarmPlayer?.release()
|
alarmPlayer?.release()
|
||||||
alarmPlayer = null
|
alarmPlayer = null
|
||||||
if (alarm.action == "start") {
|
if (alarm.action == "start") {
|
||||||
|
//播放音乐
|
||||||
|
if (alarm.playTimes >= 0) {
|
||||||
//获取音量
|
//获取音量
|
||||||
val audioManager = getSystemService(AUDIO_SERVICE) as AudioManager
|
val audioManager = getSystemService(AUDIO_SERVICE) as AudioManager
|
||||||
val maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)
|
val maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)
|
||||||
@ -164,6 +186,17 @@ class ForegroundService : Service() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//振动提醒
|
||||||
|
if (alarm.repeatTimes >= 0) {
|
||||||
|
isVibrating = true
|
||||||
|
vibrationUtils.startVibration(alarm.vibrate, alarm.repeatTimes)
|
||||||
|
}
|
||||||
|
//闪光灯提醒
|
||||||
|
if (alarm.flashTimes >= 0) {
|
||||||
|
isFlash = true
|
||||||
|
flashUtils.startFlashing(alarm.flash, alarm.flashTimes)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@ -176,7 +209,14 @@ class ForegroundService : Service() {
|
|||||||
//纯客户端模式
|
//纯客户端模式
|
||||||
if (SettingUtils.enablePureClientMode) return
|
if (SettingUtils.enablePureClientMode) return
|
||||||
|
|
||||||
|
//创建通知渠道
|
||||||
createNotificationChannel()
|
createNotificationChannel()
|
||||||
|
|
||||||
|
//初始化振动
|
||||||
|
vibrationUtils = VibrationUtils(this)
|
||||||
|
|
||||||
|
//初始化闪光灯
|
||||||
|
flashUtils = FlashUtils(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||||
@ -212,7 +252,7 @@ class ForegroundService : Service() {
|
|||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
//非纯客户端模式
|
//非纯客户端模式
|
||||||
if (!SettingUtils.enablePureClientMode) stopForegroundService()
|
if (!SettingUtils.enablePureClientMode) stopForegroundService()
|
||||||
|
flashUtils.release()
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -292,6 +332,14 @@ class ForegroundService : Service() {
|
|||||||
isRunning = false
|
isRunning = false
|
||||||
alarmPlayer?.release()
|
alarmPlayer?.release()
|
||||||
alarmPlayer = null
|
alarmPlayer = null
|
||||||
|
//停止振动
|
||||||
|
if (vibrationUtils.isVibrating) {
|
||||||
|
vibrationUtils.stopVibration()
|
||||||
|
}
|
||||||
|
//停止闪光灯
|
||||||
|
if (flashUtils.isFlashing) {
|
||||||
|
flashUtils.stopFlashing()
|
||||||
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
handleException(e, "stopForegroundService")
|
handleException(e, "stopForegroundService")
|
||||||
}
|
}
|
||||||
|
@ -6,18 +6,29 @@ import android.content.Context
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
|
import android.os.Build
|
||||||
import android.text.SpannableString
|
import android.text.SpannableString
|
||||||
import android.text.SpannableStringBuilder
|
import android.text.SpannableStringBuilder
|
||||||
import android.text.Spanned
|
import android.text.Spanned
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import android.text.method.LinkMovementMethod
|
import android.text.method.LinkMovementMethod
|
||||||
import android.text.style.ClickableSpan
|
import android.text.style.ClickableSpan
|
||||||
|
import android.util.TypedValue
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.EditText
|
import android.widget.EditText
|
||||||
|
import android.widget.GridLayout
|
||||||
|
import android.widget.TextView
|
||||||
import androidx.annotation.ColorInt
|
import androidx.annotation.ColorInt
|
||||||
import androidx.core.app.NotificationManagerCompat
|
import androidx.core.app.NotificationManagerCompat
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import com.idormy.sms.forwarder.App
|
import com.idormy.sms.forwarder.App
|
||||||
|
import com.idormy.sms.forwarder.App.Companion.APP_TAG_MAP
|
||||||
|
import com.idormy.sms.forwarder.App.Companion.BATTERY_TAG_MAP
|
||||||
|
import com.idormy.sms.forwarder.App.Companion.CALL_TAG_MAP
|
||||||
|
import com.idormy.sms.forwarder.App.Companion.COMMON_TAG_MAP
|
||||||
|
import com.idormy.sms.forwarder.App.Companion.LOCATION_TAG_MAP
|
||||||
|
import com.idormy.sms.forwarder.App.Companion.NETWORK_TAG_MAP
|
||||||
|
import com.idormy.sms.forwarder.App.Companion.SMS_TAG_MAP
|
||||||
import com.idormy.sms.forwarder.R
|
import com.idormy.sms.forwarder.R
|
||||||
import com.idormy.sms.forwarder.core.webview.AgentWebActivity
|
import com.idormy.sms.forwarder.core.webview.AgentWebActivity
|
||||||
import com.idormy.sms.forwarder.core.webview.AgentWebFragment
|
import com.idormy.sms.forwarder.core.webview.AgentWebFragment
|
||||||
@ -35,6 +46,8 @@ import com.xuexiang.xui.widget.dialog.materialdialog.MaterialDialog.SingleButton
|
|||||||
import com.xuexiang.xui.widget.imageview.preview.PreviewBuilder
|
import com.xuexiang.xui.widget.imageview.preview.PreviewBuilder
|
||||||
import com.xuexiang.xutil.XUtil
|
import com.xuexiang.xutil.XUtil
|
||||||
import com.xuexiang.xutil.common.StringUtils
|
import com.xuexiang.xutil.common.StringUtils
|
||||||
|
import com.xuexiang.xutil.resource.ResUtils.getColor
|
||||||
|
import com.xuexiang.xutil.resource.ResUtils.getDrawable
|
||||||
import com.xuexiang.xutil.resource.ResUtils.getString
|
import com.xuexiang.xutil.resource.ResUtils.getString
|
||||||
import java.net.Inet4Address
|
import java.net.Inet4Address
|
||||||
import java.net.Inet6Address
|
import java.net.Inet6Address
|
||||||
@ -338,38 +351,73 @@ class CommonUtils private constructor() {
|
|||||||
XUtil.exitApp()
|
XUtil.exitApp()
|
||||||
}
|
}
|
||||||
|
|
||||||
/*fun switchLanguage(oldLocale: Locale, newLocale: Locale) {
|
// 动态创建标签按钮并设置点击事件(将标签插入指定输入框)
|
||||||
val oldLang = if (TAG_LANG.contains(oldLocale.toString())) oldLocale.toString() else "en"
|
fun createTagButtons(context: Context, gridLayout: GridLayout, editText: EditText, scene: String = "basic", excludeButtons: Array<String> = emptyArray()) {
|
||||||
val newLang = if (TAG_LANG.contains(newLocale.toString())) newLocale.toString() else "en"
|
// 将排除的按钮转换成一个集合,方便查找
|
||||||
Log.i(App.TAG, "switchLanguage: oldLang=$oldLang, newLang=$newLang")
|
val excludeSet = excludeButtons.toSet()
|
||||||
|
|
||||||
//替换自定义模板标签
|
// 清空GridLayout中的所有视图
|
||||||
var smsTemplate = SettingUtils.smsTemplate
|
gridLayout.removeAllViews()
|
||||||
//替换Rule.sms_template中的标签
|
|
||||||
var ruleColumn = "sms_template"
|
|
||||||
//替换Sender.json_setting中的标签
|
|
||||||
var senderColumn = "json_setting"
|
|
||||||
|
|
||||||
for (i in TAG_LIST.indices) {
|
// 根据场景动态拼接所有按钮数据
|
||||||
val oldTag = TAG_LIST[i][oldLang].toString()
|
val allButtons = when (scene) {
|
||||||
val newTag = TAG_LIST[i][newLang].toString()
|
"sms" -> SMS_TAG_MAP
|
||||||
if (oldTag == newTag) continue
|
"call" -> CALL_TAG_MAP
|
||||||
|
"app" -> APP_TAG_MAP
|
||||||
|
else -> CALL_TAG_MAP + SMS_TAG_MAP + APP_TAG_MAP
|
||||||
|
}.toMutableMap()
|
||||||
|
|
||||||
smsTemplate = smsTemplate.replace(oldTag, newTag)
|
if (SettingUtils.enableLocation) {
|
||||||
ruleColumn = "REPLACE($ruleColumn, '$oldTag', '$newTag')"
|
allButtons += LOCATION_TAG_MAP
|
||||||
senderColumn = "REPLACE($senderColumn, '$oldTag', '$newTag')"
|
}
|
||||||
|
if (scene == "all") {
|
||||||
|
allButtons += BATTERY_TAG_MAP
|
||||||
|
allButtons += NETWORK_TAG_MAP
|
||||||
|
}
|
||||||
|
allButtons += COMMON_TAG_MAP
|
||||||
|
|
||||||
|
val btnBackground = getDrawable(R.drawable.rounded_button)
|
||||||
|
val btnTextColor = getColor(android.R.color.white)
|
||||||
|
|
||||||
|
// 遍历所有按钮数据,过滤掉需要排除的按钮
|
||||||
|
allButtons.forEach { (tag, lable) ->
|
||||||
|
if (excludeSet.isNotEmpty() && excludeSet.contains(tag)) {
|
||||||
|
return@forEach
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingUtils.smsTemplate = smsTemplate
|
val button = TextView(context).apply {
|
||||||
|
text = lable
|
||||||
|
setOnClickListener {
|
||||||
|
insertOrReplaceText2Cursor(editText, tag)
|
||||||
|
}
|
||||||
|
|
||||||
val updateRuleSql = "UPDATE Rule SET sms_template = $ruleColumn WHERE sms_template != ''"
|
// 设置紧凑样式
|
||||||
Log.d(App.TAG, "updateRuleSql: $updateRuleSql")
|
setTextSize(TypedValue.COMPLEX_UNIT_SP, 9f)
|
||||||
Core.rule.replaceTags(updateRuleSql)
|
maxLines = 1
|
||||||
|
ellipsize = TextUtils.TruncateAt.END
|
||||||
|
setPadding(5, 5, 5, 5)
|
||||||
|
gravity = android.view.Gravity.CENTER
|
||||||
|
background = btnBackground
|
||||||
|
setTextColor(btnTextColor)
|
||||||
|
|
||||||
|
// 布局参数
|
||||||
|
layoutParams = GridLayout.LayoutParams().apply {
|
||||||
|
height = GridLayout.LayoutParams.WRAP_CONTENT
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
|
width = 0
|
||||||
|
columnSpec = GridLayout.spec(GridLayout.UNDEFINED, 1f)
|
||||||
|
} else {
|
||||||
|
width = GridLayout.LayoutParams.WRAP_CONTENT
|
||||||
|
}
|
||||||
|
setMargins(8, 8, 8, 8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gridLayout.addView(button)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
val updateSenderSql = "UPDATE Sender SET json_setting = $senderColumn WHERE type NOT IN (4, 5, 6, 7, 8, 14)"
|
|
||||||
Log.d(App.TAG, "updateSenderSql: $updateSenderSql")
|
|
||||||
Core.sender.replaceTags(updateSenderSql)
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
package com.idormy.sms.forwarder.utils
|
package com.idormy.sms.forwarder.utils
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import com.idormy.sms.forwarder.entity.CallInfo
|
import com.idormy.sms.forwarder.entity.CallInfo
|
||||||
import com.idormy.sms.forwarder.entity.ContactInfo
|
import com.idormy.sms.forwarder.entity.ContactInfo
|
||||||
import com.idormy.sms.forwarder.entity.SmsInfo
|
import com.idormy.sms.forwarder.entity.SmsInfo
|
||||||
import com.xuexiang.xaop.annotation.MemoryCache
|
import com.xuexiang.xaop.annotation.MemoryCache
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.Calendar
|
||||||
|
import java.util.Date
|
||||||
|
|
||||||
@Suppress("SameParameterValue")
|
@Suppress("SameParameterValue")
|
||||||
object DataProvider {
|
object DataProvider {
|
||||||
@ -71,4 +75,45 @@ object DataProvider {
|
|||||||
}
|
}
|
||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断当前时间是否在时间段内
|
||||||
|
*/
|
||||||
|
@SuppressLint("SimpleDateFormat")
|
||||||
|
fun isCurrentTimeInPeriod(periodStartIndex: Int, periodEndIndex: Int): Boolean {
|
||||||
|
val periodStartStr = timePeriodOption[periodStartIndex]
|
||||||
|
val periodEndStr = timePeriodOption[periodEndIndex]
|
||||||
|
|
||||||
|
// 定义时间格式
|
||||||
|
val formatter = SimpleDateFormat("HH:mm")
|
||||||
|
|
||||||
|
// 解析时间字符串
|
||||||
|
val periodStart = Calendar.getInstance().apply {
|
||||||
|
time = formatter.parse(periodStartStr) as Date
|
||||||
|
set(Calendar.SECOND, 0)
|
||||||
|
set(Calendar.MILLISECOND, 0)
|
||||||
|
}
|
||||||
|
val periodEnd = Calendar.getInstance().apply {
|
||||||
|
time = formatter.parse(periodEndStr) as Date
|
||||||
|
set(Calendar.SECOND, 0)
|
||||||
|
set(Calendar.MILLISECOND, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前时间
|
||||||
|
val currentTime = Calendar.getInstance()
|
||||||
|
val currentHour = currentTime.get(Calendar.HOUR_OF_DAY)
|
||||||
|
val currentMinute = currentTime.get(Calendar.MINUTE)
|
||||||
|
|
||||||
|
// 判断是否跨天
|
||||||
|
return if (periodEnd.before(periodStart)) {
|
||||||
|
// 跨天的情况
|
||||||
|
(currentHour > periodStart.get(Calendar.HOUR_OF_DAY) || (currentHour == periodStart.get(Calendar.HOUR_OF_DAY) && currentMinute >= periodStart.get(Calendar.MINUTE))) ||
|
||||||
|
(currentHour < periodEnd.get(Calendar.HOUR_OF_DAY) || (currentHour == periodEnd.get(Calendar.HOUR_OF_DAY) && currentMinute < periodEnd.get(Calendar.MINUTE)))
|
||||||
|
} else {
|
||||||
|
// 不跨天的情况
|
||||||
|
(currentHour > periodStart.get(Calendar.HOUR_OF_DAY) || (currentHour == periodStart.get(Calendar.HOUR_OF_DAY) && currentMinute >= periodStart.get(Calendar.MINUTE))) &&
|
||||||
|
(currentHour < periodEnd.get(Calendar.HOUR_OF_DAY) || (currentHour == periodEnd.get(Calendar.HOUR_OF_DAY) && currentMinute < periodEnd.get(Calendar.MINUTE)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
116
app/src/main/java/com/idormy/sms/forwarder/utils/FlashUtils.kt
Normal file
116
app/src/main/java/com/idormy/sms/forwarder/utils/FlashUtils.kt
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
@file:Suppress("DEPRECATION")
|
||||||
|
|
||||||
|
package com.idormy.sms.forwarder.utils
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.hardware.Camera
|
||||||
|
import android.hardware.camera2.CameraAccessException
|
||||||
|
import android.hardware.camera2.CameraManager
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
|
|
||||||
|
class FlashUtils(context: Context) {
|
||||||
|
private var cameraManager: CameraManager? = null
|
||||||
|
private var cameraId: String? = null
|
||||||
|
private var legacyCamera: Camera? = null
|
||||||
|
private var legacyParams: Camera.Parameters? = null
|
||||||
|
private var handler: Handler? = null
|
||||||
|
private val duration = 100L // 闪烁持续时间
|
||||||
|
var isFlashing = false
|
||||||
|
private set
|
||||||
|
|
||||||
|
init {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
cameraManager = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager
|
||||||
|
try {
|
||||||
|
cameraId = cameraManager?.cameraIdList?.get(0) // 获取后置摄像头 ID
|
||||||
|
} catch (e: CameraAccessException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
legacyCamera = Camera.open()
|
||||||
|
legacyParams = legacyCamera?.parameters
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按照模式控制闪光灯
|
||||||
|
* @param pattern 例如 "XXOOXXOO" (X-开,O-关)
|
||||||
|
* @param repeatTimes 闪烁的重复次数,0 表示无限循环
|
||||||
|
*/
|
||||||
|
fun startFlashing(pattern: String, repeatTimes: Int) {
|
||||||
|
if (isFlashing) return
|
||||||
|
isFlashing = true
|
||||||
|
handler = Handler(Looper.getMainLooper())
|
||||||
|
|
||||||
|
val sequence = pattern.toCharArray()
|
||||||
|
var index = 0
|
||||||
|
var repeatCount = 0
|
||||||
|
|
||||||
|
val runnable = object : Runnable {
|
||||||
|
override fun run() {
|
||||||
|
if (!isFlashing) return
|
||||||
|
|
||||||
|
val shouldFlash = sequence[index] == 'X' || sequence[index] == '1'
|
||||||
|
setFlashlight(shouldFlash)
|
||||||
|
index++
|
||||||
|
|
||||||
|
if (index >= sequence.size) {
|
||||||
|
index = 0
|
||||||
|
repeatCount++
|
||||||
|
if (repeatTimes != 0 && repeatCount >= repeatTimes) {
|
||||||
|
stopFlashing()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handler?.postDelayed(this, duration)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handler?.post(runnable)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭闪光灯并停止模式
|
||||||
|
*/
|
||||||
|
fun stopFlashing() {
|
||||||
|
isFlashing = false
|
||||||
|
handler?.removeCallbacksAndMessages(null)
|
||||||
|
setFlashlight(false) // 确保停止后灯是关闭的
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置闪光灯状态,兼容 Android 4.4+
|
||||||
|
*/
|
||||||
|
private fun setFlashlight(enable: Boolean) {
|
||||||
|
try {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
cameraManager?.setTorchMode(cameraId!!, enable)
|
||||||
|
} else {
|
||||||
|
legacyParams?.flashMode = if (enable) Camera.Parameters.FLASH_MODE_TORCH else Camera.Parameters.FLASH_MODE_OFF
|
||||||
|
legacyCamera?.parameters = legacyParams
|
||||||
|
if (enable) legacyCamera?.startPreview() else legacyCamera?.stopPreview()
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 释放旧 API 资源
|
||||||
|
*/
|
||||||
|
fun release() {
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
||||||
|
legacyCamera?.stopPreview()
|
||||||
|
legacyCamera?.release()
|
||||||
|
legacyCamera = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -14,6 +14,7 @@ import android.provider.Settings
|
|||||||
import android.telephony.SmsManager
|
import android.telephony.SmsManager
|
||||||
import android.telephony.SubscriptionInfo
|
import android.telephony.SubscriptionInfo
|
||||||
import android.telephony.SubscriptionManager
|
import android.telephony.SubscriptionManager
|
||||||
|
import android.telephony.TelephonyManager
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import androidx.annotation.RequiresPermission
|
import androidx.annotation.RequiresPermission
|
||||||
import androidx.core.app.ActivityCompat
|
import androidx.core.app.ActivityCompat
|
||||||
@ -28,8 +29,16 @@ import com.xuexiang.xutil.XUtil
|
|||||||
import com.xuexiang.xutil.app.IntentUtils
|
import com.xuexiang.xutil.app.IntentUtils
|
||||||
import com.xuexiang.xutil.data.DateUtils
|
import com.xuexiang.xutil.data.DateUtils
|
||||||
import com.xuexiang.xutil.resource.ResUtils.getString
|
import com.xuexiang.xutil.resource.ResUtils.getString
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
import okhttp3.Request
|
||||||
|
import org.json.JSONObject
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
import kotlin.math.min
|
||||||
|
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
class PhoneUtils private constructor() {
|
class PhoneUtils private constructor() {
|
||||||
@ -37,6 +46,14 @@ class PhoneUtils private constructor() {
|
|||||||
companion object {
|
companion object {
|
||||||
const val TAG = "PhoneUtils"
|
const val TAG = "PhoneUtils"
|
||||||
|
|
||||||
|
/** 获取 sim 卡槽数量,注意不是 sim 卡的数量。*/
|
||||||
|
fun getSimSlotCount() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
|
||||||
|
(App.context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager).activeModemCount
|
||||||
|
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
|
||||||
|
(App.context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager).phoneCount
|
||||||
|
else
|
||||||
|
-1
|
||||||
|
|
||||||
//获取多卡信息
|
//获取多卡信息
|
||||||
@SuppressLint("Range")
|
@SuppressLint("Range")
|
||||||
fun getSimMultiInfo(): MutableMap<Int, SimInfo> {
|
fun getSimMultiInfo(): MutableMap<Int, SimInfo> {
|
||||||
@ -330,7 +347,7 @@ class PhoneUtils private constructor() {
|
|||||||
|
|
||||||
//获取联系人列表
|
//获取联系人列表
|
||||||
fun getContactInfoList(
|
fun getContactInfoList(
|
||||||
limit: Int, offset: Int, phoneNumber: String?, name: String?
|
limit: Int, offset: Int, phoneNumber: String?, name: String?, isFuzzy: Boolean = true
|
||||||
): MutableList<ContactInfo> {
|
): MutableList<ContactInfo> {
|
||||||
val contactInfoList: MutableList<ContactInfo> = mutableListOf()
|
val contactInfoList: MutableList<ContactInfo> = mutableListOf()
|
||||||
|
|
||||||
@ -339,7 +356,11 @@ class PhoneUtils private constructor() {
|
|||||||
val selectionArgs = ArrayList<String>()
|
val selectionArgs = ArrayList<String>()
|
||||||
if (!TextUtils.isEmpty(phoneNumber)) {
|
if (!TextUtils.isEmpty(phoneNumber)) {
|
||||||
selection += " and replace(replace(" + ContactsContract.CommonDataKinds.Phone.NUMBER + ",' ',''),'-','') like ?"
|
selection += " and replace(replace(" + ContactsContract.CommonDataKinds.Phone.NUMBER + ",' ',''),'-','') like ?"
|
||||||
|
if (isFuzzy) {
|
||||||
selectionArgs.add("%$phoneNumber%")
|
selectionArgs.add("%$phoneNumber%")
|
||||||
|
} else {
|
||||||
|
selectionArgs.add("%$phoneNumber")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!TextUtils.isEmpty(name)) {
|
if (!TextUtils.isEmpty(name)) {
|
||||||
selection += " and " + ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " like ?"
|
selection += " and " + ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " like ?"
|
||||||
@ -383,11 +404,100 @@ class PhoneUtils private constructor() {
|
|||||||
return contactInfoList
|
return contactInfoList
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取号码归属地
|
||||||
|
fun getPhoneArea(phoneNumber: String): String {
|
||||||
|
val client = OkHttpClient()
|
||||||
|
val url = "https://cx.shouji.360.cn/phonearea.php?number=$phoneNumber"
|
||||||
|
val request = Request.Builder().url(url).build()
|
||||||
|
|
||||||
|
var result = getString(R.string.unknown_area) // 默认值
|
||||||
|
|
||||||
|
// 使用协程来执行网络请求
|
||||||
|
runBlocking {
|
||||||
|
val job = CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
try {
|
||||||
|
val response = client.newCall(request).execute()
|
||||||
|
if (response.isSuccessful) {
|
||||||
|
val responseData = response.body()?.string()
|
||||||
|
Log.i(TAG, "getPhoneArea: $responseData")
|
||||||
|
if (responseData != null) {
|
||||||
|
val jsonObject = JSONObject(responseData)
|
||||||
|
val data = jsonObject.getJSONObject("data")
|
||||||
|
val province = data.getString("province")
|
||||||
|
val city = data.getString("city")
|
||||||
|
val sp = data.getString("sp")
|
||||||
|
result = "$province $city $sp"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
job.join() // 等待协程执行完毕
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
//获取联系人姓名
|
//获取联系人姓名
|
||||||
fun getContactByNumber(phoneNumber: String?): MutableList<ContactInfo> {
|
fun getContactByNumber(phoneNumber: String?): MutableList<ContactInfo> {
|
||||||
val contactInfoList = mutableListOf<ContactInfo>()
|
val contactInfoList = mutableListOf<ContactInfo>()
|
||||||
if (TextUtils.isEmpty(phoneNumber)) return contactInfoList
|
if (TextUtils.isEmpty(phoneNumber)) return contactInfoList
|
||||||
return getContactInfoList(1, 0, phoneNumber, null)
|
|
||||||
|
// 去除国际区号、空格、括号、横线等字符
|
||||||
|
val normalizedInputNumber = if (phoneNumber!!.startsWith("+") && phoneNumber.length > 4) {
|
||||||
|
phoneNumber.substring(4).replace("[^0-9]".toRegex(), "")
|
||||||
|
} else {
|
||||||
|
phoneNumber.replace("[^0-9]".toRegex(), "")
|
||||||
|
}
|
||||||
|
|
||||||
|
contactInfoList.addAll(getContactInfoList(99, 0, normalizedInputNumber, null, false))
|
||||||
|
if (contactInfoList.isEmpty() || contactInfoList.size == 1) {
|
||||||
|
return contactInfoList
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算每个联系人的匹配长度和优先级
|
||||||
|
val scoredContacts = contactInfoList.map { contact ->
|
||||||
|
//去除空格、括号、横线等字符
|
||||||
|
val normalizedContactNumber = contact.phoneNumber.replace("[^0-9]".toRegex(), "")
|
||||||
|
val matchLength = calculateMatchLength(normalizedInputNumber, normalizedContactNumber)
|
||||||
|
// 优先级规则:
|
||||||
|
// 1. 完全匹配(输入手机号与联系人手机号完全一致):优先级 2
|
||||||
|
// 2. 匹配长度等于输入手机号长度:优先级 1
|
||||||
|
// 3. 其他情况:优先级 0
|
||||||
|
val priority = when {
|
||||||
|
normalizedInputNumber == normalizedContactNumber -> 2
|
||||||
|
matchLength == normalizedInputNumber.length -> 1
|
||||||
|
else -> 0
|
||||||
|
}
|
||||||
|
contact to Pair(matchLength, priority)
|
||||||
|
}.sortedWith(compareByDescending<Pair<ContactInfo, Pair<Int, Int>>> { it.second.first } // 按匹配长度降序
|
||||||
|
.thenByDescending { it.second.second }) // 按优先级降序
|
||||||
|
|
||||||
|
// 返回匹配长度最长且优先级最高的联系人列表
|
||||||
|
val maxMatchLength = scoredContacts.first().second.first
|
||||||
|
val maxPriority = scoredContacts.first().second.second
|
||||||
|
return scoredContacts
|
||||||
|
.filter { it.second.first == maxMatchLength && it.second.second == maxPriority }
|
||||||
|
.map { it.first }
|
||||||
|
.toMutableList()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算从右向左的匹配长度
|
||||||
|
private fun calculateMatchLength(number1: String, number2: String): Int {
|
||||||
|
var matchLength = 0
|
||||||
|
val minLength = min(number1.length, number2.length)
|
||||||
|
|
||||||
|
// 从右向左逐位比较
|
||||||
|
for (i in 1..minLength) {
|
||||||
|
if (number1[number1.length - i] == number2[number2.length - i]) {
|
||||||
|
matchLength++
|
||||||
|
} else {
|
||||||
|
break // 遇到不匹配的字符,停止比较
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return matchLength
|
||||||
}
|
}
|
||||||
|
|
||||||
//获取通话记录转发内容
|
//获取通话记录转发内容
|
||||||
|
@ -119,45 +119,46 @@ class RuleLine(line: String, lineNum: Int, beforeRuleLine: RuleLine?) {
|
|||||||
|
|
||||||
//内容分支
|
//内容分支
|
||||||
private fun checkValue(msgValue: String?): Boolean {
|
private fun checkValue(msgValue: String?): Boolean {
|
||||||
var checked = false
|
if (msgValue == null) return false
|
||||||
when (check) {
|
|
||||||
CHECK_EQUALS -> checked = value == msgValue
|
|
||||||
CHECK_CONTAIN -> if (msgValue != null) {
|
|
||||||
checked = msgValue.contains(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
CHECK_NOT_CONTAIN -> if (msgValue != null) {
|
fun evaluateCondition(condition: String): Boolean {
|
||||||
checked = !msgValue.contains(value)
|
return when (check) {
|
||||||
}
|
CHECK_EQUALS -> msgValue == condition
|
||||||
|
CHECK_CONTAIN -> msgValue.contains(condition)
|
||||||
CHECK_START_WITH -> if (msgValue != null) {
|
CHECK_NOT_CONTAIN -> !msgValue.contains(condition)
|
||||||
checked = msgValue.startsWith(value)
|
CHECK_START_WITH -> msgValue.startsWith(condition)
|
||||||
}
|
CHECK_END_WITH -> msgValue.endsWith(condition)
|
||||||
|
CHECK_REGEX -> try {
|
||||||
CHECK_END_WITH -> if (msgValue != null) {
|
val pattern = Pattern.compile(condition, Pattern.CASE_INSENSITIVE)
|
||||||
checked = msgValue.endsWith(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
CHECK_REGEX -> if (msgValue != null) {
|
|
||||||
try {
|
|
||||||
//checked = Pattern.matches(this.value, msgValue);
|
|
||||||
val pattern = Pattern.compile(value, Pattern.CASE_INSENSITIVE)
|
|
||||||
val matcher = pattern.matcher(msgValue)
|
val matcher = pattern.matcher(msgValue)
|
||||||
while (matcher.find()) {
|
matcher.find()
|
||||||
checked = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
} catch (e: PatternSyntaxException) {
|
} catch (e: PatternSyntaxException) {
|
||||||
logg("PatternSyntaxException: ")
|
logg("PatternSyntaxException: ${e.description}, Index: ${e.index}, Message: ${e.message}, Pattern: ${e.pattern}")
|
||||||
logg("Description: " + e.description)
|
false
|
||||||
logg("Index: " + e.index)
|
}
|
||||||
logg("Message: " + e.message)
|
|
||||||
logg("Pattern: " + e.pattern)
|
else -> false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {}
|
fun parseAndEvaluate(expression: String): Boolean {
|
||||||
|
// Split by "||" and evaluate each segment joined by "&&"
|
||||||
|
val orGroups = expression.split("||")
|
||||||
|
return orGroups.any { orGroup ->
|
||||||
|
val andGroups = orGroup.split("&&")
|
||||||
|
andGroups.all { andGroup ->
|
||||||
|
val trimmedCondition = andGroup.trim()
|
||||||
|
evaluateCondition(trimmedCondition)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val checked = if (value.contains("&&") || value.contains("||")) {
|
||||||
|
parseAndEvaluate(value)
|
||||||
|
} else {
|
||||||
|
evaluateCondition(value)
|
||||||
|
}
|
||||||
|
|
||||||
logg("checkValue $msgValue $check $value checked:$checked")
|
logg("checkValue $msgValue $check $value checked:$checked")
|
||||||
return checked
|
return checked
|
||||||
}
|
}
|
||||||
|
@ -49,10 +49,7 @@ import com.idormy.sms.forwarder.workers.UpdateLogsWorker
|
|||||||
import com.jeremyliao.liveeventbus.LiveEventBus
|
import com.jeremyliao.liveeventbus.LiveEventBus
|
||||||
import com.xuexiang.xutil.XUtil
|
import com.xuexiang.xutil.XUtil
|
||||||
import com.xuexiang.xutil.resource.ResUtils.getString
|
import com.xuexiang.xutil.resource.ResUtils.getString
|
||||||
import java.text.ParsePosition
|
|
||||||
import java.text.SimpleDateFormat
|
|
||||||
import java.util.Calendar
|
import java.util.Calendar
|
||||||
import java.util.Date
|
|
||||||
|
|
||||||
object SendUtils {
|
object SendUtils {
|
||||||
private const val TAG = "SendUtils"
|
private const val TAG = "SendUtils"
|
||||||
@ -101,29 +98,24 @@ object SendUtils {
|
|||||||
senderLogic(0, msgInfo, rule, senderIndex, msgId)
|
senderLogic(0, msgInfo, rule, senderIndex, msgId)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
//免打扰(禁用转发)时间段
|
//免打扰(禁用转发)日期段
|
||||||
if (rule.silentPeriodStart != rule.silentPeriodEnd) {
|
Log.d(TAG, "silentDayOfWeek = ${rule.silentDayOfWeek}")
|
||||||
val periodStartDay = Date()
|
val silentDayOfWeek = rule.silentDayOfWeek.split(",").filter { it.isNotEmpty() }.map { it.toInt() }
|
||||||
var periodStartEnd = Date()
|
if (silentDayOfWeek.isNotEmpty()) {
|
||||||
//跨天了
|
val dayOfWeek = Calendar.getInstance().get(Calendar.DAY_OF_WEEK)
|
||||||
if (rule.silentPeriodStart > rule.silentPeriodEnd) {
|
if (silentDayOfWeek.contains(dayOfWeek)) {
|
||||||
val c: Calendar = Calendar.getInstance()
|
Log.d(TAG, "免打扰(禁用转发)日期段")
|
||||||
c.time = periodStartEnd
|
updateLogs(logId, 0, getString(R.string.silent_time_period))
|
||||||
c.add(Calendar.DAY_OF_MONTH, 1)
|
senderLogic(0, msgInfo, rule, senderIndex, msgId)
|
||||||
periodStartEnd = c.time
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val dateFmt = SimpleDateFormat("yyyy-MM-dd")
|
//免打扰(禁用转发)时间段
|
||||||
val mTimeOption = DataProvider.timePeriodOption
|
Log.d(TAG, "silentPeriodStart = ${rule.silentPeriodStart}, silentPeriodEnd = ${rule.silentPeriodEnd}")
|
||||||
val periodStartStr = dateFmt.format(periodStartDay) + " " + mTimeOption[rule.silentPeriodStart] + ":00"
|
if (rule.silentPeriodStart != rule.silentPeriodEnd) {
|
||||||
val periodEndStr = dateFmt.format(periodStartEnd) + " " + mTimeOption[rule.silentPeriodEnd] + ":00"
|
val isSilentPeriod = DataProvider.isCurrentTimeInPeriod(rule.silentPeriodStart, rule.silentPeriodEnd)
|
||||||
|
if (isSilentPeriod) {
|
||||||
val timeFmt = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
|
|
||||||
val periodStart = timeFmt.parse(periodStartStr, ParsePosition(0))?.time
|
|
||||||
val periodEnd = timeFmt.parse(periodEndStr, ParsePosition(0))?.time
|
|
||||||
|
|
||||||
val now = System.currentTimeMillis()
|
|
||||||
if (periodStart != null && periodEnd != null && now in periodStart..periodEnd) {
|
|
||||||
Log.d(TAG, "免打扰(禁用转发)时间段")
|
Log.d(TAG, "免打扰(禁用转发)时间段")
|
||||||
updateLogs(logId, 0, getString(R.string.silent_time_period))
|
updateLogs(logId, 0, getString(R.string.silent_time_period))
|
||||||
senderLogic(0, msgInfo, rule, senderIndex, msgId)
|
senderLogic(0, msgInfo, rule, senderIndex, msgId)
|
||||||
|
@ -80,7 +80,7 @@ class SettingUtils private constructor() {
|
|||||||
//是否不在最近任务列表中显示
|
//是否不在最近任务列表中显示
|
||||||
var enableExcludeFromRecents: Boolean by SharedPreference(SP_ENABLE_EXCLUDE_FROM_RECENTS, false)
|
var enableExcludeFromRecents: Boolean by SharedPreference(SP_ENABLE_EXCLUDE_FROM_RECENTS, false)
|
||||||
|
|
||||||
//是否转发应用通知
|
//是否启用Cactus增强保活措施
|
||||||
var enableCactus: Boolean by SharedPreference(SP_ENABLE_CACTUS, false)
|
var enableCactus: Boolean by SharedPreference(SP_ENABLE_CACTUS, false)
|
||||||
|
|
||||||
//是否播放静音音乐
|
//是否播放静音音乐
|
||||||
|
@ -0,0 +1,88 @@
|
|||||||
|
package com.idormy.sms.forwarder.utils
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
|
import android.os.VibrationEffect
|
||||||
|
import android.os.Vibrator
|
||||||
|
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
class VibrationUtils(context: Context) {
|
||||||
|
|
||||||
|
private val vibrator = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
|
||||||
|
private val handler = Handler(Looper.getMainLooper())
|
||||||
|
private var currentRepeat = 0
|
||||||
|
var isVibrating = false
|
||||||
|
private set
|
||||||
|
|
||||||
|
fun startVibration(patternString: String, repeatTimes: Int) {
|
||||||
|
isVibrating = true
|
||||||
|
currentRepeat = 0
|
||||||
|
val parsedPattern = parsePattern(patternString)
|
||||||
|
vibratePattern(parsedPattern, 0, repeatTimes)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun stopVibration() {
|
||||||
|
isVibrating = false
|
||||||
|
vibrator.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun parsePattern(pattern: String): List<Triple<Long, Boolean, Int>> {
|
||||||
|
val parsedPattern = mutableListOf<Triple<Long, Boolean, Int>>()
|
||||||
|
var currentChar = pattern[0]
|
||||||
|
var currentLength = 1L
|
||||||
|
|
||||||
|
for (i in 1 until pattern.length) {
|
||||||
|
if (pattern[i] == currentChar) {
|
||||||
|
currentLength++
|
||||||
|
} else {
|
||||||
|
parsedPattern.add(createTriple(currentChar, currentLength))
|
||||||
|
currentChar = pattern[i]
|
||||||
|
currentLength = 1L
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parsedPattern.add(createTriple(currentChar, currentLength))
|
||||||
|
return parsedPattern
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createTriple(char: Char, length: Long): Triple<Long, Boolean, Int> {
|
||||||
|
val duration = 100L * length
|
||||||
|
val intensity = when (char) {
|
||||||
|
'=' -> 255
|
||||||
|
'-' -> 128
|
||||||
|
'_' -> 0
|
||||||
|
else -> 0
|
||||||
|
}
|
||||||
|
return Triple(duration, intensity > 0, intensity)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun vibratePattern(parsedPattern: List<Triple<Long, Boolean, Int>>, index: Int, repeatTimes: Int) {
|
||||||
|
if (isVibrating && index < parsedPattern.size) {
|
||||||
|
val (duration, shouldVibrate, intensity) = parsedPattern[index]
|
||||||
|
if (shouldVibrate) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
val effect = VibrationEffect.createOneShot(duration, intensity)
|
||||||
|
vibrator.vibrate(effect)
|
||||||
|
} else {
|
||||||
|
vibrator.vibrate(duration)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
handler.postDelayed({
|
||||||
|
if (isVibrating) {
|
||||||
|
vibrator.cancel()
|
||||||
|
if (index + 1 < parsedPattern.size) {
|
||||||
|
vibratePattern(parsedPattern, index + 1, repeatTimes)
|
||||||
|
} else {
|
||||||
|
currentRepeat++
|
||||||
|
if (repeatTimes == 0 || currentRepeat < repeatTimes) {
|
||||||
|
vibratePattern(parsedPattern, 0, repeatTimes) // Restart pattern
|
||||||
|
} else {
|
||||||
|
stopVibration()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, duration)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,14 +3,16 @@ package com.idormy.sms.forwarder.utils.mail
|
|||||||
import android.text.Html
|
import android.text.Html
|
||||||
import android.text.Spanned
|
import android.text.Spanned
|
||||||
import com.idormy.sms.forwarder.utils.Log
|
import com.idormy.sms.forwarder.utils.Log
|
||||||
|
import com.sun.mail.util.MailSSLSocketFactory
|
||||||
|
import jakarta.mail.Authenticator
|
||||||
|
import jakarta.mail.PasswordAuthentication
|
||||||
import org.bouncycastle.openpgp.PGPPublicKeyRing
|
import org.bouncycastle.openpgp.PGPPublicKeyRing
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRing
|
import org.bouncycastle.openpgp.PGPSecretKeyRing
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.security.PrivateKey
|
import java.security.PrivateKey
|
||||||
import java.security.cert.X509Certificate
|
import java.security.cert.X509Certificate
|
||||||
import java.util.Properties
|
import java.util.Properties
|
||||||
import javax.mail.Authenticator
|
|
||||||
import javax.mail.PasswordAuthentication
|
|
||||||
|
|
||||||
@Suppress("PrivatePropertyName", "DEPRECATION")
|
@Suppress("PrivatePropertyName", "DEPRECATION")
|
||||||
class EmailSender(
|
class EmailSender(
|
||||||
@ -32,7 +34,6 @@ class EmailSender(
|
|||||||
private val listener: EmailTaskListener? = null,
|
private val listener: EmailTaskListener? = null,
|
||||||
// 安全选项
|
// 安全选项
|
||||||
private val openSSL: Boolean = false, //是否开启ssl验证 默认关闭
|
private val openSSL: Boolean = false, //是否开启ssl验证 默认关闭
|
||||||
private val sslFactory: String = "javax.net.ssl.SSLSocketFactory", //SSL构建类名
|
|
||||||
private val startTls: Boolean = false, //是否开启starttls加密方式 默认关闭
|
private val startTls: Boolean = false, //是否开启starttls加密方式 默认关闭
|
||||||
// 邮件加密方式: S/MIME、OpenPGP、Plain(不传证书)
|
// 邮件加密方式: S/MIME、OpenPGP、Plain(不传证书)
|
||||||
private val encryptionProtocol: String = "S/MIME",
|
private val encryptionProtocol: String = "S/MIME",
|
||||||
@ -58,7 +59,11 @@ class EmailSender(
|
|||||||
// 设置是否启用 SSL 连接
|
// 设置是否启用 SSL 连接
|
||||||
if (openSSL) {
|
if (openSSL) {
|
||||||
put("mail.smtp.ssl.enable", "true")
|
put("mail.smtp.ssl.enable", "true")
|
||||||
put("mail.smtp.socketFactory.class", sslFactory)
|
// 使用 TLSv1.2 协议 & 信任所有主机
|
||||||
|
val sf = MailSSLSocketFactory("TLSv1.2")
|
||||||
|
sf.setTrustedHosts("*")
|
||||||
|
put("mail.smtp.ssl.socketFactory", sf)
|
||||||
|
put("mail.smtp.ssl.protocols", "TLSv1.2")
|
||||||
}
|
}
|
||||||
// 设置是否启用 TLS 连接
|
// 设置是否启用 TLS 连接
|
||||||
if (startTls) {
|
if (startTls) {
|
||||||
|
@ -1,6 +1,18 @@
|
|||||||
package com.idormy.sms.forwarder.utils.mail
|
package com.idormy.sms.forwarder.utils.mail
|
||||||
|
|
||||||
import com.idormy.sms.forwarder.utils.Log
|
import com.idormy.sms.forwarder.utils.Log
|
||||||
|
import jakarta.activation.DataHandler
|
||||||
|
import jakarta.activation.FileDataSource
|
||||||
|
import jakarta.mail.Authenticator
|
||||||
|
import jakarta.mail.Message
|
||||||
|
import jakarta.mail.Session
|
||||||
|
import jakarta.mail.Transport
|
||||||
|
import jakarta.mail.internet.InternetAddress
|
||||||
|
import jakarta.mail.internet.MimeBodyPart
|
||||||
|
import jakarta.mail.internet.MimeMessage
|
||||||
|
import jakarta.mail.internet.MimeMultipart
|
||||||
|
import jakarta.mail.internet.MimeUtility
|
||||||
|
import jakarta.mail.util.ByteArrayDataSource
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import org.bouncycastle.jce.provider.BouncyCastleProvider
|
import org.bouncycastle.jce.provider.BouncyCastleProvider
|
||||||
@ -22,18 +34,6 @@ import java.io.InputStream
|
|||||||
import java.security.Security
|
import java.security.Security
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
import java.util.Properties
|
import java.util.Properties
|
||||||
import javax.activation.DataHandler
|
|
||||||
import javax.activation.FileDataSource
|
|
||||||
import javax.mail.Authenticator
|
|
||||||
import javax.mail.Message
|
|
||||||
import javax.mail.Session
|
|
||||||
import javax.mail.Transport
|
|
||||||
import javax.mail.internet.InternetAddress
|
|
||||||
import javax.mail.internet.MimeBodyPart
|
|
||||||
import javax.mail.internet.MimeMessage
|
|
||||||
import javax.mail.internet.MimeMultipart
|
|
||||||
import javax.mail.internet.MimeUtility
|
|
||||||
import javax.mail.util.ByteArrayDataSource
|
|
||||||
|
|
||||||
|
|
||||||
@Suppress("PrivatePropertyName")
|
@Suppress("PrivatePropertyName")
|
||||||
@ -244,4 +244,3 @@ class PgpUtils(
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,17 @@
|
|||||||
package com.idormy.sms.forwarder.utils.mail
|
package com.idormy.sms.forwarder.utils.mail
|
||||||
|
|
||||||
import com.idormy.sms.forwarder.utils.Log
|
import com.idormy.sms.forwarder.utils.Log
|
||||||
|
import jakarta.activation.DataHandler
|
||||||
|
import jakarta.activation.FileDataSource
|
||||||
|
import jakarta.mail.Authenticator
|
||||||
|
import jakarta.mail.Message
|
||||||
|
import jakarta.mail.Session
|
||||||
|
import jakarta.mail.Transport
|
||||||
|
import jakarta.mail.internet.InternetAddress
|
||||||
|
import jakarta.mail.internet.MimeBodyPart
|
||||||
|
import jakarta.mail.internet.MimeMessage
|
||||||
|
import jakarta.mail.internet.MimeMultipart
|
||||||
|
import jakarta.mail.internet.MimeUtility
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import org.bouncycastle.cert.jcajce.JcaCertStore
|
import org.bouncycastle.cert.jcajce.JcaCertStore
|
||||||
@ -24,17 +35,7 @@ import java.security.Security
|
|||||||
import java.security.cert.X509Certificate
|
import java.security.cert.X509Certificate
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
import java.util.Properties
|
import java.util.Properties
|
||||||
import javax.activation.DataHandler
|
|
||||||
import javax.activation.FileDataSource
|
|
||||||
import javax.mail.Authenticator
|
|
||||||
import javax.mail.Message
|
|
||||||
import javax.mail.Session
|
|
||||||
import javax.mail.Transport
|
|
||||||
import javax.mail.internet.InternetAddress
|
|
||||||
import javax.mail.internet.MimeBodyPart
|
|
||||||
import javax.mail.internet.MimeMessage
|
|
||||||
import javax.mail.internet.MimeMultipart
|
|
||||||
import javax.mail.internet.MimeUtility
|
|
||||||
|
|
||||||
@Suppress("PrivatePropertyName")
|
@Suppress("PrivatePropertyName")
|
||||||
class SmimeUtils(
|
class SmimeUtils(
|
||||||
|
@ -67,18 +67,28 @@ class BarkUtils {
|
|||||||
if (!TextUtils.isEmpty(setting.level)) msgMap["level"] = setting.level
|
if (!TextUtils.isEmpty(setting.level)) msgMap["level"] = setting.level
|
||||||
if (!TextUtils.isEmpty(setting.sound)) msgMap["sound"] = setting.sound
|
if (!TextUtils.isEmpty(setting.sound)) msgMap["sound"] = setting.sound
|
||||||
if (!TextUtils.isEmpty(setting.badge)) msgMap["badge"] = setting.badge
|
if (!TextUtils.isEmpty(setting.badge)) msgMap["badge"] = setting.badge
|
||||||
if (!TextUtils.isEmpty(setting.url)) msgMap["url"] = setting.url
|
if (!TextUtils.isEmpty(setting.url)) {
|
||||||
|
val replacedUrl = msgInfo.getContentForSend(setting.url)
|
||||||
|
msgMap["url"] = replacedUrl
|
||||||
|
}
|
||||||
|
|
||||||
//自动复制验证码
|
if (!TextUtils.isEmpty(setting.call)) msgMap["call"] = setting.call
|
||||||
|
|
||||||
|
//自动复制
|
||||||
|
if (TextUtils.isEmpty(setting.autoCopy)) {
|
||||||
val pattern = Regex("(?<!回复)(验证码|授权码|校验码|检验码|确认码|激活码|动态码|安全码|(验证)?代码|校验代码|检验代码|激活代码|确认代码|动态代码|安全代码|登入码|认证码|识别码|短信口令|动态密码|交易码|上网密码|动态口令|随机码|驗證碼|授權碼|校驗碼|檢驗碼|確認碼|激活碼|動態碼|(驗證)?代碼|校驗代碼|檢驗代碼|確認代碼|激活代碼|動態代碼|登入碼|認證碼|識別碼|一次性密码|[Cc][Oo][Dd][Ee]|[Vv]erification)")
|
val pattern = Regex("(?<!回复)(验证码|授权码|校验码|检验码|确认码|激活码|动态码|安全码|(验证)?代码|校验代码|检验代码|激活代码|确认代码|动态代码|安全代码|登入码|认证码|识别码|短信口令|动态密码|交易码|上网密码|动态口令|随机码|驗證碼|授權碼|校驗碼|檢驗碼|確認碼|激活碼|動態碼|(驗證)?代碼|校驗代碼|檢驗代碼|確認代碼|激活代碼|動態代碼|登入碼|認證碼|識別碼|一次性密码|[Cc][Oo][Dd][Ee]|[Vv]erification)")
|
||||||
if (pattern.containsMatchIn(content)) {
|
if (pattern.containsMatchIn(content)) {
|
||||||
var code = content.replace("(.*)((代|授权|验证|动态|校验)码|[【\\[].*[】\\]]|[Cc][Oo][Dd][Ee]|[Vv]erification\\s?([Cc]ode)?)\\s?(G-|<#>)?([::\\s是为]|[Ii][Ss]){0,3}[\\((\\[【{「]?(([0-9\\s]{4,7})|([\\dA-Za-z]{5,6})(?!([Vv]erification)?([Cc][Oo][Dd][Ee])|:))[」}】\\])\\)]?(?=([^0-9a-zA-Z]|\$))(.*)".toRegex(), "$7").trim()
|
var code = content.replace("(.*)((代|授权|验证|动态|校验)码|[【\\[].*[】\\]]|[Cc][Oo][Dd][Ee]|[Vv]erification\\s?([Cc]ode)?)\\s?(G-|<#>)?([::\\s是为]|[Ii][Ss]){0,3}[\\((\\[【{「]?(([0-9\\s]{4,7})|([\\dA-Za-z]{5,6})(?!([Vv]erification)?([Cc][Oo][Dd][Ee])|:))[」}】\\])\\)]?(?=([^0-9a-zA-Z]|\$))(.*)".toRegex(), "$7").trim()
|
||||||
code = code.replace("\\D*[\\((\\[【{「]?([0-9]{3}\\s?[0-9]{1,3})[」}】\\])\\)]?(?=.*((代|授权|验证|动态|校验)码|[【\\[].*[】\\]]|[Cc][Oo][Dd][Ee]|[Vv]erification\\s?([Cc]ode)?))(.*)".toRegex(), "$1").trim()
|
code = code.replace("\\D*[\\((\\[【{「]?([0-9]{3}\\s?[0-9]{1,3})[」}】\\])\\)]?(?=.*((代|授权|验证|动态|校验)码|[【\\[].*[】\\]]|[Cc][Oo][Dd][Ee]|[Vv]erification\\s?([Cc]ode)?))(.*)".toRegex(), "$1").trim()
|
||||||
if (code.isNotEmpty()) {
|
if (code.isNotEmpty()) {
|
||||||
msgMap["copy"] = code
|
msgMap["copy"] = code
|
||||||
msgMap["automaticallyCopy"] = 1
|
msgMap["autoCopy"] = 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
msgMap["copy"] = msgInfo.getContentForSend(setting.autoCopy)
|
||||||
|
msgMap["autoCopy"] = 1
|
||||||
|
}
|
||||||
|
|
||||||
val requestMsg: String = Gson().toJson(msgMap)
|
val requestMsg: String = Gson().toJson(msgMap)
|
||||||
Log.i(TAG, "requestMsg:$requestMsg")
|
Log.i(TAG, "requestMsg:$requestMsg")
|
||||||
|
@ -137,6 +137,14 @@ class EmailUtils {
|
|||||||
setting.fromEmail += setting.mailType
|
setting.fromEmail += setting.mailType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"@icloud.com" -> {
|
||||||
|
setting.host = "smtp.mail.me.com"
|
||||||
|
setting.port = "587"
|
||||||
|
setting.ssl = false
|
||||||
|
setting.startTls = true
|
||||||
|
setting.fromEmail += setting.mailType
|
||||||
|
}
|
||||||
|
|
||||||
else -> {}
|
else -> {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,7 +38,14 @@ class ServerchanUtils {
|
|||||||
msgInfo.getContentForSend(SettingUtils.smsTemplate)
|
msgInfo.getContentForSend(SettingUtils.smsTemplate)
|
||||||
}
|
}
|
||||||
|
|
||||||
val requestUrl: String = String.format("https://sctapi.ftqq.com/%s.send", setting.sendKey) //推送地址
|
// 兼容Server酱³Sendkey,使用正则表达式提取数字部分
|
||||||
|
val matchResult = Regex("^sctp(\\d+)t", RegexOption.IGNORE_CASE).find(setting.sendKey)
|
||||||
|
val requestUrl = if (matchResult != null && matchResult.groups[1] != null) {
|
||||||
|
"https://${matchResult.groups[1]?.value}.push.ft07.com/send/${setting.sendKey}.send"
|
||||||
|
} else {
|
||||||
|
String.format("https://sctapi.ftqq.com/%s.send", setting.sendKey) // 默认推送地址
|
||||||
|
}
|
||||||
|
|
||||||
Log.i(TAG, "requestUrl:$requestUrl")
|
Log.i(TAG, "requestUrl:$requestUrl")
|
||||||
|
|
||||||
val request = XHttp.post(requestUrl)
|
val request = XHttp.post(requestUrl)
|
||||||
|
@ -58,13 +58,29 @@ class TelegramUtils private constructor() {
|
|||||||
|
|
||||||
val request = if (setting.method == "GET") {
|
val request = if (setting.method == "GET") {
|
||||||
requestUrl += "?chat_id=" + setting.chatId + "&text=" + URLEncoder.encode(content, "UTF-8")
|
requestUrl += "?chat_id=" + setting.chatId + "&text=" + URLEncoder.encode(content, "UTF-8")
|
||||||
|
if (setting.parseMode.isNotEmpty() && setting.parseMode != "TEXT") {
|
||||||
|
requestUrl += "&parse_mode=" + setting.parseMode
|
||||||
|
}
|
||||||
Log.i(TAG, "requestUrl:$requestUrl")
|
Log.i(TAG, "requestUrl:$requestUrl")
|
||||||
XHttp.get(requestUrl)
|
XHttp.get(requestUrl)
|
||||||
} else {
|
} else {
|
||||||
val bodyMap: MutableMap<String, Any> = mutableMapOf()
|
val bodyMap: MutableMap<String, Any> = mutableMapOf()
|
||||||
bodyMap["chat_id"] = setting.chatId
|
bodyMap["chat_id"] = setting.chatId
|
||||||
bodyMap["text"] = content
|
when (setting.parseMode) {
|
||||||
|
"MarkdownV2" -> {
|
||||||
|
bodyMap["parse_mode"] = "MarkdownV2"
|
||||||
|
bodyMap["text"] = escapeMarkdownV2(content)
|
||||||
|
}
|
||||||
|
|
||||||
|
"HTML" -> {
|
||||||
bodyMap["parse_mode"] = "HTML"
|
bodyMap["parse_mode"] = "HTML"
|
||||||
|
bodyMap["text"] = content
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
bodyMap["text"] = content
|
||||||
|
}
|
||||||
|
}
|
||||||
bodyMap["disable_web_page_preview"] = "true"
|
bodyMap["disable_web_page_preview"] = "true"
|
||||||
val requestMsg: String = Gson().toJson(bodyMap)
|
val requestMsg: String = Gson().toJson(bodyMap)
|
||||||
Log.i(TAG, "requestMsg:$requestMsg")
|
Log.i(TAG, "requestMsg:$requestMsg")
|
||||||
@ -155,5 +171,18 @@ class TelegramUtils private constructor() {
|
|||||||
}
|
}
|
||||||
return buffer.toString()
|
return buffer.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 用于转义 MarkdownV2 特殊字符的方法
|
||||||
|
private fun escapeMarkdownV2(text: String): String {
|
||||||
|
// TODO: MarkdownV2 要求转义以下字符,实测不能全部转义(丢失格式)
|
||||||
|
//val specialChars = listOf('_', '*', '[', ']', '(', ')', '~', '`', '>', '#', '+', '-', '=', '|', '{', '}', '.', '!')
|
||||||
|
val specialChars = listOf('-')
|
||||||
|
var escapedText = text
|
||||||
|
for (char in specialChars) {
|
||||||
|
// 将每个字符替换为带反斜杠的形式
|
||||||
|
escapedText = escapedText.replace(char.toString(), "\\$char")
|
||||||
|
}
|
||||||
|
return escapedText
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -91,6 +91,24 @@ class WebhookUtils {
|
|||||||
Log.i(TAG, "requestUrl:$requestUrl")
|
Log.i(TAG, "requestUrl:$requestUrl")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//通过`Content-Type=applicaton/json`指定请求体为`json`格式
|
||||||
|
var isJson = false
|
||||||
|
//通过`Content-Type=text/plain、text/html、text/css、text/javascript、text/xml`指定请求体为`文本`格式
|
||||||
|
var isText = false
|
||||||
|
var mediaType = "text/plain"
|
||||||
|
for ((key, value) in setting.headers.entries) {
|
||||||
|
if (key.equals("Content-Type", ignoreCase = true)) {
|
||||||
|
if (value.contains("application/json")) {
|
||||||
|
isJson = true
|
||||||
|
break
|
||||||
|
} else if (value.startsWith("text/")) {
|
||||||
|
isText = true
|
||||||
|
mediaType = value
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val request = if (setting.method == "GET" && TextUtils.isEmpty(webParams)) {
|
val request = if (setting.method == "GET" && TextUtils.isEmpty(webParams)) {
|
||||||
setting.webServer += (if (setting.webServer.contains("?")) "&" else "?") + "from=" + URLEncoder.encode(
|
setting.webServer += (if (setting.webServer.contains("?")) "&" else "?") + "from=" + URLEncoder.encode(
|
||||||
from,
|
from,
|
||||||
@ -104,6 +122,7 @@ class WebhookUtils {
|
|||||||
Log.d(TAG, "method = GET, Url = $requestUrl")
|
Log.d(TAG, "method = GET, Url = $requestUrl")
|
||||||
XHttp.get(requestUrl).keepJson(true)
|
XHttp.get(requestUrl).keepJson(true)
|
||||||
} else if (setting.method == "GET" && !TextUtils.isEmpty(webParams)) {
|
} else if (setting.method == "GET" && !TextUtils.isEmpty(webParams)) {
|
||||||
|
webParams = msgInfo.replaceTemplate(webParams, "", "URLEncoder")
|
||||||
webParams = webParams.replace("[from]", URLEncoder.encode(from, "UTF-8"))
|
webParams = webParams.replace("[from]", URLEncoder.encode(from, "UTF-8"))
|
||||||
.replace("[content]", URLEncoder.encode(content, "UTF-8"))
|
.replace("[content]", URLEncoder.encode(content, "UTF-8"))
|
||||||
.replace("[msg]", URLEncoder.encode(content, "UTF-8"))
|
.replace("[msg]", URLEncoder.encode(content, "UTF-8"))
|
||||||
@ -128,7 +147,8 @@ class WebhookUtils {
|
|||||||
}
|
}
|
||||||
Log.d(TAG, "method = GET, Url = $requestUrl")
|
Log.d(TAG, "method = GET, Url = $requestUrl")
|
||||||
XHttp.get(requestUrl).keepJson(true)
|
XHttp.get(requestUrl).keepJson(true)
|
||||||
} else if (webParams.isNotEmpty() && webParams.startsWith("{")) {
|
} else if (webParams.isNotEmpty() && (isJson || isText || webParams.startsWith("{"))) {
|
||||||
|
webParams = msgInfo.replaceTemplate(webParams, "", "Gson")
|
||||||
val bodyMsg = webParams.replace("[from]", from)
|
val bodyMsg = webParams.replace("[from]", from)
|
||||||
.replace("[content]", escapeJson(content))
|
.replace("[content]", escapeJson(content))
|
||||||
.replace("[msg]", escapeJson(content))
|
.replace("[msg]", escapeJson(content))
|
||||||
@ -144,11 +164,19 @@ class WebhookUtils {
|
|||||||
.replace("[timestamp]", timestamp.toString())
|
.replace("[timestamp]", timestamp.toString())
|
||||||
.replace("[sign]", sign)
|
.replace("[sign]", sign)
|
||||||
Log.d(TAG, "method = ${setting.method}, Url = $requestUrl, bodyMsg = $bodyMsg")
|
Log.d(TAG, "method = ${setting.method}, Url = $requestUrl, bodyMsg = $bodyMsg")
|
||||||
|
if (isText) {
|
||||||
|
when (setting.method) {
|
||||||
|
"PUT" -> XHttp.put(requestUrl).keepJson(true).upString(bodyMsg, mediaType)
|
||||||
|
"PATCH" -> XHttp.patch(requestUrl).keepJson(true).upString(bodyMsg, mediaType)
|
||||||
|
else -> XHttp.post(requestUrl).keepJson(true).upString(bodyMsg, mediaType)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
when (setting.method) {
|
when (setting.method) {
|
||||||
"PUT" -> XHttp.put(requestUrl).keepJson(true).upJson(bodyMsg)
|
"PUT" -> XHttp.put(requestUrl).keepJson(true).upJson(bodyMsg)
|
||||||
"PATCH" -> XHttp.patch(requestUrl).keepJson(true).upJson(bodyMsg)
|
"PATCH" -> XHttp.patch(requestUrl).keepJson(true).upJson(bodyMsg)
|
||||||
else -> XHttp.post(requestUrl).keepJson(true).upJson(bodyMsg)
|
else -> XHttp.post(requestUrl).keepJson(true).upJson(bodyMsg)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (webParams.isEmpty()) {
|
if (webParams.isEmpty()) {
|
||||||
webParams = "from=[from]&content=[content]×tamp=[timestamp]"
|
webParams = "from=[from]&content=[content]×tamp=[timestamp]"
|
||||||
@ -160,11 +188,13 @@ class WebhookUtils {
|
|||||||
"PATCH" -> XHttp.patch(requestUrl).keepJson(true)
|
"PATCH" -> XHttp.patch(requestUrl).keepJson(true)
|
||||||
else -> XHttp.post(requestUrl).keepJson(true)
|
else -> XHttp.post(requestUrl).keepJson(true)
|
||||||
}
|
}
|
||||||
|
webParams = msgInfo.replaceTemplate(webParams)
|
||||||
webParams.trim('&').split("&").forEach {
|
webParams.trim('&').split("&").forEach {
|
||||||
val param = it.split("=")
|
val sepIndex = it.indexOf("=")
|
||||||
if (param.size == 2) {
|
if (sepIndex != -1) {
|
||||||
postRequest.params(
|
val key = it.substring(0, sepIndex).trim()
|
||||||
param[0], param[1].replace("[from]", from)
|
val value = it.substring(sepIndex + 1).trim()
|
||||||
|
postRequest.params(key, value.replace("[from]", from)
|
||||||
.replace("[content]", content)
|
.replace("[content]", content)
|
||||||
.replace("[msg]", content)
|
.replace("[msg]", content)
|
||||||
.replace("[org_content]", orgContent)
|
.replace("[org_content]", orgContent)
|
||||||
|
@ -26,6 +26,7 @@ class XHttpUpdateHttpServiceImpl : IUpdateHttpService {
|
|||||||
callBack: IUpdateHttpService.Callback,
|
callBack: IUpdateHttpService.Callback,
|
||||||
) {
|
) {
|
||||||
XHttp.get(url)
|
XHttp.get(url)
|
||||||
|
.ignoreHttpsCert()
|
||||||
.params(params)
|
.params(params)
|
||||||
.keepJson(true)
|
.keepJson(true)
|
||||||
.execute(object : SimpleCallBack<String>() {
|
.execute(object : SimpleCallBack<String>() {
|
||||||
@ -46,6 +47,7 @@ class XHttpUpdateHttpServiceImpl : IUpdateHttpService {
|
|||||||
callBack: IUpdateHttpService.Callback,
|
callBack: IUpdateHttpService.Callback,
|
||||||
) {
|
) {
|
||||||
XHttp.post(url)
|
XHttp.post(url)
|
||||||
|
.ignoreHttpsCert()
|
||||||
.upJson(JsonUtil.toJson(params))
|
.upJson(JsonUtil.toJson(params))
|
||||||
.keepJson(true)
|
.keepJson(true)
|
||||||
.execute(object : SimpleCallBack<String>() {
|
.execute(object : SimpleCallBack<String>() {
|
||||||
@ -63,6 +65,7 @@ class XHttpUpdateHttpServiceImpl : IUpdateHttpService {
|
|||||||
override fun download(url: String, path: String, fileName: String, callback: DownloadCallback) {
|
override fun download(url: String, path: String, fileName: String, callback: DownloadCallback) {
|
||||||
XHttpSDK.addRequest(
|
XHttpSDK.addRequest(
|
||||||
url, XHttp.downLoad(url)
|
url, XHttp.downLoad(url)
|
||||||
|
.ignoreHttpsCert()
|
||||||
.savePath(path)
|
.savePath(path)
|
||||||
.saveName(fileName)
|
.saveName(fileName)
|
||||||
.isUseBaseUrl(false)
|
.isUseBaseUrl(false)
|
||||||
|
@ -6,17 +6,19 @@ import android.widget.CompoundButton
|
|||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.appcompat.widget.AppCompatCheckBox
|
import androidx.appcompat.widget.AppCompatCheckBox
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import com.google.gson.JsonObject
|
||||||
|
import com.google.gson.reflect.TypeToken
|
||||||
import com.idormy.sms.forwarder.R
|
import com.idormy.sms.forwarder.R
|
||||||
import com.idormy.sms.forwarder.core.http.api.ApiService.IGetService
|
|
||||||
import com.idormy.sms.forwarder.core.http.callback.NoTipCallBack
|
|
||||||
import com.idormy.sms.forwarder.core.http.entity.TipInfo
|
import com.idormy.sms.forwarder.core.http.entity.TipInfo
|
||||||
import com.idormy.sms.forwarder.utils.AppUtils
|
import com.idormy.sms.forwarder.utils.AppUtils
|
||||||
import com.idormy.sms.forwarder.utils.SharedPreference
|
import com.idormy.sms.forwarder.utils.SharedPreference
|
||||||
import com.xuexiang.constant.TimeConstants
|
|
||||||
import com.xuexiang.xaop.annotation.SingleClick
|
import com.xuexiang.xaop.annotation.SingleClick
|
||||||
import com.xuexiang.xhttp2.XHttp
|
import com.xuexiang.xhttp2.XHttp
|
||||||
import com.xuexiang.xhttp2.cache.model.CacheMode
|
import com.xuexiang.xhttp2.callback.SimpleCallBack
|
||||||
|
import com.xuexiang.xhttp2.exception.ApiException
|
||||||
import com.xuexiang.xui.widget.dialog.BaseDialog
|
import com.xuexiang.xui.widget.dialog.BaseDialog
|
||||||
|
import com.xuexiang.xutil.resource.ResUtils.getString
|
||||||
import com.zzhoujay.richtext.RichText
|
import com.zzhoujay.richtext.RichText
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -163,15 +165,30 @@ class GuideTipsDialog(context: Context?, tips: List<TipInfo>) :
|
|||||||
*/
|
*/
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun showTipsForce(context: Context?) {
|
fun showTipsForce(context: Context?) {
|
||||||
val request = XHttp.custom().cacheMode(CacheMode.FIRST_CACHE)
|
XHttp.get(getString(R.string.url_tips))
|
||||||
.cacheTime(TimeConstants.DAY.toLong()).cacheKey("getTips")
|
.keepJson(true)
|
||||||
request.apiCall(request.create(
|
.ignoreHttpsCert()
|
||||||
IGetService::class.java
|
.timeStamp(true) //url自动追加时间戳,避免缓存
|
||||||
).tips, object : NoTipCallBack<List<TipInfo>>() {
|
.execute(object : SimpleCallBack<String>() {
|
||||||
@Throws(Throwable::class)
|
override fun onError(e: ApiException) {
|
||||||
override fun onSuccess(response: List<TipInfo>?) {
|
e.printStackTrace()
|
||||||
if (!response.isNullOrEmpty()) {
|
}
|
||||||
GuideTipsDialog(context, response).show()
|
|
||||||
|
override fun onSuccess(json: String) {
|
||||||
|
try {
|
||||||
|
val gson = Gson()
|
||||||
|
val jsonObject = gson.fromJson(json, JsonObject::class.java)
|
||||||
|
if (jsonObject.isJsonObject
|
||||||
|
&& jsonObject.has("Code") && jsonObject["Code"].asInt == 0
|
||||||
|
&& jsonObject.has("Data") && jsonObject["Data"].isJsonArray
|
||||||
|
) {
|
||||||
|
val dataJsonArray = jsonObject["Data"].asJsonArray
|
||||||
|
val listType = object : TypeToken<List<TipInfo>>() {}.type
|
||||||
|
val tips = gson.fromJson<List<TipInfo>>(dataJsonArray, listType)
|
||||||
|
GuideTipsDialog(context, tips).show()
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -32,10 +32,6 @@ import com.xuexiang.xutil.resource.ResUtils
|
|||||||
import com.xuexiang.xutil.security.CipherUtils
|
import com.xuexiang.xutil.security.CipherUtils
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import java.text.ParsePosition
|
|
||||||
import java.text.SimpleDateFormat
|
|
||||||
import java.util.Calendar
|
|
||||||
import java.util.Date
|
|
||||||
|
|
||||||
@Suppress("PrivatePropertyName", "DEPRECATION")
|
@Suppress("PrivatePropertyName", "DEPRECATION")
|
||||||
class SendWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {
|
class SendWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {
|
||||||
@ -61,36 +57,15 @@ class SendWorker(context: Context, params: WorkerParameters) : CoroutineWorker(c
|
|||||||
|
|
||||||
// 免打扰(禁用转发)时间段
|
// 免打扰(禁用转发)时间段
|
||||||
var isSilentPeriod = false
|
var isSilentPeriod = false
|
||||||
|
Log.d(TAG, "silentPeriodStart = ${SettingUtils.silentPeriodStart}, silentPeriodEnd = ${SettingUtils.silentPeriodEnd}")
|
||||||
if (SettingUtils.silentPeriodStart != SettingUtils.silentPeriodEnd) {
|
if (SettingUtils.silentPeriodStart != SettingUtils.silentPeriodEnd) {
|
||||||
val periodStartDay = Date()
|
isSilentPeriod = DataProvider.isCurrentTimeInPeriod(SettingUtils.silentPeriodStart, SettingUtils.silentPeriodEnd)
|
||||||
var periodStartEnd = Date()
|
Log.d(TAG, "isSilentPeriod = $isSilentPeriod, enableSilentPeriodLogs = ${SettingUtils.enableSilentPeriodLogs}")
|
||||||
//跨天了
|
if (isSilentPeriod && !SettingUtils.enableSilentPeriodLogs) {
|
||||||
if (SettingUtils.silentPeriodStart > SettingUtils.silentPeriodEnd) {
|
|
||||||
val c: Calendar = Calendar.getInstance()
|
|
||||||
c.time = periodStartEnd
|
|
||||||
c.add(Calendar.DAY_OF_MONTH, 1)
|
|
||||||
periodStartEnd = c.time
|
|
||||||
}
|
|
||||||
|
|
||||||
val dateFmt = SimpleDateFormat("yyyy-MM-dd")
|
|
||||||
val mTimeOption = DataProvider.timePeriodOption
|
|
||||||
val periodStartStr = dateFmt.format(periodStartDay) + " " + mTimeOption[SettingUtils.silentPeriodStart] + ":00"
|
|
||||||
val periodEndStr = dateFmt.format(periodStartEnd) + " " + mTimeOption[SettingUtils.silentPeriodEnd] + ":00"
|
|
||||||
|
|
||||||
val timeFmt = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
|
|
||||||
val periodStart = timeFmt.parse(periodStartStr, ParsePosition(0))?.time
|
|
||||||
val periodEnd = timeFmt.parse(periodEndStr, ParsePosition(0))?.time
|
|
||||||
|
|
||||||
val now = System.currentTimeMillis()
|
|
||||||
if (periodStart != null && periodEnd != null && now in periodStart..periodEnd) {
|
|
||||||
if (SettingUtils.enableSilentPeriodLogs) {
|
|
||||||
isSilentPeriod = true
|
|
||||||
} else {
|
|
||||||
Log.e(TAG, "免打扰(禁用转发)时间段")
|
Log.e(TAG, "免打扰(禁用转发)时间段")
|
||||||
return@withContext Result.failure(workDataOf("send" to "failed"))
|
return@withContext Result.failure(workDataOf("send" to "failed"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// 过滤重复消息机制
|
// 过滤重复消息机制
|
||||||
val duplicateMessagesLimits = SettingUtils.duplicateMessagesLimits * 1000L
|
val duplicateMessagesLimits = SettingUtils.duplicateMessagesLimits * 1000L
|
||||||
|
20
app/src/main/res/drawable/rounded_button.xml
Normal file
20
app/src/main/res/drawable/rounded_button.xml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<!-- 按下时的背景 -->
|
||||||
|
<item android:state_pressed="true">
|
||||||
|
<shape>
|
||||||
|
<solid android:color="#1E88E5" /> <!-- 按下时的深蓝背景色 -->
|
||||||
|
<corners android:radius="3dp" /> <!-- 圆角半径 -->
|
||||||
|
<stroke android:width="1dp" android:color="#1565C0" /> <!-- 边框深蓝色 -->
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
|
||||||
|
<!-- 默认背景 -->
|
||||||
|
<item>
|
||||||
|
<shape>
|
||||||
|
<solid android:color="#2196F3" /> <!-- 默认浅蓝背景色 -->
|
||||||
|
<corners android:radius="3dp" /> <!-- 圆角半径 -->
|
||||||
|
<stroke android:width="1dp" android:color="#1E88E5" /> <!-- 边框蓝色 -->
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</selector>
|
@ -376,65 +376,13 @@
|
|||||||
android:inputType="textMultiLine"
|
android:inputType="textMultiLine"
|
||||||
app:met_clearButton="true" />
|
app:met_clearButton="true" />
|
||||||
|
|
||||||
<LinearLayout
|
<GridLayout
|
||||||
|
android:id="@+id/gl_sms_template"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal">
|
android:layout_gravity="center"
|
||||||
|
android:columnCount="4"
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
android:orientation="horizontal" />
|
||||||
android:id="@+id/bt_insert_sender"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:text="@string/insert_sender" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_content"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:text="@string/insert_content" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_extra"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:text="@string/insert_extra" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_sender_app"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:text="@string/insert_sender_app" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_uid"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:text="@string/insert_uid" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_title_app"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:text="@string/insert_title_app" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_content_app"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:text="@string/insert_content_app" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_time"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:text="@string/insert_time" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_device_name"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:text="@string/insert_device_name" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@ -507,6 +455,12 @@
|
|||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/layout_silent_period"
|
android:id="@+id/layout_silent_period"
|
||||||
style="@style/BarStyle"
|
style="@style/BarStyle"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
tools:ignore="RtlSymmetry">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
tools:ignore="RtlSymmetry">
|
tools:ignore="RtlSymmetry">
|
||||||
@ -558,6 +512,132 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<HorizontalScrollView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="3dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<com.xuexiang.xui.widget.button.SmoothCheckBox
|
||||||
|
android:id="@+id/mon"
|
||||||
|
android:layout_width="15dp"
|
||||||
|
android:layout_height="15dp"
|
||||||
|
app:scb_color_checked="@color/colorPrimary"
|
||||||
|
tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:text="@string/mon"
|
||||||
|
android:textSize="@dimen/text_size_small"
|
||||||
|
tools:ignore="SmallSp" />
|
||||||
|
|
||||||
|
<com.xuexiang.xui.widget.button.SmoothCheckBox
|
||||||
|
android:id="@+id/tue"
|
||||||
|
android:layout_width="15dp"
|
||||||
|
android:layout_height="15dp"
|
||||||
|
android:layout_marginStart="5dp"
|
||||||
|
app:scb_color_checked="@color/colorPrimary"
|
||||||
|
tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:text="@string/tue"
|
||||||
|
android:textSize="@dimen/text_size_small"
|
||||||
|
tools:ignore="SmallSp" />
|
||||||
|
|
||||||
|
<com.xuexiang.xui.widget.button.SmoothCheckBox
|
||||||
|
android:id="@+id/wed"
|
||||||
|
android:layout_width="15dp"
|
||||||
|
android:layout_height="15dp"
|
||||||
|
android:layout_marginStart="5dp"
|
||||||
|
app:scb_color_checked="@color/colorPrimary"
|
||||||
|
tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:text="@string/wed"
|
||||||
|
android:textSize="@dimen/text_size_small"
|
||||||
|
tools:ignore="SmallSp" />
|
||||||
|
|
||||||
|
<com.xuexiang.xui.widget.button.SmoothCheckBox
|
||||||
|
android:id="@+id/thu"
|
||||||
|
android:layout_width="15dp"
|
||||||
|
android:layout_height="15dp"
|
||||||
|
android:layout_marginStart="5dp"
|
||||||
|
app:scb_color_checked="@color/colorPrimary"
|
||||||
|
tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:text="@string/thu"
|
||||||
|
android:textSize="@dimen/text_size_small"
|
||||||
|
tools:ignore="SmallSp" />
|
||||||
|
|
||||||
|
<com.xuexiang.xui.widget.button.SmoothCheckBox
|
||||||
|
android:id="@+id/fri"
|
||||||
|
android:layout_width="15dp"
|
||||||
|
android:layout_height="15dp"
|
||||||
|
android:layout_marginStart="5dp"
|
||||||
|
app:scb_color_checked="@color/colorPrimary"
|
||||||
|
tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:text="@string/fri"
|
||||||
|
android:textSize="@dimen/text_size_small"
|
||||||
|
tools:ignore="SmallSp" />
|
||||||
|
|
||||||
|
<com.xuexiang.xui.widget.button.SmoothCheckBox
|
||||||
|
android:id="@+id/sat"
|
||||||
|
android:layout_width="15dp"
|
||||||
|
android:layout_height="15dp"
|
||||||
|
android:layout_marginStart="5dp"
|
||||||
|
app:scb_color_checked="@color/colorPrimary"
|
||||||
|
tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:text="@string/sat"
|
||||||
|
android:textSize="@dimen/text_size_small"
|
||||||
|
tools:ignore="SmallSp" />
|
||||||
|
|
||||||
|
<com.xuexiang.xui.widget.button.SmoothCheckBox
|
||||||
|
android:id="@+id/sun"
|
||||||
|
android:layout_width="15dp"
|
||||||
|
android:layout_height="15dp"
|
||||||
|
android:layout_marginStart="5dp"
|
||||||
|
app:scb_color_checked="@color/colorPrimary"
|
||||||
|
tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:text="@string/sun"
|
||||||
|
android:textSize="@dimen/text_size_small"
|
||||||
|
tools:ignore="SmallSp" />
|
||||||
|
</LinearLayout>
|
||||||
|
</HorizontalScrollView>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</androidx.core.widget.NestedScrollView>
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
@ -140,6 +140,28 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
style="@style/BarStyle.Switch"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="3"
|
||||||
|
android:text="@string/bark_call"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<com.xuexiang.xui.widget.button.switchbutton.SwitchButton
|
||||||
|
android:id="@+id/sb_call"
|
||||||
|
style="@style/SwitchButtonStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:checked="true" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
style="@style/BarStyle"
|
style="@style/BarStyle"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -271,36 +293,60 @@
|
|||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
app:met_clearButton="true" />
|
app:met_clearButton="true" />
|
||||||
|
|
||||||
|
<GridLayout
|
||||||
|
android:id="@+id/gl_title_template"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:columnCount="4"
|
||||||
|
android:orientation="horizontal" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/layout_auto_copy_template"
|
||||||
|
style="@style/BarStyle"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
<TextView
|
||||||
android:id="@+id/bt_insert_sender"
|
android:layout_width="wrap_content"
|
||||||
style="@style/insertButtonStyle"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/insert_sender" />
|
android:text="@string/auto_copy"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
<TextView
|
||||||
android:id="@+id/bt_insert_extra"
|
android:layout_width="wrap_content"
|
||||||
style="@style/insertButtonStyle"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="5dp"
|
android:layout_marginStart="5dp"
|
||||||
android:text="@string/insert_extra" />
|
android:text="@string/custom_template_tips"
|
||||||
|
android:textSize="@dimen/text_size_mini"
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
tools:ignore="SmallSp" />
|
||||||
android:id="@+id/bt_insert_time"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:text="@string/insert_time" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_device_name"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:text="@string/insert_device_name" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<com.xuexiang.xui.widget.edittext.materialedittext.MaterialEditText
|
||||||
|
android:id="@+id/et_auto_copy_template"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:singleLine="true"
|
||||||
|
app:met_clearButton="true" />
|
||||||
|
|
||||||
|
<GridLayout
|
||||||
|
android:id="@+id/gl_auto_copy_template"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:columnCount="4"
|
||||||
|
android:orientation="horizontal" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
@ -253,35 +253,13 @@
|
|||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
app:met_clearButton="true" />
|
app:met_clearButton="true" />
|
||||||
|
|
||||||
<LinearLayout
|
<GridLayout
|
||||||
|
android:id="@+id/gl_title_template"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal">
|
android:layout_gravity="center"
|
||||||
|
android:columnCount="4"
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
android:orientation="horizontal" />
|
||||||
android:id="@+id/bt_insert_sender"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:text="@string/insert_sender" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_extra"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:text="@string/insert_extra" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_time"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:text="@string/insert_time" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_device_name"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:text="@string/insert_device_name" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
@ -230,35 +230,13 @@
|
|||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
app:met_clearButton="true" />
|
app:met_clearButton="true" />
|
||||||
|
|
||||||
<LinearLayout
|
<GridLayout
|
||||||
|
android:id="@+id/gl_title_template"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal">
|
android:layout_gravity="center"
|
||||||
|
android:columnCount="4"
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
android:orientation="horizontal" />
|
||||||
android:id="@+id/bt_insert_sender"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:text="@string/insert_sender" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_extra"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:text="@string/insert_extra" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_time"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:text="@string/insert_time" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_device_name"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:text="@string/insert_device_name" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
@ -149,35 +149,13 @@
|
|||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
app:met_clearButton="true" />
|
app:met_clearButton="true" />
|
||||||
|
|
||||||
<LinearLayout
|
<GridLayout
|
||||||
|
android:id="@+id/gl_nickname"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal">
|
android:layout_gravity="center"
|
||||||
|
android:columnCount="4"
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
android:orientation="horizontal" />
|
||||||
android:id="@+id/bt_insert_sender_to_nickname"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:text="@string/insert_sender" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_extra_to_nickname"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:text="@string/insert_extra" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_time_to_nickname"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:text="@string/insert_time" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_device_name_to_nickname"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:text="@string/insert_device_name" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@ -520,35 +498,13 @@
|
|||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
app:met_clearButton="true" />
|
app:met_clearButton="true" />
|
||||||
|
|
||||||
<LinearLayout
|
<GridLayout
|
||||||
|
android:id="@+id/gl_title_template"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal">
|
android:layout_gravity="center"
|
||||||
|
android:columnCount="4"
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
android:orientation="horizontal" />
|
||||||
android:id="@+id/bt_insert_sender"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:text="@string/insert_sender" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_extra"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:text="@string/insert_extra" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_time"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:text="@string/insert_time" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_device_name"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:text="@string/insert_device_name" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
@ -158,35 +158,13 @@
|
|||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
app:met_clearButton="true" />
|
app:met_clearButton="true" />
|
||||||
|
|
||||||
<LinearLayout
|
<GridLayout
|
||||||
|
android:id="@+id/gl_title_template"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal">
|
android:layout_gravity="center"
|
||||||
|
android:columnCount="4"
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
android:orientation="horizontal" />
|
||||||
android:id="@+id/bt_insert_sender_to_title"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:text="@string/insert_sender" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_extra_to_title"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:text="@string/insert_extra" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_time_to_title"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:text="@string/insert_time" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_device_name_to_title"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:text="@string/insert_device_name" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@ -230,41 +208,13 @@
|
|||||||
android:text=""
|
android:text=""
|
||||||
tools:ignore="RtlHardcoded,SpeakableTextPresentCheck" />
|
tools:ignore="RtlHardcoded,SpeakableTextPresentCheck" />
|
||||||
|
|
||||||
<LinearLayout
|
<GridLayout
|
||||||
|
android:id="@+id/gl_message_card"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal">
|
android:layout_gravity="center"
|
||||||
|
android:columnCount="4"
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
android:orientation="horizontal" />
|
||||||
android:id="@+id/bt_insert_sender"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:text="@string/insert_sender" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_content"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="3dp"
|
|
||||||
android:text="@string/insert_content" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_extra"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="3dp"
|
|
||||||
android:text="@string/insert_extra" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_time"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="3dp"
|
|
||||||
android:text="@string/insert_time" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_device_name"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="3dp"
|
|
||||||
android:text="@string/insert_device_name" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
@ -235,35 +235,13 @@
|
|||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
app:met_clearButton="true" />
|
app:met_clearButton="true" />
|
||||||
|
|
||||||
<LinearLayout
|
<GridLayout
|
||||||
|
android:id="@+id/gl_title_template"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal">
|
android:layout_gravity="center"
|
||||||
|
android:columnCount="4"
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
android:orientation="horizontal" />
|
||||||
android:id="@+id/bt_insert_sender_to_title"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:text="@string/insert_sender" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_extra_to_title"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:text="@string/insert_extra" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_time_to_title"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:text="@string/insert_time" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_device_name_to_title"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:text="@string/insert_device_name" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@ -307,41 +285,13 @@
|
|||||||
android:text=""
|
android:text=""
|
||||||
tools:ignore="RtlHardcoded,SpeakableTextPresentCheck" />
|
tools:ignore="RtlHardcoded,SpeakableTextPresentCheck" />
|
||||||
|
|
||||||
<LinearLayout
|
<GridLayout
|
||||||
|
android:id="@+id/gl_message_card"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal">
|
android:layout_gravity="center"
|
||||||
|
android:columnCount="4"
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
android:orientation="horizontal" />
|
||||||
android:id="@+id/bt_insert_sender"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:text="@string/insert_sender" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_content"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="3dp"
|
|
||||||
android:text="@string/insert_content" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_extra"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="3dp"
|
|
||||||
android:text="@string/insert_extra" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_time"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="3dp"
|
|
||||||
android:text="@string/insert_time" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_device_name"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="3dp"
|
|
||||||
android:text="@string/insert_device_name" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
@ -112,35 +112,13 @@
|
|||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
app:met_clearButton="true" />
|
app:met_clearButton="true" />
|
||||||
|
|
||||||
<LinearLayout
|
<GridLayout
|
||||||
|
android:id="@+id/gl_title_template"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal">
|
android:layout_gravity="center"
|
||||||
|
android:columnCount="4"
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
android:orientation="horizontal" />
|
||||||
android:id="@+id/bt_insert_sender"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:text="@string/insert_sender" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_extra"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:text="@string/insert_extra" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_time"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:text="@string/insert_time" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_device_name"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:text="@string/insert_device_name" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
@ -286,35 +286,13 @@
|
|||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
app:met_clearButton="true" />
|
app:met_clearButton="true" />
|
||||||
|
|
||||||
<LinearLayout
|
<GridLayout
|
||||||
|
android:id="@+id/gl_title_template"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal">
|
android:layout_gravity="center"
|
||||||
|
android:columnCount="4"
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
android:orientation="horizontal" />
|
||||||
android:id="@+id/bt_insert_sender"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:text="@string/insert_sender" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_extra"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:text="@string/insert_extra" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_time"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:text="@string/insert_time" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_device_name"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:text="@string/insert_device_name" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
@ -102,6 +102,44 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
style="@style/BarStyle"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/parse_mode"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<RadioGroup
|
||||||
|
android:id="@+id/rg_parse_mode"
|
||||||
|
style="@style/rg_style"
|
||||||
|
android:layout_marginStart="5dp"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/rb_parse_mode_text"
|
||||||
|
style="@style/rg_rb_style"
|
||||||
|
android:text="@string/parse_mode_text" />
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/rb_parse_mode_html"
|
||||||
|
style="@style/rg_rb_style"
|
||||||
|
android:checked="true"
|
||||||
|
android:text="@string/parse_mode_html" />
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/rb_parse_mode_markdown"
|
||||||
|
style="@style/rg_rb_style"
|
||||||
|
android:text="@string/parse_mode_markdown" />
|
||||||
|
|
||||||
|
</RadioGroup>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
style="@style/BarStyle"
|
style="@style/BarStyle"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -1226,7 +1226,7 @@
|
|||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/enabe_cactus_tips"
|
android:text="@string/enable_cactus_tips"
|
||||||
android:textSize="@dimen/text_size_mini"
|
android:textSize="@dimen/text_size_mini"
|
||||||
tools:ignore="SmallSp" />
|
tools:ignore="SmallSp" />
|
||||||
|
|
||||||
@ -1567,6 +1567,7 @@
|
|||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
android:id="@+id/layout_sim2"
|
||||||
style="@style/BarStyle"
|
style="@style/BarStyle"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@ -1741,41 +1742,13 @@
|
|||||||
android:text=""
|
android:text=""
|
||||||
tools:ignore="RtlHardcoded,SpeakableTextPresentCheck" />
|
tools:ignore="RtlHardcoded,SpeakableTextPresentCheck" />
|
||||||
|
|
||||||
<LinearLayout
|
<GridLayout
|
||||||
|
android:id="@+id/gl_sms_template"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal">
|
android:layout_gravity="center"
|
||||||
|
android:columnCount="4"
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
android:orientation="horizontal" />
|
||||||
android:id="@+id/bt_insert_sender"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:text="@string/insert_sender" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_content"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="3dp"
|
|
||||||
android:text="@string/insert_content" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_extra"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="3dp"
|
|
||||||
android:text="@string/insert_extra" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_time"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="3dp"
|
|
||||||
android:text="@string/insert_time" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_device_name"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="3dp"
|
|
||||||
android:text="@string/insert_device_name" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
@ -86,13 +86,34 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<TextView
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
android:text="@string/alarm_play_settings"
|
android:text="@string/alarm_play_settings"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
tools:ignore="RelativeOverlap" />
|
tools:ignore="RelativeOverlap" />
|
||||||
|
|
||||||
|
<com.xuexiang.xui.widget.button.switchbutton.SwitchButton
|
||||||
|
android:id="@+id/sb_enable_music"
|
||||||
|
style="@style/SwitchButtonStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/layout_alarm_settings_content"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="1dp"
|
android:layout_height="1dp"
|
||||||
@ -134,7 +155,7 @@
|
|||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.picker.XSeekBar
|
<com.xuexiang.xui.widget.picker.XSeekBar
|
||||||
android:id="@+id/xsb_loop_times"
|
android:id="@+id/xsb_play_times"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="5dp"
|
android:layout_marginStart="5dp"
|
||||||
@ -188,6 +209,234 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/layout_vibrate_settings"
|
||||||
|
style="@style/BarStyle"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="@string/alarm_vibrate_settings"
|
||||||
|
android:textStyle="bold"
|
||||||
|
tools:ignore="RelativeOverlap" />
|
||||||
|
|
||||||
|
<com.xuexiang.xui.widget.button.switchbutton.SwitchButton
|
||||||
|
android:id="@+id/sb_enable_vibrate"
|
||||||
|
style="@style/SwitchButtonStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/layout_vibrate_settings_content"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:layout_marginTop="5dp"
|
||||||
|
android:background="?attr/xui_config_color_separator_light" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/alarm_vibration_effect"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<com.xuexiang.xui.widget.edittext.ClearEditText
|
||||||
|
android:id="@+id/et_vibration_effect"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="5dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:hint="@string/alarm_vibration_effect_tips"
|
||||||
|
android:textSize="@dimen/text_size_mini"
|
||||||
|
tools:ignore="SmallSp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
||||||
|
android:id="@+id/bt_insert_vibration_effect_1"
|
||||||
|
style="@style/insertButtonStyle"
|
||||||
|
android:text="@string/alarm_vibration_effect_1" />
|
||||||
|
|
||||||
|
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
||||||
|
android:id="@+id/bt_insert_vibration_effect_2"
|
||||||
|
style="@style/insertButtonStyle"
|
||||||
|
android:layout_marginStart="5dp"
|
||||||
|
android:text="@string/alarm_vibration_effect_2" />
|
||||||
|
|
||||||
|
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
||||||
|
android:id="@+id/bt_insert_vibration_effect_3"
|
||||||
|
style="@style/insertButtonStyle"
|
||||||
|
android:layout_marginStart="5dp"
|
||||||
|
android:text="@string/alarm_vibration_effect_3" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="5dp"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/alarm_repeat_times"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<com.xuexiang.xui.widget.picker.XSeekBar
|
||||||
|
android:id="@+id/xsb_repeat_times"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="5dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:padding="0dp"
|
||||||
|
app:xsb_max="30"
|
||||||
|
app:xsb_min="0" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/layout_flash_settings"
|
||||||
|
style="@style/BarStyle"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="@string/alarm_flash_settings"
|
||||||
|
android:textStyle="bold"
|
||||||
|
tools:ignore="RelativeOverlap" />
|
||||||
|
|
||||||
|
<com.xuexiang.xui.widget.button.switchbutton.SwitchButton
|
||||||
|
android:id="@+id/sb_enable_flash"
|
||||||
|
style="@style/SwitchButtonStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/layout_flash_settings_content"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:layout_marginTop="5dp"
|
||||||
|
android:background="?attr/xui_config_color_separator_light" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/alarm_flash_effect"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<com.xuexiang.xui.widget.edittext.ClearEditText
|
||||||
|
android:id="@+id/et_flash_effect"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="5dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:hint="@string/alarm_flash_effect_tips"
|
||||||
|
android:textSize="@dimen/text_size_mini"
|
||||||
|
tools:ignore="SmallSp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
||||||
|
android:id="@+id/bt_insert_flash_effect_1"
|
||||||
|
style="@style/insertButtonStyle"
|
||||||
|
android:text="@string/alarm_flash_effect_1" />
|
||||||
|
|
||||||
|
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
||||||
|
android:id="@+id/bt_insert_flash_effect_2"
|
||||||
|
style="@style/insertButtonStyle"
|
||||||
|
android:layout_marginStart="5dp"
|
||||||
|
android:text="@string/alarm_flash_effect_2" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="5dp"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/alarm_repeat_times"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<com.xuexiang.xui.widget.picker.XSeekBar
|
||||||
|
android:id="@+id/xsb_flash_times"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="5dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:padding="0dp"
|
||||||
|
app:xsb_max="30"
|
||||||
|
app:xsb_min="0" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
</androidx.core.widget.NestedScrollView>
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
@ -161,65 +161,13 @@
|
|||||||
android:inputType="textMultiLine"
|
android:inputType="textMultiLine"
|
||||||
app:met_clearButton="true" />
|
app:met_clearButton="true" />
|
||||||
|
|
||||||
<LinearLayout
|
<GridLayout
|
||||||
|
android:id="@+id/gl_sms_template"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal">
|
android:layout_gravity="center"
|
||||||
|
android:columnCount="4"
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
android:orientation="horizontal" />
|
||||||
android:id="@+id/bt_insert_sender"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:text="@string/insert_sender" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_content"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:text="@string/insert_content" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_extra"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:text="@string/insert_extra" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_sender_app"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:text="@string/insert_sender_app" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_uid"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:text="@string/insert_uid" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_title_app"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:text="@string/insert_title_app" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_content_app"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:text="@string/insert_content_app" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_time"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:text="@string/insert_time" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
|
||||||
android:id="@+id/bt_insert_device_name"
|
|
||||||
style="@style/insertButtonStyle"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:text="@string/insert_device_name" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@
|
|||||||
android:id="@+id/tv_description"
|
android:id="@+id/tv_description"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/task_battery_tips"
|
android:text="@string/task_charge_tips"
|
||||||
android:textSize="@dimen/text_size_mini"
|
android:textSize="@dimen/text_size_mini"
|
||||||
tools:ignore="SmallSp" />
|
tools:ignore="SmallSp" />
|
||||||
|
|
||||||
|
@ -1,5 +1,35 @@
|
|||||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
|
<string name="insert_tag_from">Phone Number</string>
|
||||||
|
<string name="insert_tag_sms">SMS Content</string>
|
||||||
|
<string name="insert_tag_package_name">Package Name</string>
|
||||||
|
<string name="insert_tag_app_name">App Name</string>
|
||||||
|
<string name="insert_tag_title">Inform Title</string>
|
||||||
|
<string name="insert_tag_msg">Inform Content</string>
|
||||||
|
<string name="insert_tag_card_slot">SIM Label</string>
|
||||||
|
<string name="insert_tag_card_subid">SIM SubId</string>
|
||||||
|
<string name="insert_tag_receive_time">Receive Time</string>
|
||||||
|
<string name="insert_tag_current_time">Current Time</string>
|
||||||
|
<string name="insert_tag_device_name">Device Name</string>
|
||||||
|
<string name="insert_tag_app_version">SmsF Version</string>
|
||||||
|
<string name="insert_tag_call_type">Call Type</string>
|
||||||
|
<string name="insert_tag_location">Location</string>
|
||||||
|
<string name="insert_tag_location_longitude">Longitude</string>
|
||||||
|
<string name="insert_tag_location_latitude">Latitude</string>
|
||||||
|
<string name="insert_tag_location_address">Address</string>
|
||||||
|
<string name="insert_tag_battery_pct">Battery Percentage</string>
|
||||||
|
<string name="insert_tag_battery_status">Battery Status</string>
|
||||||
|
<string name="insert_tag_battery_plugged">Charging Method</string>
|
||||||
|
<string name="insert_tag_battery_info">Complete Battery Info</string>
|
||||||
|
<string name="insert_tag_battery_info_simple">Simplified Battery Info</string>
|
||||||
|
<string name="insert_tag_uid">UID</string>
|
||||||
|
<string name="insert_tag_ipv4">Public IPv4</string>
|
||||||
|
<string name="insert_tag_ipv6">Public IPv6</string>
|
||||||
|
<string name="insert_tag_ip_list">IP List</string>
|
||||||
|
<string name="insert_tag_net_type">Network Status</string>
|
||||||
|
<string name="insert_tag_contact_name">Contact Name</string>
|
||||||
|
<string name="insert_tag_phone_area">Phone Area</string>
|
||||||
|
|
||||||
<string name="type_param_sms">Sms</string>
|
<string name="type_param_sms">Sms</string>
|
||||||
<string name="type_param_call">Call</string>
|
<string name="type_param_call">Call</string>
|
||||||
<string name="type_param_app">App</string>
|
<string name="type_param_app">App</string>
|
||||||
@ -58,6 +88,7 @@
|
|||||||
<string name="url_help">https://gitee.com/pp/SmsForwarder/wikis/pages</string>
|
<string name="url_help">https://gitee.com/pp/SmsForwarder/wikis/pages</string>
|
||||||
<string name="url_donation_link">https://gitee.com/pp/SmsForwarder.wiki/raw/master/%E6%89%93%E8%B5%8F%E5%90%8D%E5%8D%95.md</string>
|
<string name="url_donation_link">https://gitee.com/pp/SmsForwarder.wiki/raw/master/%E6%89%93%E8%B5%8F%E5%90%8D%E5%8D%95.md</string>
|
||||||
<string name="url_wechat_miniprogram">https://gitee.com/pp/SmsForwarder/raw/main/pic/wechat_miniprogram.jpg</string>
|
<string name="url_wechat_miniprogram">https://gitee.com/pp/SmsForwarder/raw/main/pic/wechat_miniprogram.jpg</string>
|
||||||
|
<string name="url_tips">https://gitee.com/pp/SmsForwarder.wiki/raw/master/tips_en.json</string>
|
||||||
|
|
||||||
<string name="lab_yes">Yes</string>
|
<string name="lab_yes">Yes</string>
|
||||||
<string name="lab_no">No</string>
|
<string name="lab_no">No</string>
|
||||||
@ -186,6 +217,13 @@
|
|||||||
<string name="switch_rule_status">Enable This Forwarding Rule</string>
|
<string name="switch_rule_status">Enable This Forwarding Rule</string>
|
||||||
<string name="invalid_match_value">The matched value cannot be null</string>
|
<string name="invalid_match_value">The matched value cannot be null</string>
|
||||||
<string name="invalid_call_type">The call type is incorrect, you can only enter any number from 1 to 6.</string>
|
<string name="invalid_call_type">The call type is incorrect, you can only enter any number from 1 to 6.</string>
|
||||||
|
<string name="mon">MON</string>
|
||||||
|
<string name="tue">TUE</string>
|
||||||
|
<string name="wed">WED</string>
|
||||||
|
<string name="thu">THU</string>
|
||||||
|
<string name="fri">FRI</string>
|
||||||
|
<string name="sat">SAT</string>
|
||||||
|
<string name="sun">SUN</string>
|
||||||
<!--SenderActivity-->
|
<!--SenderActivity-->
|
||||||
<string name="delete_sender_title">Delete confirmation</string>
|
<string name="delete_sender_title">Delete confirmation</string>
|
||||||
<string name="delete_sender_tips">Are you sure to delete this sender?</string>
|
<string name="delete_sender_tips">Are you sure to delete this sender?</string>
|
||||||
@ -215,8 +253,8 @@
|
|||||||
<string name="invalid_wework_agent">CoreID, AgentID, and Secret cannot be empty</string>
|
<string name="invalid_wework_agent">CoreID, AgentID, and Secret cannot be empty</string>
|
||||||
<string name="invalid_dingtalk_inner_robot">AgentId, AppKey, AppSecret, and UserIds cannot be empty</string>
|
<string name="invalid_dingtalk_inner_robot">AgentId, AppKey, AppSecret, and UserIds cannot be empty</string>
|
||||||
<string name="invalid_phone_num">The receiving phone number cannot be empty</string>
|
<string name="invalid_phone_num">The receiving phone number cannot be empty</string>
|
||||||
<string name="invalid_multi_match">Malformed multiple match rule line %s</string>
|
<string name="invalid_multi_match">Malformed multiple match rule line %d</string>
|
||||||
<string name="invalid_regex_replace">Incorrect format on line %s of regex replacement</string>
|
<string name="invalid_regex_replace">Incorrect format on line %d of regex replacement</string>
|
||||||
<string name="invalid_message_card">The Message Card Json is invalid.</string>
|
<string name="invalid_message_card">The Message Card Json is invalid.</string>
|
||||||
<string name="email_host">Host</string>
|
<string name="email_host">Host</string>
|
||||||
<string name="smtp_port">Port</string>
|
<string name="smtp_port">Port</string>
|
||||||
@ -271,6 +309,10 @@
|
|||||||
<string name="TelegramApiToken">ApiToken or Custom Proxy Address (startwith http)</string>
|
<string name="TelegramApiToken">ApiToken or Custom Proxy Address (startwith http)</string>
|
||||||
<string name="TelegramChatId">ChatId</string>
|
<string name="TelegramChatId">ChatId</string>
|
||||||
<string name="Method" formatted="false">Method</string>
|
<string name="Method" formatted="false">Method</string>
|
||||||
|
<string name="parse_mode">Parse Mode</string>
|
||||||
|
<string name="parse_mode_text">Text</string>
|
||||||
|
<string name="parse_mode_html">Html</string>
|
||||||
|
<string name="parse_mode_markdown">MarkdownV2</string>
|
||||||
|
|
||||||
<string name="SmsSimSlot">SIM Slot</string>
|
<string name="SmsSimSlot">SIM Slot</string>
|
||||||
<string name="same_source">Same source</string>
|
<string name="same_source">Same source</string>
|
||||||
@ -310,17 +352,10 @@
|
|||||||
<string name="custom_template">Custom templates</string>
|
<string name="custom_template">Custom templates</string>
|
||||||
<string name="custom_template_tips">Tip: Insert labels as needed; Leave blank to apply default template</string>
|
<string name="custom_template_tips">Tip: Insert labels as needed; Leave blank to apply default template</string>
|
||||||
<string name="insert_sender">Phone</string>
|
<string name="insert_sender">Phone</string>
|
||||||
<string name="insert_sender_app">PackageName</string>
|
|
||||||
<string name="insert_uid">UID</string>
|
|
||||||
<string name="insert_content">SMS</string>
|
|
||||||
<string name="insert_title_app">InformTitle</string>
|
|
||||||
<string name="insert_content_app">InformContent</string>
|
|
||||||
<string name="insert_extra">SIM</string>
|
|
||||||
<string name="insert_time">Time</string>
|
|
||||||
<string name="insert_device_name">Device</string>
|
|
||||||
<string name="battery_setting">Battery Optimization</string>
|
<string name="battery_setting">Battery Optimization</string>
|
||||||
<string name="battery_setting_tips">Set it to manual management, including automatic startup, associated startup, and background running</string>
|
<string name="battery_setting_tips">Set it to manual management, including automatic startup, associated startup, and background running</string>
|
||||||
<string name="unknown_number">Unknown Number</string>
|
<string name="unknown_number">Unknown Number</string>
|
||||||
|
<string name="unknown_area">Unknown Area</string>
|
||||||
<string name="unsupport">Your phone does not support this setting</string>
|
<string name="unsupport">Your phone does not support this setting</string>
|
||||||
<string name="isIgnored">Set successfully!</string>
|
<string name="isIgnored">Set successfully!</string>
|
||||||
<string name="isIgnored2">Can not directly operate the system power saving optimization Settings</string>
|
<string name="isIgnored2">Can not directly operate the system power saving optimization Settings</string>
|
||||||
@ -357,6 +392,7 @@
|
|||||||
<string name="appicon">App Icon</string>
|
<string name="appicon">App Icon</string>
|
||||||
<string name="user_app">User App</string>
|
<string name="user_app">User App</string>
|
||||||
<string name="system_app">System App</string>
|
<string name="system_app">System App</string>
|
||||||
|
<string name="tips_get_installed_apps">Please grant GET_INSTALLED_APPS permission</string>
|
||||||
<string name="tips_notification">Please grant Notification permission, in order to keep the App alive!</string>
|
<string name="tips_notification">Please grant Notification permission, in order to keep the App alive!</string>
|
||||||
<string name="tips_notification_listener">Please grant Notification reading permission to SmsForwarder, before other Apps\'s notification could be forwarded. Forwarding automatically canceled!</string>
|
<string name="tips_notification_listener">Please grant Notification reading permission to SmsForwarder, before other Apps\'s notification could be forwarded. Forwarding automatically canceled!</string>
|
||||||
<string name="pushplus_website">Official website</string>
|
<string name="pushplus_website">Official website</string>
|
||||||
@ -403,6 +439,7 @@
|
|||||||
<string name="GotifyWebServer">WebServer</string>
|
<string name="GotifyWebServer">WebServer</string>
|
||||||
<string name="GotifyWebServerTips"><![CDATA[eg.: https://push.ppps.cn/message?token=<apptoken>]]></string>
|
<string name="GotifyWebServerTips"><![CDATA[eg.: https://push.ppps.cn/message?token=<apptoken>]]></string>
|
||||||
<string name="title_template">Title Template</string>
|
<string name="title_template">Title Template</string>
|
||||||
|
<string name="auto_copy">Auto Copy</string>
|
||||||
<string name="priority">Priority(1 – 9)</string>
|
<string name="priority">Priority(1 – 9)</string>
|
||||||
<string name="dingtalk_robot">Dingtalk Group Bot</string>
|
<string name="dingtalk_robot">Dingtalk Group Bot</string>
|
||||||
<string name="dingtalk_inner_robot">Dingtalk Inner Bot</string>
|
<string name="dingtalk_inner_robot">Dingtalk Inner Bot</string>
|
||||||
@ -446,7 +483,7 @@
|
|||||||
<string name="interval_label">Increasing Interval</string>
|
<string name="interval_label">Increasing Interval</string>
|
||||||
<string name="timeout_label">Single Timeout</string>
|
<string name="timeout_label">Single Timeout</string>
|
||||||
<string name="seconds">secs</string>
|
<string name="seconds">secs</string>
|
||||||
<string name="seconds_n">%s sec</string>
|
<string name="seconds_n">%d sec</string>
|
||||||
<string name="retry_label">Max Retries</string>
|
<string name="retry_label">Max Retries</string>
|
||||||
<string name="test_sender_sms">[%s] Congratulations, the sender test is successful, please continue to add forwarding rules!</string>
|
<string name="test_sender_sms">[%s] Congratulations, the sender test is successful, please continue to add forwarding rules!</string>
|
||||||
<string name="test_sender_name">Test Channel</string>
|
<string name="test_sender_name">Test Channel</string>
|
||||||
@ -512,7 +549,7 @@
|
|||||||
<string name="no">No</string>
|
<string name="no">No</string>
|
||||||
<string name="refresh">Refresh</string>
|
<string name="refresh">Refresh</string>
|
||||||
<string name="tip_can_not_get_sim_infos">Please confirm that the app permission [Get mobile phone information] is [Always allow]</string>
|
<string name="tip_can_not_get_sim_infos">Please confirm that the app permission [Get mobile phone information] is [Always allow]</string>
|
||||||
<string name="tip_can_not_get_sim_info">The SIM card information in the card slot %s has not been obtained</string>
|
<string name="tip_can_not_get_sim_info">The SIM card information in the card slot %d has not been obtained</string>
|
||||||
<string name="auto_check">Auto check</string>
|
<string name="auto_check">Auto check</string>
|
||||||
<string name="check_update">Check</string>
|
<string name="check_update">Check</string>
|
||||||
<string name="join_preview_program">Join Preview Program</string>
|
<string name="join_preview_program">Join Preview Program</string>
|
||||||
@ -534,12 +571,13 @@
|
|||||||
|
|
||||||
<string name="bark_server">Bark-Server</string>
|
<string name="bark_server">Bark-Server</string>
|
||||||
<string name="bark_server_tips">e.g. https://api.day.app/XXXXXXXX/</string>
|
<string name="bark_server_tips">e.g. https://api.day.app/XXXXXXXX/</string>
|
||||||
<string name="bark_server_regex">^https?://[^/]+/[^/]+/$</string>
|
<string name="bark_server_regex">^https?://[^/]+/[^/]+/.*</string>
|
||||||
<string name="bark_server_error">The Url format is wrong, e.g. https://api.day.app/XXXXXXXX/</string>
|
<string name="bark_server_error">The Url format is wrong, e.g. https://api.day.app/XXXXXXXX/</string>
|
||||||
<string name="bark_group">Group Name</string>
|
<string name="bark_group">Group Name</string>
|
||||||
<string name="bark_group_tips">Opt., e.g. SmsForwarder</string>
|
<string name="bark_group_tips">Opt., e.g. SmsForwarder</string>
|
||||||
<string name="bark_icon">Message Icon</string>
|
<string name="bark_icon">Message Icon</string>
|
||||||
<string name="bark_icon_tips">Opt., fill in Url, the picture should not be too big</string>
|
<string name="bark_icon_tips">Opt., fill in Url, the picture should not be too big</string>
|
||||||
|
<string name="bark_call">Keep Reminding</string>
|
||||||
<string name="bark_sound">Message Sound</string>
|
<string name="bark_sound">Message Sound</string>
|
||||||
<string name="bark_sound_tips">Opt., e.g. minuet.caf</string>
|
<string name="bark_sound_tips">Opt., e.g. minuet.caf</string>
|
||||||
<string name="bark_badge">Message Badge</string>
|
<string name="bark_badge">Message Badge</string>
|
||||||
@ -606,7 +644,7 @@
|
|||||||
<string name="extra_app">Extra Apps</string>
|
<string name="extra_app">Extra Apps</string>
|
||||||
<string name="extra_app_hint">One package name per line\nEnable async loading of the App list for selection.</string>
|
<string name="extra_app_hint">One package name per line\nEnable async loading of the App list for selection.</string>
|
||||||
<string name="choose_app_hint">Drop-down selection to get package name, keyword fuzzy matching APP name</string>
|
<string name="choose_app_hint">Drop-down selection to get package name, keyword fuzzy matching APP name</string>
|
||||||
<string name="regex_multi_match" tools:ignore="TypographyDashes">^\\s*(AND|OR)\\s(IS|NOTIS)\\s(PHONE_NUM|PACKAGE_NAME|MSG_CONTENT|INFORM_CONTENT|INFORM_TITLE|CARD_SLOT|CALL_TYPE)\\s(EQUALS|CONTAIN|NOTCONTAIN|STARTWITH|ENDWITH|REGEX)\\s(.*)$</string>
|
<string name="regex_multi_match" tools:ignore="TypographyDashes">^\\s*(AND|OR)\\s(IS|NOTIS)\\s(PHONE_NUM|PACKAGE_NAME|MSG_CONTENT|INFORM_CONTENT|INFORM_TITLE|CARD_SLOT|CALL_TYPE|UID)\\s(EQUALS|CONTAIN|NOTCONTAIN|STARTWITH|ENDWITH|REGEX)\\s(.*)$</string>
|
||||||
<string name="privacy_content_1">Welcome to</string>
|
<string name="privacy_content_1">Welcome to</string>
|
||||||
<string name="privacy_content_2">We understand the importance of personal information to you and thank you for your trust in us.\n</string>
|
<string name="privacy_content_2">We understand the importance of personal information to you and thank you for your trust in us.\n</string>
|
||||||
<string name="privacy_content_3">In order to better protect your rights and comply with relevant regulatory requirements, we will pass "</string>
|
<string name="privacy_content_3">In order to better protect your rights and comply with relevant regulatory requirements, we will pass "</string>
|
||||||
@ -803,7 +841,7 @@
|
|||||||
<string name="debug_mode_tips">Save Log.* to file for troubleshooting; export to download directory.</string>
|
<string name="debug_mode_tips">Save Log.* to file for troubleshooting; export to download directory.</string>
|
||||||
<string name="optional_components">Opt.:</string>
|
<string name="optional_components">Opt.:</string>
|
||||||
<string name="enable_cactus">Enable Cactus Keep Alive</string>
|
<string name="enable_cactus">Enable Cactus Keep Alive</string>
|
||||||
<string name="enabe_cactus_tips">Dual foreground service/JobScheduler/WorkManager/1px/silent music</string>
|
<string name="enable_cactus_tips">Dual foreground service/JobScheduler/WorkManager/1px/silent music</string>
|
||||||
<string name="load_app_list">Get installed app info async at startup</string>
|
<string name="load_app_list">Get installed app info async at startup</string>
|
||||||
<string name="load_app_list_tips">Used to speed up entering the application list/editing forwarding rules drop-down selection/replacement {{APP_NAME}}</string>
|
<string name="load_app_list_tips">Used to speed up entering the application list/editing forwarding rules drop-down selection/replacement {{APP_NAME}}</string>
|
||||||
<string name="load_app_list_toast">A type must be selected when enabling asynchronous loading of the list of installed apps</string>
|
<string name="load_app_list_toast">A type must be selected when enabling asynchronous loading of the list of installed apps</string>
|
||||||
@ -940,6 +978,7 @@
|
|||||||
<string name="task_charge">Charge</string>
|
<string name="task_charge">Charge</string>
|
||||||
<string name="task_lock_screen">Screen Off/On</string>
|
<string name="task_lock_screen">Screen Off/On</string>
|
||||||
<string name="task_lock_screen_tips">Trigger upon screen lock/unlock instantly or after a set time.</string>
|
<string name="task_lock_screen_tips">Trigger upon screen lock/unlock instantly or after a set time.</string>
|
||||||
|
<string name="task_charge_tips">Triggered when the charging state meets the conditions.</string>
|
||||||
<string name="task_sms">SMS</string>
|
<string name="task_sms">SMS</string>
|
||||||
<string name="task_sms_when">received SMS broadcast from %s</string>
|
<string name="task_sms_when">received SMS broadcast from %s</string>
|
||||||
<string name="task_call">Call</string>
|
<string name="task_call">Call</string>
|
||||||
@ -963,8 +1002,8 @@
|
|||||||
<string name="task_rule_tips">Control the enable/disable of "Rules"</string>
|
<string name="task_rule_tips">Control the enable/disable of "Rules"</string>
|
||||||
<string name="task_sender">Channels On/Off</string>
|
<string name="task_sender">Channels On/Off</string>
|
||||||
<string name="task_sender_tips">Control the enable/disable of "Senders"</string>
|
<string name="task_sender_tips">Control the enable/disable of "Senders"</string>
|
||||||
<string name="task_alarm">Alarm</string>
|
<string name="task_alarm">Alarm Reminder</string>
|
||||||
<string name="task_alarm_tips">Alarm</string>
|
<string name="task_alarm_tips">Play music/vibrate phone to remind</string>
|
||||||
<string name="task_resend">Resend Message</string>
|
<string name="task_resend">Resend Message</string>
|
||||||
<string name="task_resend_tips">Resend forwarded records since N hours ago, 0=ALL</string>
|
<string name="task_resend_tips">Resend forwarded records since N hours ago, 0=ALL</string>
|
||||||
<string name="task_resend_desc" formatted="false">Resend forwarding records since %s hours ago for %s</string>
|
<string name="task_resend_desc" formatted="false">Resend forwarding records since %s hours ago for %s</string>
|
||||||
@ -1108,16 +1147,30 @@
|
|||||||
<string name="chat_id">Chat ID</string>
|
<string name="chat_id">Chat ID</string>
|
||||||
<string name="receive_id">Receive ID</string>
|
<string name="receive_id">Receive ID</string>
|
||||||
<string name="toast_location_not_enabled">Location is not enabled, Please go to system settings and activate it.</string>
|
<string name="toast_location_not_enabled">Location is not enabled, Please go to system settings and activate it.</string>
|
||||||
|
<string name="toast_bluetooth_not_enabled">Bluetooth is not enabled, Please go to system settings and activate it.</string>
|
||||||
<string name="task_condition_check_again">Recheck when delaying execution.</string>
|
<string name="task_condition_check_again">Recheck when delaying execution.</string>
|
||||||
<string name="task_condition_check_again_tips">When used as a triggering condition, recheck during delayed action execution.</string>
|
<string name="task_condition_check_again_tips">When used as a triggering condition, recheck during delayed action execution.</string>
|
||||||
|
|
||||||
<string name="start_alarm">Start Alarm</string>
|
<string name="start_alarm">Start Alarm</string>
|
||||||
<string name="stop_alarm">Stop Alarm</string>
|
<string name="stop_alarm">Stop Alarm</string>
|
||||||
<string name="alarm_play_settings">Playback Settings</string>
|
<string name="alarm_play_settings">Play Music</string>
|
||||||
<string name="alarm_music">Specify Music</string>
|
<string name="alarm_music">Specify Music</string>
|
||||||
<string name="alarm_music_tips">Opt., download mp3/ogg/wav to the Download directory.</string>
|
<string name="alarm_music_tips">Opt., download mp3/ogg/wav to the Download directory.</string>
|
||||||
<string name="alarm_volume">Alarm Volume</string>
|
<string name="alarm_volume">Alarm Volume</string>
|
||||||
<string name="alarm_play_times">Play Times(0=Infinite)</string>
|
<string name="alarm_play_times">Play Times(0=Infinite)</string>
|
||||||
|
<string name="alarm_vibrate_settings">Vibrate Phone</string>
|
||||||
|
<string name="alarm_repeat_times">Repeat Times(0=Infinite)</string>
|
||||||
|
<string name="alarm_vibration_effect">Vibration Effect</string>
|
||||||
|
<string name="alarm_vibration_effect_tips">Syntax: =[strong], -[weak], _[no], 100ms each</string>
|
||||||
|
<string name="alarm_vibration_effect_1">Strong vibration</string>
|
||||||
|
<string name="alarm_vibration_effect_2">Weak vibration</string>
|
||||||
|
<string name="alarm_vibration_effect_3">No vibration</string>
|
||||||
|
<string name="alarm_flash_settings">Flash Phone</string>
|
||||||
|
<string name="alarm_flash_effect">Flash Effect</string>
|
||||||
|
<string name="alarm_flash_effect_tips">Syntax: 1 or X [turn on flash], 0 or O [turn off flash], each time 100ms</string>
|
||||||
|
<string name="alarm_flash_effect_1">Turn on flash 100ms</string>
|
||||||
|
<string name="alarm_flash_effect_2">Turn off flash 100ms</string>
|
||||||
|
<string name="alarm_settings_error">At least one of Play Music/Vibrate Phone/Flash Phone must be enabled</string>
|
||||||
|
|
||||||
<string name="invalid_tag" formatted="false">%s tag is invalid: %s</string>
|
<string name="invalid_tag" formatted="false">%s tag is invalid: %s</string>
|
||||||
<string name="invalid_task_name">Please input task name.</string>
|
<string name="invalid_task_name">Please input task name.</string>
|
||||||
@ -1140,4 +1193,5 @@
|
|||||||
<string name="bluetooth_not_supported">Bluetooth not supported.</string>
|
<string name="bluetooth_not_supported">Bluetooth not supported.</string>
|
||||||
<string name="start_discovery">Discovery</string>
|
<string name="start_discovery">Discovery</string>
|
||||||
<string name="invalid_bluetooth_mac_address">Bluetooth Mac Address is invalid, eg. AA:BB:CC:DD:EE:FF</string>
|
<string name="invalid_bluetooth_mac_address">Bluetooth Mac Address is invalid, eg. AA:BB:CC:DD:EE:FF</string>
|
||||||
|
<string name="auto_start_redmi"><![CDATA[RedMi: Authorization Management -> Self-Start Management -> Allow Apps to Self-Start]]></string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -1,5 +1,35 @@
|
|||||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
|
<string name="insert_tag_from">来源号码</string>
|
||||||
|
<string name="insert_tag_sms">短信内容</string>
|
||||||
|
<string name="insert_tag_package_name">APP包名</string>
|
||||||
|
<string name="insert_tag_app_name">APP应用名</string>
|
||||||
|
<string name="insert_tag_title">通知标题</string>
|
||||||
|
<string name="insert_tag_msg">通知内容</string>
|
||||||
|
<string name="insert_tag_card_slot">卡槽备注</string>
|
||||||
|
<string name="insert_tag_card_subid">卡槽主键</string>
|
||||||
|
<string name="insert_tag_receive_time">接收时间</string>
|
||||||
|
<string name="insert_tag_current_time">当前时间</string>
|
||||||
|
<string name="insert_tag_device_name">设备名称</string>
|
||||||
|
<string name="insert_tag_app_version">SmsF版本</string>
|
||||||
|
<string name="insert_tag_call_type">通话类型</string>
|
||||||
|
<string name="insert_tag_location">定位信息</string>
|
||||||
|
<string name="insert_tag_location_longitude">定位经度</string>
|
||||||
|
<string name="insert_tag_location_latitude">定位纬度</string>
|
||||||
|
<string name="insert_tag_location_address">定位地址</string>
|
||||||
|
<string name="insert_tag_battery_pct">电池电量</string>
|
||||||
|
<string name="insert_tag_battery_status">电池状态</string>
|
||||||
|
<string name="insert_tag_battery_plugged">充电方式</string>
|
||||||
|
<string name="insert_tag_battery_info">电池完整信息</string>
|
||||||
|
<string name="insert_tag_battery_info_simple">电池简单信息</string>
|
||||||
|
<string name="insert_tag_uid">用户UID</string>
|
||||||
|
<string name="insert_tag_ipv4">公网IPv4</string>
|
||||||
|
<string name="insert_tag_ipv6">公网IPv6</string>
|
||||||
|
<string name="insert_tag_ip_list">IP地址列表</string>
|
||||||
|
<string name="insert_tag_net_type">网络状态</string>
|
||||||
|
<string name="insert_tag_contact_name">来源姓名</string>
|
||||||
|
<string name="insert_tag_phone_area">来源归属</string>
|
||||||
|
|
||||||
<string name="type_param_sms">短信</string>
|
<string name="type_param_sms">短信</string>
|
||||||
<string name="type_param_call">通话</string>
|
<string name="type_param_call">通话</string>
|
||||||
<string name="type_param_app">应用</string>
|
<string name="type_param_app">应用</string>
|
||||||
@ -58,6 +88,7 @@
|
|||||||
<string name="url_help">https://gitee.com/pp/SmsForwarder/wikis/pages</string>
|
<string name="url_help">https://gitee.com/pp/SmsForwarder/wikis/pages</string>
|
||||||
<string name="url_donation_link">https://gitee.com/pp/SmsForwarder.wiki/raw/master/%E6%89%93%E8%B5%8F%E5%90%8D%E5%8D%95.md</string>
|
<string name="url_donation_link">https://gitee.com/pp/SmsForwarder.wiki/raw/master/%E6%89%93%E8%B5%8F%E5%90%8D%E5%8D%95.md</string>
|
||||||
<string name="url_wechat_miniprogram">https://gitee.com/pp/SmsForwarder/raw/main/pic/wechat_miniprogram.jpg</string>
|
<string name="url_wechat_miniprogram">https://gitee.com/pp/SmsForwarder/raw/main/pic/wechat_miniprogram.jpg</string>
|
||||||
|
<string name="url_tips">https://gitee.com/pp/SmsForwarder.wiki/raw/master/tips.json</string>
|
||||||
|
|
||||||
<string name="lab_yes">是</string>
|
<string name="lab_yes">是</string>
|
||||||
<string name="lab_no">否</string>
|
<string name="lab_no">否</string>
|
||||||
@ -187,6 +218,13 @@
|
|||||||
<string name="switch_rule_status">启用该条转发规则</string>
|
<string name="switch_rule_status">启用该条转发规则</string>
|
||||||
<string name="invalid_match_value">匹配的值不可为空</string>
|
<string name="invalid_match_value">匹配的值不可为空</string>
|
||||||
<string name="invalid_call_type">通话类型不正确,只能填写1到6的任意一个数字</string>
|
<string name="invalid_call_type">通话类型不正确,只能填写1到6的任意一个数字</string>
|
||||||
|
<string name="mon">周一</string>
|
||||||
|
<string name="tue">周二</string>
|
||||||
|
<string name="wed">周三</string>
|
||||||
|
<string name="thu">周四</string>
|
||||||
|
<string name="fri">周五</string>
|
||||||
|
<string name="sat">周六</string>
|
||||||
|
<string name="sun">周日</string>
|
||||||
<!--SenderActivity-->
|
<!--SenderActivity-->
|
||||||
<string name="delete_sender_title">发送通道操作确认</string>
|
<string name="delete_sender_title">发送通道操作确认</string>
|
||||||
<string name="delete_sender_tips">删除发送通道后会级联删除其相关的转发规则、转发日志的所有记录!\n\n确定删除该条发送通道?</string>
|
<string name="delete_sender_tips">删除发送通道后会级联删除其相关的转发规则、转发日志的所有记录!\n\n确定删除该条发送通道?</string>
|
||||||
@ -216,8 +254,8 @@
|
|||||||
<string name="invalid_wework_agent">企业ID、AgentID、Secret都不能为空</string>
|
<string name="invalid_wework_agent">企业ID、AgentID、Secret都不能为空</string>
|
||||||
<string name="invalid_dingtalk_inner_robot">AgentId、AppKey、AppSecret、UserIds都不能为空</string>
|
<string name="invalid_dingtalk_inner_robot">AgentId、AppKey、AppSecret、UserIds都不能为空</string>
|
||||||
<string name="invalid_phone_num">接收手机号不能为空</string>
|
<string name="invalid_phone_num">接收手机号不能为空</string>
|
||||||
<string name="invalid_multi_match">多重匹配规则的第 %s 行格式有误</string>
|
<string name="invalid_multi_match">多重匹配规则的第 %d 行格式有误</string>
|
||||||
<string name="invalid_regex_replace">正则替换内容的第 %s 行格式有误</string>
|
<string name="invalid_regex_replace">正则替换内容的第 %d 行格式有误</string>
|
||||||
<string name="invalid_message_card">自定义消息卡片Json不合法</string>
|
<string name="invalid_message_card">自定义消息卡片Json不合法</string>
|
||||||
<string name="email_host">主机</string>
|
<string name="email_host">主机</string>
|
||||||
<string name="smtp_port">端口</string>
|
<string name="smtp_port">端口</string>
|
||||||
@ -272,6 +310,10 @@
|
|||||||
<string name="TelegramApiToken">ApiToken 或 自定义代理地址(http开头)</string>
|
<string name="TelegramApiToken">ApiToken 或 自定义代理地址(http开头)</string>
|
||||||
<string name="TelegramChatId">被通知人(或群组)的ChatId</string>
|
<string name="TelegramChatId">被通知人(或群组)的ChatId</string>
|
||||||
<string name="Method" formatted="false">请求方式</string>
|
<string name="Method" formatted="false">请求方式</string>
|
||||||
|
<string name="parse_mode">解析模式</string>
|
||||||
|
<string name="parse_mode_text">Text</string>
|
||||||
|
<string name="parse_mode_html">Html</string>
|
||||||
|
<string name="parse_mode_markdown">MarkdownV2</string>
|
||||||
|
|
||||||
<string name="SmsSimSlot">发送卡槽</string>
|
<string name="SmsSimSlot">发送卡槽</string>
|
||||||
<string name="same_source">原进原出</string>
|
<string name="same_source">原进原出</string>
|
||||||
@ -311,17 +353,10 @@
|
|||||||
<string name="custom_template">转发信息模版</string>
|
<string name="custom_template">转发信息模版</string>
|
||||||
<string name="custom_template_tips">Tip:按需插入内容标签;留空使用默认模版</string>
|
<string name="custom_template_tips">Tip:按需插入内容标签;留空使用默认模版</string>
|
||||||
<string name="insert_sender">来源号码</string>
|
<string name="insert_sender">来源号码</string>
|
||||||
<string name="insert_sender_app">APP包名</string>
|
|
||||||
<string name="insert_uid">UID</string>
|
|
||||||
<string name="insert_content">短信内容</string>
|
|
||||||
<string name="insert_title_app">通知标题</string>
|
|
||||||
<string name="insert_content_app">通知内容</string>
|
|
||||||
<string name="insert_extra">卡槽信息</string>
|
|
||||||
<string name="insert_time">接收时间</string>
|
|
||||||
<string name="insert_device_name">设备名称</string>
|
|
||||||
<string name="battery_setting">忽略电池优化设置</string>
|
<string name="battery_setting">忽略电池优化设置</string>
|
||||||
<string name="battery_setting_tips">请设置为手动管理:允许自启动、允许关联启动、允许后台运行</string>
|
<string name="battery_setting_tips">请设置为手动管理:允许自启动、允许关联启动、允许后台运行</string>
|
||||||
<string name="unknown_number">未知号码</string>
|
<string name="unknown_number">未知号码</string>
|
||||||
|
<string name="unknown_area">未知归属地</string>
|
||||||
<string name="unsupport">您的手机不支持此设置</string>
|
<string name="unsupport">您的手机不支持此设置</string>
|
||||||
<string name="isIgnored">已将省电优化设置为无限制(不优化)!</string>
|
<string name="isIgnored">已将省电优化设置为无限制(不优化)!</string>
|
||||||
<string name="isIgnored2">本界面无法直接操作系统的省电优化设置</string>
|
<string name="isIgnored2">本界面无法直接操作系统的省电优化设置</string>
|
||||||
@ -358,6 +393,7 @@
|
|||||||
<string name="appicon">应用图标</string>
|
<string name="appicon">应用图标</string>
|
||||||
<string name="user_app">用户应用</string>
|
<string name="user_app">用户应用</string>
|
||||||
<string name="system_app">系统应用</string>
|
<string name="system_app">系统应用</string>
|
||||||
|
<string name="tips_get_installed_apps">请先授予获取应用列表权限</string>
|
||||||
<string name="tips_notification">请先授予发送通知权限,有利于《短信转发器》保活!</string>
|
<string name="tips_notification">请先授予发送通知权限,有利于《短信转发器》保活!</string>
|
||||||
<string name="tips_notification_listener">请先授予《短信转发器》通知使用权,否则无法转发APP通知,已经自动关闭转发!</string>
|
<string name="tips_notification_listener">请先授予《短信转发器》通知使用权,否则无法转发APP通知,已经自动关闭转发!</string>
|
||||||
<string name="pushplus_website">官网地址</string>
|
<string name="pushplus_website">官网地址</string>
|
||||||
@ -404,6 +440,7 @@
|
|||||||
<string name="GotifyWebServer">WebServer</string>
|
<string name="GotifyWebServer">WebServer</string>
|
||||||
<string name="GotifyWebServerTips"><![CDATA[例:https://push.ppps.cn/message?token=<apptoken>]]></string>
|
<string name="GotifyWebServerTips"><![CDATA[例:https://push.ppps.cn/message?token=<apptoken>]]></string>
|
||||||
<string name="title_template">标题模板</string>
|
<string name="title_template">标题模板</string>
|
||||||
|
<string name="auto_copy">自动复制</string>
|
||||||
<string name="priority">优先级(1 – 9)</string>
|
<string name="priority">优先级(1 – 9)</string>
|
||||||
<string name="dingtalk_robot">钉钉群机器人</string>
|
<string name="dingtalk_robot">钉钉群机器人</string>
|
||||||
<string name="dingtalk_inner_robot">钉钉企业机器人</string>
|
<string name="dingtalk_inner_robot">钉钉企业机器人</string>
|
||||||
@ -447,7 +484,7 @@
|
|||||||
<string name="interval_label">递增间隔</string>
|
<string name="interval_label">递增间隔</string>
|
||||||
<string name="timeout_label">单次超时</string>
|
<string name="timeout_label">单次超时</string>
|
||||||
<string name="seconds">秒</string>
|
<string name="seconds">秒</string>
|
||||||
<string name="seconds_n">%s秒</string>
|
<string name="seconds_n">%d秒</string>
|
||||||
<string name="retry_label">最多重试</string>
|
<string name="retry_label">最多重试</string>
|
||||||
<string name="test_sender_sms">【%s】恭喜您,该发送通道测试成功,请继续添加转发规则!</string>
|
<string name="test_sender_sms">【%s】恭喜您,该发送通道测试成功,请继续添加转发规则!</string>
|
||||||
<string name="test_sender_name">测试通道</string>
|
<string name="test_sender_name">测试通道</string>
|
||||||
@ -513,7 +550,7 @@
|
|||||||
<string name="no">No</string>
|
<string name="no">No</string>
|
||||||
<string name="refresh">刷新</string>
|
<string name="refresh">刷新</string>
|
||||||
<string name="tip_can_not_get_sim_infos">无法获取卡槽信息,请确认应用权限【获取手机信息】为【始终允许】</string>
|
<string name="tip_can_not_get_sim_infos">无法获取卡槽信息,请确认应用权限【获取手机信息】为【始终允许】</string>
|
||||||
<string name="tip_can_not_get_sim_info">未获取到卡槽%s中的SIM卡信息</string>
|
<string name="tip_can_not_get_sim_info">未获取到卡槽%d中的SIM卡信息</string>
|
||||||
<string name="auto_check">启动时检查</string>
|
<string name="auto_check">启动时检查</string>
|
||||||
<string name="check_update">检查更新</string>
|
<string name="check_update">检查更新</string>
|
||||||
<string name="join_preview_program">加入SmsF预览体验计划</string>
|
<string name="join_preview_program">加入SmsF预览体验计划</string>
|
||||||
@ -535,12 +572,13 @@
|
|||||||
|
|
||||||
<string name="bark_server">Bark-Server</string>
|
<string name="bark_server">Bark-Server</string>
|
||||||
<string name="bark_server_tips">例:https://api.day.app/XXXXXXXX/</string>
|
<string name="bark_server_tips">例:https://api.day.app/XXXXXXXX/</string>
|
||||||
<string name="bark_server_regex">^https?://[^/]+/[^/]+/$</string>
|
<string name="bark_server_regex">^https?://[^/]+/[^/]+/.*</string>
|
||||||
<string name="bark_server_error">Url格式错误,例:https://api.day.app/XXXXXXXX/</string>
|
<string name="bark_server_error">Url格式错误,例:https://api.day.app/XXXXXXXX/</string>
|
||||||
<string name="bark_group">分组名称</string>
|
<string name="bark_group">分组名称</string>
|
||||||
<string name="bark_group_tips">可选,例:短信转发器</string>
|
<string name="bark_group_tips">可选,例:短信转发器</string>
|
||||||
<string name="bark_icon">消息图标</string>
|
<string name="bark_icon">消息图标</string>
|
||||||
<string name="bark_icon_tips">可选,填写Url,图片不要太大</string>
|
<string name="bark_icon_tips">可选,填写Url,图片不要太大</string>
|
||||||
|
<string name="bark_call">持续提醒</string>
|
||||||
<string name="bark_sound">消息声音</string>
|
<string name="bark_sound">消息声音</string>
|
||||||
<string name="bark_sound_tips">可选,例:minuet.caf</string>
|
<string name="bark_sound_tips">可选,例:minuet.caf</string>
|
||||||
<string name="bark_badge">消息角标</string>
|
<string name="bark_badge">消息角标</string>
|
||||||
@ -607,7 +645,7 @@
|
|||||||
<string name="extra_app">额外消除应用通知</string>
|
<string name="extra_app">额外消除应用通知</string>
|
||||||
<string name="extra_app_hint">一行一个包名\n开启异步加载App列表以便选择</string>
|
<string name="extra_app_hint">一行一个包名\n开启异步加载App列表以便选择</string>
|
||||||
<string name="choose_app_hint">下拉选择获取包名,关键字模糊匹配APP名称</string>
|
<string name="choose_app_hint">下拉选择获取包名,关键字模糊匹配APP名称</string>
|
||||||
<string name="regex_multi_match" tools:ignore="TypographyDashes">^\\s*(并且|或者)\\s(是|不是)\\s(手机号|APP包名|短信内容|通知内容|通知标题|卡槽信息|通话类型)\\s(相等|包含|不包含|开头|结尾|正则匹配)\\s(.*)$</string>
|
<string name="regex_multi_match" tools:ignore="TypographyDashes">^\\s*(并且|或者)\\s(是|不是)\\s(手机号|APP包名|短信内容|通知内容|通知标题|卡槽信息|通话类型|UID)\\s(相等|包含|不包含|开头|结尾|正则匹配)\\s(.*)$</string>
|
||||||
<string name="privacy_content_1">欢迎使用</string>
|
<string name="privacy_content_1">欢迎使用</string>
|
||||||
<string name="privacy_content_2">我们深知个人信息对你的重要性,也感谢你对我们的信任。\n</string>
|
<string name="privacy_content_2">我们深知个人信息对你的重要性,也感谢你对我们的信任。\n</string>
|
||||||
<string name="privacy_content_3">为了更好地保护你的权益,同时遵守相关监管的要求,我们将通过 </string>
|
<string name="privacy_content_3">为了更好地保护你的权益,同时遵守相关监管的要求,我们将通过 </string>
|
||||||
@ -695,7 +733,7 @@
|
|||||||
<string name="api_location_tips">远程查询手机定位,方便找回手机/防止老少走丢</string>
|
<string name="api_location_tips">远程查询手机定位,方便找回手机/防止老少走丢</string>
|
||||||
<string name="api_location_permission_tips">请先在【通用设置】中【启用GPS定位功能】</string>
|
<string name="api_location_permission_tips">请先在【通用设置】中【启用GPS定位功能】</string>
|
||||||
<string name="location_longitude">经度:%s</string>
|
<string name="location_longitude">经度:%s</string>
|
||||||
<string name="location_latitude">维度:%s</string>
|
<string name="location_latitude">纬度:%s</string>
|
||||||
<string name="location_address">地址:%s</string>
|
<string name="location_address">地址:%s</string>
|
||||||
<string name="location_time">时间:%s</string>
|
<string name="location_time">时间:%s</string>
|
||||||
<string name="location_provider">供应商:%s</string>
|
<string name="location_provider">供应商:%s</string>
|
||||||
@ -804,7 +842,7 @@
|
|||||||
<string name="debug_mode_tips">将Log.*写入文件,以便排查问题;可导出到下载目录</string>
|
<string name="debug_mode_tips">将Log.*写入文件,以便排查问题;可导出到下载目录</string>
|
||||||
<string name="optional_components">可选组件:</string>
|
<string name="optional_components">可选组件:</string>
|
||||||
<string name="enable_cactus">启用 Cactus 增强保活措施(会增加耗电)</string>
|
<string name="enable_cactus">启用 Cactus 增强保活措施(会增加耗电)</string>
|
||||||
<string name="enabe_cactus_tips">双进程前台服务/JobScheduler/WorkManager/1像素/无声音乐</string>
|
<string name="enable_cactus_tips">双进程前台服务/JobScheduler/WorkManager/1像素/无声音乐</string>
|
||||||
<string name="load_app_list">启动时异步获取已安装App列表</string>
|
<string name="load_app_list">启动时异步获取已安装App列表</string>
|
||||||
<string name="load_app_list_tips">用于加速进入应用列表/编辑转发规则下拉选择/替换{{APP_NAME}}</string>
|
<string name="load_app_list_tips">用于加速进入应用列表/编辑转发规则下拉选择/替换{{APP_NAME}}</string>
|
||||||
<string name="load_app_list_toast">开启异步获取已安装App列表时必选一个类型</string>
|
<string name="load_app_list_toast">开启异步获取已安装App列表时必选一个类型</string>
|
||||||
@ -939,6 +977,7 @@
|
|||||||
<string name="task_battery">电量使用</string>
|
<string name="task_battery">电量使用</string>
|
||||||
<string name="task_battery_tips">当剩余电量满足条件时触发</string>
|
<string name="task_battery_tips">当剩余电量满足条件时触发</string>
|
||||||
<string name="task_charge">充电状态</string>
|
<string name="task_charge">充电状态</string>
|
||||||
|
<string name="task_charge_tips">当充电状态满足条件时触发</string>
|
||||||
<string name="task_lock_screen">锁屏解锁</string>
|
<string name="task_lock_screen">锁屏解锁</string>
|
||||||
<string name="task_lock_screen_tips">在屏幕锁定或解锁后立即或指定时间触发</string>
|
<string name="task_lock_screen_tips">在屏幕锁定或解锁后立即或指定时间触发</string>
|
||||||
<string name="task_sms">短信广播</string>
|
<string name="task_sms">短信广播</string>
|
||||||
@ -964,8 +1003,8 @@
|
|||||||
<string name="task_rule_tips">控制【转发规则】的启用/禁用</string>
|
<string name="task_rule_tips">控制【转发规则】的启用/禁用</string>
|
||||||
<string name="task_sender">启停通道</string>
|
<string name="task_sender">启停通道</string>
|
||||||
<string name="task_sender_tips">控制【发送通道】的启用/禁用</string>
|
<string name="task_sender_tips">控制【发送通道】的启用/禁用</string>
|
||||||
<string name="task_alarm">声音警报</string>
|
<string name="task_alarm">警报提醒</string>
|
||||||
<string name="task_alarm_tips">声音警报</string>
|
<string name="task_alarm_tips">播放音乐/振动手机提醒</string>
|
||||||
<string name="task_resend">重发消息</string>
|
<string name="task_resend">重发消息</string>
|
||||||
<string name="task_resend_tips">自动重发N小时以来的转发记录,0=全部</string>
|
<string name="task_resend_tips">自动重发N小时以来的转发记录,0=全部</string>
|
||||||
<string name="task_resend_desc" formatted="false">自动重发%s小时以来%s的转发记录</string>
|
<string name="task_resend_desc" formatted="false">自动重发%s小时以来%s的转发记录</string>
|
||||||
@ -1059,7 +1098,7 @@
|
|||||||
<string name="calc_type_distance">根据GPS坐标计算距离</string>
|
<string name="calc_type_distance">根据GPS坐标计算距离</string>
|
||||||
<string name="calc_type_address">根据地址关键字判断</string>
|
<string name="calc_type_address">根据地址关键字判断</string>
|
||||||
<string name="longitude">经度</string>
|
<string name="longitude">经度</string>
|
||||||
<string name="latitude">维度</string>
|
<string name="latitude">纬度</string>
|
||||||
<string name="distance1">以经纬度为中心,</string>
|
<string name="distance1">以经纬度为中心,</string>
|
||||||
<string name="distance2">米半径建立电子围栏</string>
|
<string name="distance2">米半径建立电子围栏</string>
|
||||||
<string name="current_coordinates">当前坐标</string>
|
<string name="current_coordinates">当前坐标</string>
|
||||||
@ -1109,16 +1148,30 @@
|
|||||||
<string name="chat_id">Chat ID</string>
|
<string name="chat_id">Chat ID</string>
|
||||||
<string name="receive_id">消息接收者ID</string>
|
<string name="receive_id">消息接收者ID</string>
|
||||||
<string name="toast_location_not_enabled">位置服务未开启,请先前往系统设置中开启!</string>
|
<string name="toast_location_not_enabled">位置服务未开启,请先前往系统设置中开启!</string>
|
||||||
|
<string name="toast_bluetooth_not_enabled">蓝牙服务未开启,请先前往系统设置中开启!</string>
|
||||||
<string name="task_condition_check_again">延迟执行时再次校验</string>
|
<string name="task_condition_check_again">延迟执行时再次校验</string>
|
||||||
<string name="task_condition_check_again_tips">作为触发条件时,在延迟执行动作时再次校验是否满足</string>
|
<string name="task_condition_check_again_tips">作为触发条件时,在延迟执行动作时再次校验是否满足</string>
|
||||||
|
|
||||||
<string name="start_alarm">启动警报</string>
|
<string name="start_alarm">启动警报</string>
|
||||||
<string name="stop_alarm">停止警报</string>
|
<string name="stop_alarm">停止警报</string>
|
||||||
<string name="alarm_play_settings">播放设置</string>
|
<string name="alarm_play_settings">播放音乐</string>
|
||||||
<string name="alarm_music">指定音乐</string>
|
<string name="alarm_music">指定音乐</string>
|
||||||
<string name="alarm_music_tips">可选,下载 mp3/ogg/wav 到 Download 目录</string>
|
<string name="alarm_music_tips">可选,下载 mp3/ogg/wav 到 Download 目录</string>
|
||||||
<string name="alarm_volume">播放音量</string>
|
<string name="alarm_volume">播放音量</string>
|
||||||
<string name="alarm_play_times">播放次数(0=无限)</string>
|
<string name="alarm_play_times">播放次数(0=无限)</string>
|
||||||
|
<string name="alarm_vibrate_settings">振动手机</string>
|
||||||
|
<string name="alarm_repeat_times">重复次数(0=无限)</string>
|
||||||
|
<string name="alarm_vibration_effect">振动效果</string>
|
||||||
|
<string name="alarm_vibration_effect_tips">语法:=[强振动], -[弱震动], _[不振动], 每次100ms</string>
|
||||||
|
<string name="alarm_vibration_effect_1">强振动 100ms</string>
|
||||||
|
<string name="alarm_vibration_effect_2">弱振动 100ms</string>
|
||||||
|
<string name="alarm_vibration_effect_3">不振动 100ms</string>
|
||||||
|
<string name="alarm_flash_settings">闪烁手机</string>
|
||||||
|
<string name="alarm_flash_effect">闪光效果</string>
|
||||||
|
<string name="alarm_flash_effect_tips">语法:1或X[开启闪光灯], 0或O[关闭闪光灯], 每次100ms</string>
|
||||||
|
<string name="alarm_flash_effect_1">开启闪光灯 100ms</string>
|
||||||
|
<string name="alarm_flash_effect_2">关闭闪光灯 100ms</string>
|
||||||
|
<string name="alarm_settings_error">播放音乐/振动手机/闪烁手机必须至少开启一个</string>
|
||||||
|
|
||||||
<string name="invalid_tag" formatted="false">%s 标签无效:%s</string>
|
<string name="invalid_tag" formatted="false">%s 标签无效:%s</string>
|
||||||
<string name="invalid_task_name">请输入任务名称</string>
|
<string name="invalid_task_name">请输入任务名称</string>
|
||||||
@ -1141,4 +1194,5 @@
|
|||||||
<string name="bluetooth_not_supported">不支持蓝牙设备</string>
|
<string name="bluetooth_not_supported">不支持蓝牙设备</string>
|
||||||
<string name="start_discovery">搜索设备</string>
|
<string name="start_discovery">搜索设备</string>
|
||||||
<string name="invalid_bluetooth_mac_address">蓝牙设备MAC地址无效,例如:AA:BB:CC:DD:EE:FF</string>
|
<string name="invalid_bluetooth_mac_address">蓝牙设备MAC地址无效,例如:AA:BB:CC:DD:EE:FF</string>
|
||||||
|
<string name="auto_start_redmi"><![CDATA[红米手机:授权管理 -> 自启动管理 -> 允许应用自启动]]></string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -1,5 +1,35 @@
|
|||||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
|
<string name="insert_tag_from">來源號碼</string>
|
||||||
|
<string name="insert_tag_sms">簡訊內容</string>
|
||||||
|
<string name="insert_tag_package_name">APP包名</string>
|
||||||
|
<string name="insert_tag_app_name">APP應用名</string>
|
||||||
|
<string name="insert_tag_title">通知標題</string>
|
||||||
|
<string name="insert_tag_msg">通知內容</string>
|
||||||
|
<string name="insert_tag_card_slot">卡槽備註</string>
|
||||||
|
<string name="insert_tag_card_subid">卡槽主鍵</string>
|
||||||
|
<string name="insert_tag_receive_time">接收時間</string>
|
||||||
|
<string name="insert_tag_current_time">當前時間</string>
|
||||||
|
<string name="insert_tag_device_name">設備名稱</string>
|
||||||
|
<string name="insert_tag_app_version">SmsF版本</string>
|
||||||
|
<string name="insert_tag_call_type">通話類型</string>
|
||||||
|
<string name="insert_tag_location">定位資訊</string>
|
||||||
|
<string name="insert_tag_location_longitude">定位經度</string>
|
||||||
|
<string name="insert_tag_location_latitude">定位緯度</string>
|
||||||
|
<string name="insert_tag_location_address">定位地址</string>
|
||||||
|
<string name="insert_tag_battery_pct">電池電量</string>
|
||||||
|
<string name="insert_tag_battery_status">電池狀態</string>
|
||||||
|
<string name="insert_tag_battery_plugged">充電方式</string>
|
||||||
|
<string name="insert_tag_battery_info">電池完整資訊</string>
|
||||||
|
<string name="insert_tag_battery_info_simple">電池簡單資訊</string>
|
||||||
|
<string name="insert_tag_uid">用戶UID</string>
|
||||||
|
<string name="insert_tag_ipv4">公網IPv4</string>
|
||||||
|
<string name="insert_tag_ipv6">公網IPv6</string>
|
||||||
|
<string name="insert_tag_ip_list">IP地址列表</string>
|
||||||
|
<string name="insert_tag_net_type">網路狀態</string>
|
||||||
|
<string name="insert_tag_contact_name">來源姓名</string>
|
||||||
|
<string name="insert_tag_phone_area">来源歸屬</string>
|
||||||
|
|
||||||
<string name="type_param_sms">簡訊</string>
|
<string name="type_param_sms">簡訊</string>
|
||||||
<string name="type_param_call">通話</string>
|
<string name="type_param_call">通話</string>
|
||||||
<string name="type_param_app">應用</string>
|
<string name="type_param_app">應用</string>
|
||||||
@ -58,6 +88,7 @@
|
|||||||
<string name="url_help">https://gitee.com/pp/SmsForwarder/wikis/pages</string>
|
<string name="url_help">https://gitee.com/pp/SmsForwarder/wikis/pages</string>
|
||||||
<string name="url_donation_link">https://gitee.com/pp/SmsForwarder.wiki/raw/master/%E6%89%93%E8%B5%8F%E5%90%8D%E5%8D%95.md</string>
|
<string name="url_donation_link">https://gitee.com/pp/SmsForwarder.wiki/raw/master/%E6%89%93%E8%B5%8F%E5%90%8D%E5%8D%95.md</string>
|
||||||
<string name="url_wechat_miniprogram">https://gitee.com/pp/SmsForwarder/raw/main/pic/wechat_miniprogram.jpg</string>
|
<string name="url_wechat_miniprogram">https://gitee.com/pp/SmsForwarder/raw/main/pic/wechat_miniprogram.jpg</string>
|
||||||
|
<string name="url_tips">https://gitee.com/pp/SmsForwarder.wiki/raw/master/tips_tc.json</string>
|
||||||
|
|
||||||
<string name="lab_yes">是</string>
|
<string name="lab_yes">是</string>
|
||||||
<string name="lab_no">否</string>
|
<string name="lab_no">否</string>
|
||||||
@ -187,6 +218,13 @@
|
|||||||
<string name="switch_rule_status">啟用該條轉發規則</string>
|
<string name="switch_rule_status">啟用該條轉發規則</string>
|
||||||
<string name="invalid_match_value">匹配的值不可為空</string>
|
<string name="invalid_match_value">匹配的值不可為空</string>
|
||||||
<string name="invalid_call_type">通話類型不正確,只能填寫1到6的任意一個數字</string>
|
<string name="invalid_call_type">通話類型不正確,只能填寫1到6的任意一個數字</string>
|
||||||
|
<string name="mon">星期一</string>
|
||||||
|
<string name="tue">星期二</string>
|
||||||
|
<string name="wed">星期三</string>
|
||||||
|
<string name="thu">星期四</string>
|
||||||
|
<string name="fri">星期五</string>
|
||||||
|
<string name="sat">星期六</string>
|
||||||
|
<string name="sun">星期日</string>
|
||||||
<!--SenderActivity-->
|
<!--SenderActivity-->
|
||||||
<string name="delete_sender_title">發送通道操作確認</string>
|
<string name="delete_sender_title">發送通道操作確認</string>
|
||||||
<string name="delete_sender_tips">刪除發送通道後會級聯刪除其相關的轉發規則、轉發日誌的所有記錄!\n\n確定刪除該條發送通道?</string>
|
<string name="delete_sender_tips">刪除發送通道後會級聯刪除其相關的轉發規則、轉發日誌的所有記錄!\n\n確定刪除該條發送通道?</string>
|
||||||
@ -216,8 +254,8 @@
|
|||||||
<string name="invalid_wework_agent">企業ID、AgentID、Secret都不能為空</string>
|
<string name="invalid_wework_agent">企業ID、AgentID、Secret都不能為空</string>
|
||||||
<string name="invalid_dingtalk_inner_robot">AgentId、AppKey、AppSecret、UserIds都不能為空</string>
|
<string name="invalid_dingtalk_inner_robot">AgentId、AppKey、AppSecret、UserIds都不能為空</string>
|
||||||
<string name="invalid_phone_num">接收手機號不能為空</string>
|
<string name="invalid_phone_num">接收手機號不能為空</string>
|
||||||
<string name="invalid_multi_match">多重匹配規則的第 %s 行格式有誤</string>
|
<string name="invalid_multi_match">多重匹配規則的第 %d 行格式有誤</string>
|
||||||
<string name="invalid_regex_replace">正則替換內容的第 %s 行格式有誤</string>
|
<string name="invalid_regex_replace">正則替換內容的第 %d 行格式有誤</string>
|
||||||
<string name="invalid_message_card">自定義消息卡片Json不合法</string>
|
<string name="invalid_message_card">自定義消息卡片Json不合法</string>
|
||||||
<string name="email_host">主機</string>
|
<string name="email_host">主機</string>
|
||||||
<string name="smtp_port">端口</string>
|
<string name="smtp_port">端口</string>
|
||||||
@ -272,6 +310,10 @@
|
|||||||
<string name="TelegramApiToken">ApiToken 或 自定義代理地址(http開頭)</string>
|
<string name="TelegramApiToken">ApiToken 或 自定義代理地址(http開頭)</string>
|
||||||
<string name="TelegramChatId">被通知人(或群組)的ChatId</string>
|
<string name="TelegramChatId">被通知人(或群組)的ChatId</string>
|
||||||
<string name="Method" formatted="false">請求方式</string>
|
<string name="Method" formatted="false">請求方式</string>
|
||||||
|
<string name="parse_mode">解析模式</string>
|
||||||
|
<string name="parse_mode_text">Text</string>
|
||||||
|
<string name="parse_mode_html">Html</string>
|
||||||
|
<string name="parse_mode_markdown">MarkdownV2</string>
|
||||||
|
|
||||||
<string name="SmsSimSlot">發送卡槽</string>
|
<string name="SmsSimSlot">發送卡槽</string>
|
||||||
<string name="same_source">原進原出</string>
|
<string name="same_source">原進原出</string>
|
||||||
@ -311,17 +353,10 @@
|
|||||||
<string name="custom_template">轉發信息模版</string>
|
<string name="custom_template">轉發信息模版</string>
|
||||||
<string name="custom_template_tips">Tip:按需插入內容標籤;留空使用默認模版</string>
|
<string name="custom_template_tips">Tip:按需插入內容標籤;留空使用默認模版</string>
|
||||||
<string name="insert_sender">來源號碼</string>
|
<string name="insert_sender">來源號碼</string>
|
||||||
<string name="insert_sender_app">APP包名</string>
|
|
||||||
<string name="insert_uid">UID</string>
|
|
||||||
<string name="insert_content">簡訊內容</string>
|
|
||||||
<string name="insert_title_app">通知標題</string>
|
|
||||||
<string name="insert_content_app">通知內容</string>
|
|
||||||
<string name="insert_extra">卡槽信息</string>
|
|
||||||
<string name="insert_time">接收時間</string>
|
|
||||||
<string name="insert_device_name">裝置名稱</string>
|
|
||||||
<string name="battery_setting">忽略電池優化設置</string>
|
<string name="battery_setting">忽略電池優化設置</string>
|
||||||
<string name="battery_setting_tips">請設置為手動管理:允許自啟動、允許關聯啟動、允許後台運行</string>
|
<string name="battery_setting_tips">請設置為手動管理:允許自啟動、允許關聯啟動、允許後台運行</string>
|
||||||
<string name="unknown_number">未知號碼</string>
|
<string name="unknown_number">未知號碼</string>
|
||||||
|
<string name="unknown_area">未知歸屬地</string>
|
||||||
<string name="unsupport">您的手機不支持此設置</string>
|
<string name="unsupport">您的手機不支持此設置</string>
|
||||||
<string name="isIgnored">已將省電優化設置為無限制(不優化)!</string>
|
<string name="isIgnored">已將省電優化設置為無限制(不優化)!</string>
|
||||||
<string name="isIgnored2">本界面無法直接操作系統的省電優化設置</string>
|
<string name="isIgnored2">本界面無法直接操作系統的省電優化設置</string>
|
||||||
@ -358,6 +393,7 @@
|
|||||||
<string name="appicon">應用圖標</string>
|
<string name="appicon">應用圖標</string>
|
||||||
<string name="user_app">用戶應用</string>
|
<string name="user_app">用戶應用</string>
|
||||||
<string name="system_app">系統應用</string>
|
<string name="system_app">系統應用</string>
|
||||||
|
<string name="tips_get_installed_apps">請先授予獲取應用列表權限</string>
|
||||||
<string name="tips_notification">請先授予發送通知權限,有利於《簡訊轉發器》保活!</string>
|
<string name="tips_notification">請先授予發送通知權限,有利於《簡訊轉發器》保活!</string>
|
||||||
<string name="tips_notification_listener">請先授予《簡訊轉發器》通知使用權,否則無法轉發應用程式通知,已經自動關閉轉發!</string>
|
<string name="tips_notification_listener">請先授予《簡訊轉發器》通知使用權,否則無法轉發應用程式通知,已經自動關閉轉發!</string>
|
||||||
<string name="pushplus_website">官網地址</string>
|
<string name="pushplus_website">官網地址</string>
|
||||||
@ -404,6 +440,7 @@
|
|||||||
<string name="GotifyWebServer">WebServer</string>
|
<string name="GotifyWebServer">WebServer</string>
|
||||||
<string name="GotifyWebServerTips"><![CDATA[例:https://push.ppps.cn/message?token=<apptoken>]]></string>
|
<string name="GotifyWebServerTips"><![CDATA[例:https://push.ppps.cn/message?token=<apptoken>]]></string>
|
||||||
<string name="title_template">標題模板</string>
|
<string name="title_template">標題模板</string>
|
||||||
|
<string name="auto_copy">自動複製</string>
|
||||||
<string name="priority">優先級(1 – 9)</string>
|
<string name="priority">優先級(1 – 9)</string>
|
||||||
<string name="dingtalk_robot">釘釘群機器人</string>
|
<string name="dingtalk_robot">釘釘群機器人</string>
|
||||||
<string name="dingtalk_inner_robot">釘釘企業機器人</string>
|
<string name="dingtalk_inner_robot">釘釘企業機器人</string>
|
||||||
@ -447,7 +484,7 @@
|
|||||||
<string name="interval_label">遞增間隔</string>
|
<string name="interval_label">遞增間隔</string>
|
||||||
<string name="timeout_label">單次超時</string>
|
<string name="timeout_label">單次超時</string>
|
||||||
<string name="seconds">秒</string>
|
<string name="seconds">秒</string>
|
||||||
<string name="seconds_n">%s秒</string>
|
<string name="seconds_n">%d秒</string>
|
||||||
<string name="retry_label">最多重試</string>
|
<string name="retry_label">最多重試</string>
|
||||||
<string name="test_sender_sms">【%s】恭喜您,該發送通道測試成功,請繼續添加轉發規則!</string>
|
<string name="test_sender_sms">【%s】恭喜您,該發送通道測試成功,請繼續添加轉發規則!</string>
|
||||||
<string name="test_sender_name">測試通道</string>
|
<string name="test_sender_name">測試通道</string>
|
||||||
@ -513,7 +550,7 @@
|
|||||||
<string name="no">No</string>
|
<string name="no">No</string>
|
||||||
<string name="refresh">刷新</string>
|
<string name="refresh">刷新</string>
|
||||||
<string name="tip_can_not_get_sim_infos">無法獲取卡槽信息,請確認應用權限【獲取手機信息】為【始終允許】</string>
|
<string name="tip_can_not_get_sim_infos">無法獲取卡槽信息,請確認應用權限【獲取手機信息】為【始終允許】</string>
|
||||||
<string name="tip_can_not_get_sim_info">未獲取到卡槽%s中的SIM卡信息</string>
|
<string name="tip_can_not_get_sim_info">未獲取到卡槽%d中的SIM卡信息</string>
|
||||||
<string name="auto_check">啟動時檢查</string>
|
<string name="auto_check">啟動時檢查</string>
|
||||||
<string name="check_update">檢查更新</string>
|
<string name="check_update">檢查更新</string>
|
||||||
<string name="join_preview_program">加入SmsF預覽體驗計劃</string>
|
<string name="join_preview_program">加入SmsF預覽體驗計劃</string>
|
||||||
@ -535,12 +572,13 @@
|
|||||||
|
|
||||||
<string name="bark_server">Bark-Server</string>
|
<string name="bark_server">Bark-Server</string>
|
||||||
<string name="bark_server_tips">例:https://api.day.app/XXXXXXXX/</string>
|
<string name="bark_server_tips">例:https://api.day.app/XXXXXXXX/</string>
|
||||||
<string name="bark_server_regex">^https?://[^/]+/[^/]+/$</string>
|
<string name="bark_server_regex">^https?://[^/]+/[^/]+/.*</string>
|
||||||
<string name="bark_server_error">Url格式錯誤,例:https://api.day.app/XXXXXXXX/</string>
|
<string name="bark_server_error">Url格式錯誤,例:https://api.day.app/XXXXXXXX/</string>
|
||||||
<string name="bark_group">分組名稱</string>
|
<string name="bark_group">分組名稱</string>
|
||||||
<string name="bark_group_tips">可選,例:簡訊轉發器</string>
|
<string name="bark_group_tips">可選,例:簡訊轉發器</string>
|
||||||
<string name="bark_icon">消息圖標</string>
|
<string name="bark_icon">消息圖標</string>
|
||||||
<string name="bark_icon_tips">可選,填寫Url,圖片不要太大</string>
|
<string name="bark_icon_tips">可選,填寫Url,圖片不要太大</string>
|
||||||
|
<string name="bark_call">持續提醒</string>
|
||||||
<string name="bark_sound">消息聲音</string>
|
<string name="bark_sound">消息聲音</string>
|
||||||
<string name="bark_sound_tips">可選,例:minuet.caf</string>
|
<string name="bark_sound_tips">可選,例:minuet.caf</string>
|
||||||
<string name="bark_badge">消息角標</string>
|
<string name="bark_badge">消息角標</string>
|
||||||
@ -607,7 +645,7 @@
|
|||||||
<string name="extra_app">額外消除應用通知</string>
|
<string name="extra_app">額外消除應用通知</string>
|
||||||
<string name="extra_app_hint">一行一個包名\n開啟異步加載App列表以便選擇</string>
|
<string name="extra_app_hint">一行一個包名\n開啟異步加載App列表以便選擇</string>
|
||||||
<string name="choose_app_hint">下拉選擇獲取包名,關鍵字模糊匹配APP名稱</string>
|
<string name="choose_app_hint">下拉選擇獲取包名,關鍵字模糊匹配APP名稱</string>
|
||||||
<string name="regex_multi_match" tools:ignore="TypographyDashes">^\\s*(並且|或者)\\s(是|不是)\\s(手機號|APP包名|簡訊內容|通知內容|通知標題|卡槽信息|通話類型)\\s(相等|包含|不包含|開頭|結尾|正則匹配)\\s(.*)$</string>
|
<string name="regex_multi_match" tools:ignore="TypographyDashes">^\\s*(並且|或者)\\s(是|不是)\\s(手機號|APP包名|簡訊內容|通知內容|通知標題|卡槽信息|通話類型|UID)\\s(相等|包含|不包含|開頭|結尾|正則匹配)\\s(.*)$</string>
|
||||||
<string name="privacy_content_1">歡迎使用</string>
|
<string name="privacy_content_1">歡迎使用</string>
|
||||||
<string name="privacy_content_2">我們深知個人信息對你的重要性,也感謝你對我們的信任。\n</string>
|
<string name="privacy_content_2">我們深知個人信息對你的重要性,也感謝你對我們的信任。\n</string>
|
||||||
<string name="privacy_content_3">為了更好地保護你的權益,同時遵守相關監管的要求,我們將通過 </string>
|
<string name="privacy_content_3">為了更好地保護你的權益,同時遵守相關監管的要求,我們將通過 </string>
|
||||||
@ -804,7 +842,7 @@
|
|||||||
<string name="debug_mode_tips">將 Log.* 寫入檔案,以便排查問題;可匯出至下載目錄</string>
|
<string name="debug_mode_tips">將 Log.* 寫入檔案,以便排查問題;可匯出至下載目錄</string>
|
||||||
<string name="optional_components">可選組件:</string>
|
<string name="optional_components">可選組件:</string>
|
||||||
<string name="enable_cactus">啟用 Cactus 增強保活措施(會增加耗電)</string>
|
<string name="enable_cactus">啟用 Cactus 增強保活措施(會增加耗電)</string>
|
||||||
<string name="enabe_cactus_tips">雙進程前台服務/JobScheduler/WorkManager/1像素/無聲音樂</string>
|
<string name="enable_cactus_tips">雙進程前台服務/JobScheduler/WorkManager/1像素/無聲音樂</string>
|
||||||
<string name="load_app_list">啟動時異步獲取已安裝App列表</string>
|
<string name="load_app_list">啟動時異步獲取已安裝App列表</string>
|
||||||
<string name="load_app_list_tips">用於加速進入應用列表/編輯轉發規則下拉選擇/替換{{APP_NAME}}</string>
|
<string name="load_app_list_tips">用於加速進入應用列表/編輯轉發規則下拉選擇/替換{{APP_NAME}}</string>
|
||||||
<string name="load_app_list_toast">開啟異步獲取已安裝App列表時必選一個類型</string>
|
<string name="load_app_list_toast">開啟異步獲取已安裝App列表時必選一個類型</string>
|
||||||
@ -939,6 +977,7 @@
|
|||||||
<string name="task_battery">電量使用</string>
|
<string name="task_battery">電量使用</string>
|
||||||
<string name="task_battery_tips">當剩餘電量滿足條件時觸發</string>
|
<string name="task_battery_tips">當剩餘電量滿足條件時觸發</string>
|
||||||
<string name="task_charge">充電狀態</string>
|
<string name="task_charge">充電狀態</string>
|
||||||
|
<string name="task_charge_tips">當充電狀態滿足條件時觸發</string>
|
||||||
<string name="task_lock_screen">鎖屏解鎖</string>
|
<string name="task_lock_screen">鎖屏解鎖</string>
|
||||||
<string name="task_lock_screen_tips">在屏幕鎖定或解鎖後立即或指定時間觸發</string>
|
<string name="task_lock_screen_tips">在屏幕鎖定或解鎖後立即或指定時間觸發</string>
|
||||||
<string name="task_sms">簡訊廣播</string>
|
<string name="task_sms">簡訊廣播</string>
|
||||||
@ -964,8 +1003,8 @@
|
|||||||
<string name="task_rule_tips">控制【轉發規則】的啟用/禁用</string>
|
<string name="task_rule_tips">控制【轉發規則】的啟用/禁用</string>
|
||||||
<string name="task_sender">啟停通道</string>
|
<string name="task_sender">啟停通道</string>
|
||||||
<string name="task_sender_tips">控制【發送通道】的啟用/禁用</string>
|
<string name="task_sender_tips">控制【發送通道】的啟用/禁用</string>
|
||||||
<string name="task_alarm">聲音警報</string>
|
<string name="task_alarm">警報提醒</string>
|
||||||
<string name="task_alarm_tips">聲音警報</string>
|
<string name="task_alarm_tips">播放音樂/震動手機發出提醒</string>
|
||||||
<string name="task_resend">重發消息</string>
|
<string name="task_resend">重發消息</string>
|
||||||
<string name="task_resend_tips">自動重發N小時以來的轉發記錄,0=全部</string>
|
<string name="task_resend_tips">自動重發N小時以來的轉發記錄,0=全部</string>
|
||||||
<string name="task_resend_desc" formatted="false">自動重發%s小時以來%s的轉發記錄</string>
|
<string name="task_resend_desc" formatted="false">自動重發%s小時以來%s的轉發記錄</string>
|
||||||
@ -1109,16 +1148,31 @@
|
|||||||
<string name="chat_id">Chat ID</string>
|
<string name="chat_id">Chat ID</string>
|
||||||
<string name="receive_id">訊息接收者ID</string>
|
<string name="receive_id">訊息接收者ID</string>
|
||||||
<string name="toast_location_not_enabled">定位服務未開啟,請先前往系統設置中開啟!</string>
|
<string name="toast_location_not_enabled">定位服務未開啟,請先前往系統設置中開啟!</string>
|
||||||
|
<string name="toast_bluetooth_not_enabled">藍牙服務未開啟,請先前往系統設置中開啟!</string>
|
||||||
<string name="task_condition_check_again">延遲執行時再次校驗</string>
|
<string name="task_condition_check_again">延遲執行時再次校驗</string>
|
||||||
<string name="task_condition_check_again_tips">作為觸發條件時,在延遲執行動作時再次校驗是否滿足</string>
|
<string name="task_condition_check_again_tips">作為觸發條件時,在延遲執行動作時再次校驗是否滿足</string>
|
||||||
|
|
||||||
<string name="start_alarm">啟動警報</string>
|
<string name="start_alarm">啟動警報</string>
|
||||||
<string name="stop_alarm">停止警報</string>
|
<string name="stop_alarm">停止警報</string>
|
||||||
<string name="alarm_play_settings">播放設置</string>
|
<string name="alarm_play_settings">播放音樂</string>
|
||||||
<string name="alarm_music">指定音樂</string>
|
<string name="alarm_music">指定音樂</string>
|
||||||
<string name="alarm_music_tips">可選,下載 mp3/ogg/wav 到 Download 目錄</string>
|
<string name="alarm_music_tips">可選,下載 mp3/ogg/wav 到 Download 目錄</string>
|
||||||
<string name="alarm_volume">播放音量</string>
|
<string name="alarm_volume">播放音量</string>
|
||||||
<string name="alarm_play_times">播放次數(0=無限)</string>
|
<string name="alarm_play_times">播放次數(0=無限)</string>
|
||||||
|
<string name="alarm_vibrate_settings">振動手機</string>
|
||||||
|
<string name="alarm_repeat_times">重複次數(0=無限)</string>
|
||||||
|
<string name="alarm_vibration_effect">振動效果</string>
|
||||||
|
<string name="alarm_vibration_effect_tips">語法:=[強振動], -[弱振動], _[不振動], 每次100ms</string>
|
||||||
|
<string name="alarm_vibration_effect_1">強振動 100ms</string>
|
||||||
|
<string name="alarm_vibration_effect_2">弱振動 100ms</string>
|
||||||
|
<string name="alarm_vibration_effect_3">不振動 100ms</string>
|
||||||
|
<string name="alarm_flash_settings">閃爍手機</string>
|
||||||
|
<string name="alarm_flash_effect">閃光效果</string>
|
||||||
|
<string name="alarm_flash_effect_tips">語法:1或X[開啟閃光燈],0或O[關閉閃光燈],每次300毫秒</string>
|
||||||
|
<string name="alarm_flash_effect_1">開啟閃光燈 300毫秒</string>
|
||||||
|
<string name="alarm_flash_effect_2">關閉閃光燈 300毫秒</string>
|
||||||
|
<string name="alarm_settings_error">播放音樂/振動手機/閃爍手機必須至少開啟一個</string>
|
||||||
|
|
||||||
|
|
||||||
<string name="invalid_tag" formatted="false">%s 標籤無效:%s</string>
|
<string name="invalid_tag" formatted="false">%s 標籤無效:%s</string>
|
||||||
<string name="invalid_task_name">請輸入任務名稱</string>
|
<string name="invalid_task_name">請輸入任務名稱</string>
|
||||||
@ -1141,4 +1195,5 @@
|
|||||||
<string name="bluetooth_not_supported">不支援藍牙裝置</string>
|
<string name="bluetooth_not_supported">不支援藍牙裝置</string>
|
||||||
<string name="start_discovery">搜索裝置</string>
|
<string name="start_discovery">搜索裝置</string>
|
||||||
<string name="invalid_bluetooth_mac_address">藍牙裝置MAC地址無效,例如:AA:BB:CC:DD:EE:FF</string>
|
<string name="invalid_bluetooth_mac_address">藍牙裝置MAC地址無效,例如:AA:BB:CC:DD:EE:FF</string>
|
||||||
|
<string name="auto_start_redmi"><![CDATA[紅米手機:授權管理 -> 自啟動管理 -> 允許應用自啟動]]></string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -127,6 +127,7 @@
|
|||||||
<item>\@sina.cn</item>
|
<item>\@sina.cn</item>
|
||||||
<item>\@139.com</item>
|
<item>\@139.com</item>
|
||||||
<item>\@189.cn</item>
|
<item>\@189.cn</item>
|
||||||
|
<item>\@icloud.com</item>
|
||||||
<item>@string/other_mail_type</item><!--注意这里不能修改-->
|
<item>@string/other_mail_type</item><!--注意这里不能修改-->
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
@ -26,6 +26,38 @@
|
|||||||
<string name="tag_ipv6" translatable="false">{{IPV6}}</string>
|
<string name="tag_ipv6" translatable="false">{{IPV6}}</string>
|
||||||
<string name="tag_ip_list" translatable="false">{{IP_LIST}}</string>
|
<string name="tag_ip_list" translatable="false">{{IP_LIST}}</string>
|
||||||
<string name="tag_net_type" translatable="false">{{NET_TYPE}}</string>
|
<string name="tag_net_type" translatable="false">{{NET_TYPE}}</string>
|
||||||
|
<string name="tag_contact_name" translatable="false">{{CONTACT_NAME}}</string>
|
||||||
|
<string name="tag_phone_area" translatable="false">{{PHONE_AREA}}</string>
|
||||||
|
|
||||||
|
<string name="insert_tag_from">来源号码</string>
|
||||||
|
<string name="insert_tag_sms">短信内容</string>
|
||||||
|
<string name="insert_tag_package_name">APP包名</string>
|
||||||
|
<string name="insert_tag_app_name">APP应用名</string>
|
||||||
|
<string name="insert_tag_title">通知标题</string>
|
||||||
|
<string name="insert_tag_msg">通知内容</string>
|
||||||
|
<string name="insert_tag_card_slot">卡槽备注</string>
|
||||||
|
<string name="insert_tag_card_subid">卡槽主键</string>
|
||||||
|
<string name="insert_tag_receive_time">接收时间</string>
|
||||||
|
<string name="insert_tag_current_time">当前时间</string>
|
||||||
|
<string name="insert_tag_device_name">设备名称</string>
|
||||||
|
<string name="insert_tag_app_version">SmsF版本</string>
|
||||||
|
<string name="insert_tag_call_type">通话类型</string>
|
||||||
|
<string name="insert_tag_location">定位信息</string>
|
||||||
|
<string name="insert_tag_location_longitude">定位经度</string>
|
||||||
|
<string name="insert_tag_location_latitude">定位纬度</string>
|
||||||
|
<string name="insert_tag_location_address">定位地址</string>
|
||||||
|
<string name="insert_tag_battery_pct">电池电量</string>
|
||||||
|
<string name="insert_tag_battery_status">电池状态</string>
|
||||||
|
<string name="insert_tag_battery_plugged">充电方式</string>
|
||||||
|
<string name="insert_tag_battery_info">电池完整信息</string>
|
||||||
|
<string name="insert_tag_battery_info_simple">电池简单信息</string>
|
||||||
|
<string name="insert_tag_uid">用户UID</string>
|
||||||
|
<string name="insert_tag_ipv4">公网IPv4</string>
|
||||||
|
<string name="insert_tag_ipv6">公网IPv6</string>
|
||||||
|
<string name="insert_tag_ip_list">IP地址列表</string>
|
||||||
|
<string name="insert_tag_net_type">网络状态</string>
|
||||||
|
<string name="insert_tag_contact_name">来源姓名</string>
|
||||||
|
<string name="insert_tag_phone_area">来源归属</string>
|
||||||
|
|
||||||
<string name="type_param_sms">短信</string>
|
<string name="type_param_sms">短信</string>
|
||||||
<string name="type_param_call">通话</string>
|
<string name="type_param_call">通话</string>
|
||||||
@ -85,6 +117,7 @@
|
|||||||
<string name="url_help">https://gitee.com/pp/SmsForwarder/wikis/pages</string>
|
<string name="url_help">https://gitee.com/pp/SmsForwarder/wikis/pages</string>
|
||||||
<string name="url_donation_link">https://gitee.com/pp/SmsForwarder.wiki/raw/master/%E6%89%93%E8%B5%8F%E5%90%8D%E5%8D%95.md</string>
|
<string name="url_donation_link">https://gitee.com/pp/SmsForwarder.wiki/raw/master/%E6%89%93%E8%B5%8F%E5%90%8D%E5%8D%95.md</string>
|
||||||
<string name="url_wechat_miniprogram">https://gitee.com/pp/SmsForwarder/raw/main/pic/wechat_miniprogram.jpg</string>
|
<string name="url_wechat_miniprogram">https://gitee.com/pp/SmsForwarder/raw/main/pic/wechat_miniprogram.jpg</string>
|
||||||
|
<string name="url_tips">https://gitee.com/pp/SmsForwarder.wiki/raw/master/tips.json</string>
|
||||||
|
|
||||||
<string name="lab_yes">是</string>
|
<string name="lab_yes">是</string>
|
||||||
<string name="lab_no">否</string>
|
<string name="lab_no">否</string>
|
||||||
@ -214,6 +247,13 @@
|
|||||||
<string name="switch_rule_status">启用该条转发规则</string>
|
<string name="switch_rule_status">启用该条转发规则</string>
|
||||||
<string name="invalid_match_value">匹配的值不可为空</string>
|
<string name="invalid_match_value">匹配的值不可为空</string>
|
||||||
<string name="invalid_call_type">通话类型不正确,只能填写1到6的任意一个数字</string>
|
<string name="invalid_call_type">通话类型不正确,只能填写1到6的任意一个数字</string>
|
||||||
|
<string name="mon">周一</string>
|
||||||
|
<string name="tue">周二</string>
|
||||||
|
<string name="wed">周三</string>
|
||||||
|
<string name="thu">周四</string>
|
||||||
|
<string name="fri">周五</string>
|
||||||
|
<string name="sat">周六</string>
|
||||||
|
<string name="sun">周日</string>
|
||||||
<!--SenderActivity-->
|
<!--SenderActivity-->
|
||||||
<string name="delete_sender_title">发送通道操作确认</string>
|
<string name="delete_sender_title">发送通道操作确认</string>
|
||||||
<string name="delete_sender_tips">删除发送通道后会级联删除其相关的转发规则、转发日志的所有记录!\n\n确定删除该条发送通道?</string>
|
<string name="delete_sender_tips">删除发送通道后会级联删除其相关的转发规则、转发日志的所有记录!\n\n确定删除该条发送通道?</string>
|
||||||
@ -243,8 +283,8 @@
|
|||||||
<string name="invalid_wework_agent">企业ID、AgentID、Secret都不能为空</string>
|
<string name="invalid_wework_agent">企业ID、AgentID、Secret都不能为空</string>
|
||||||
<string name="invalid_dingtalk_inner_robot">AgentId、AppKey、AppSecret、UserIds都不能为空</string>
|
<string name="invalid_dingtalk_inner_robot">AgentId、AppKey、AppSecret、UserIds都不能为空</string>
|
||||||
<string name="invalid_phone_num">接收手机号不能为空</string>
|
<string name="invalid_phone_num">接收手机号不能为空</string>
|
||||||
<string name="invalid_multi_match">多重匹配规则的第 %s 行格式有误</string>
|
<string name="invalid_multi_match">多重匹配规则的第 %d 行格式有误</string>
|
||||||
<string name="invalid_regex_replace">正则替换内容的第 %s 行格式有误</string>
|
<string name="invalid_regex_replace">正则替换内容的第 %d 行格式有误</string>
|
||||||
<string name="invalid_message_card">自定义消息卡片Json不合法</string>
|
<string name="invalid_message_card">自定义消息卡片Json不合法</string>
|
||||||
<string name="email_host">主机</string>
|
<string name="email_host">主机</string>
|
||||||
<string name="smtp_port">端口</string>
|
<string name="smtp_port">端口</string>
|
||||||
@ -299,6 +339,10 @@
|
|||||||
<string name="TelegramApiToken">ApiToken 或 自定义代理地址(http开头)</string>
|
<string name="TelegramApiToken">ApiToken 或 自定义代理地址(http开头)</string>
|
||||||
<string name="TelegramChatId">被通知人(或群组)的ChatId</string>
|
<string name="TelegramChatId">被通知人(或群组)的ChatId</string>
|
||||||
<string name="Method" formatted="false">请求方式</string>
|
<string name="Method" formatted="false">请求方式</string>
|
||||||
|
<string name="parse_mode">解析模式</string>
|
||||||
|
<string name="parse_mode_text">Text</string>
|
||||||
|
<string name="parse_mode_html">Html</string>
|
||||||
|
<string name="parse_mode_markdown">MarkdownV2</string>
|
||||||
|
|
||||||
<string name="SmsSimSlot">发送卡槽</string>
|
<string name="SmsSimSlot">发送卡槽</string>
|
||||||
<string name="same_source">原进原出</string>
|
<string name="same_source">原进原出</string>
|
||||||
@ -338,17 +382,10 @@
|
|||||||
<string name="custom_template">转发信息模版</string>
|
<string name="custom_template">转发信息模版</string>
|
||||||
<string name="custom_template_tips">Tip:按需插入内容标签;留空使用默认模版</string>
|
<string name="custom_template_tips">Tip:按需插入内容标签;留空使用默认模版</string>
|
||||||
<string name="insert_sender">来源号码</string>
|
<string name="insert_sender">来源号码</string>
|
||||||
<string name="insert_sender_app">APP包名</string>
|
|
||||||
<string name="insert_uid">UID</string>
|
|
||||||
<string name="insert_content">短信内容</string>
|
|
||||||
<string name="insert_title_app">通知标题</string>
|
|
||||||
<string name="insert_content_app">通知内容</string>
|
|
||||||
<string name="insert_extra">卡槽信息</string>
|
|
||||||
<string name="insert_time">接收时间</string>
|
|
||||||
<string name="insert_device_name">设备名称</string>
|
|
||||||
<string name="battery_setting">忽略电池优化设置</string>
|
<string name="battery_setting">忽略电池优化设置</string>
|
||||||
<string name="battery_setting_tips">请设置为手动管理:允许自启动、允许关联启动、允许后台运行</string>
|
<string name="battery_setting_tips">请设置为手动管理:允许自启动、允许关联启动、允许后台运行</string>
|
||||||
<string name="unknown_number">未知号码</string>
|
<string name="unknown_number">未知号码</string>
|
||||||
|
<string name="unknown_area">未知归属地</string>
|
||||||
<string name="unsupport">您的手机不支持此设置</string>
|
<string name="unsupport">您的手机不支持此设置</string>
|
||||||
<string name="isIgnored">已将省电优化设置为无限制(不优化)!</string>
|
<string name="isIgnored">已将省电优化设置为无限制(不优化)!</string>
|
||||||
<string name="isIgnored2">本界面无法直接操作系统的省电优化设置</string>
|
<string name="isIgnored2">本界面无法直接操作系统的省电优化设置</string>
|
||||||
@ -385,6 +422,7 @@
|
|||||||
<string name="appicon">应用图标</string>
|
<string name="appicon">应用图标</string>
|
||||||
<string name="user_app">用户应用</string>
|
<string name="user_app">用户应用</string>
|
||||||
<string name="system_app">系统应用</string>
|
<string name="system_app">系统应用</string>
|
||||||
|
<string name="tips_get_installed_apps">请先授予获取应用列表权限</string>
|
||||||
<string name="tips_notification">请先授予发送通知权限,有利于《短信转发器》保活!</string>
|
<string name="tips_notification">请先授予发送通知权限,有利于《短信转发器》保活!</string>
|
||||||
<string name="tips_notification_listener">请先授予《短信转发器》通知使用权,否则无法转发APP通知,已经自动关闭转发!</string>
|
<string name="tips_notification_listener">请先授予《短信转发器》通知使用权,否则无法转发APP通知,已经自动关闭转发!</string>
|
||||||
<string name="pushplus_website">官网地址</string>
|
<string name="pushplus_website">官网地址</string>
|
||||||
@ -431,6 +469,7 @@
|
|||||||
<string name="GotifyWebServer">WebServer</string>
|
<string name="GotifyWebServer">WebServer</string>
|
||||||
<string name="GotifyWebServerTips"><![CDATA[例:https://push.ppps.cn/message?token=<apptoken>]]></string>
|
<string name="GotifyWebServerTips"><![CDATA[例:https://push.ppps.cn/message?token=<apptoken>]]></string>
|
||||||
<string name="title_template">标题模板</string>
|
<string name="title_template">标题模板</string>
|
||||||
|
<string name="auto_copy">自动复制</string>
|
||||||
<string name="priority">优先级(1 – 9)</string>
|
<string name="priority">优先级(1 – 9)</string>
|
||||||
<string name="dingtalk_robot">钉钉群机器人</string>
|
<string name="dingtalk_robot">钉钉群机器人</string>
|
||||||
<string name="dingtalk_inner_robot">钉钉企业机器人</string>
|
<string name="dingtalk_inner_robot">钉钉企业机器人</string>
|
||||||
@ -474,7 +513,7 @@
|
|||||||
<string name="interval_label">递增间隔</string>
|
<string name="interval_label">递增间隔</string>
|
||||||
<string name="timeout_label">单次超时</string>
|
<string name="timeout_label">单次超时</string>
|
||||||
<string name="seconds">秒</string>
|
<string name="seconds">秒</string>
|
||||||
<string name="seconds_n">%s秒</string>
|
<string name="seconds_n">%d秒</string>
|
||||||
<string name="retry_label">最多重试</string>
|
<string name="retry_label">最多重试</string>
|
||||||
<string name="test_sender_sms">【%s】恭喜您,该发送通道测试成功,请继续添加转发规则!</string>
|
<string name="test_sender_sms">【%s】恭喜您,该发送通道测试成功,请继续添加转发规则!</string>
|
||||||
<string name="test_sender_name">测试通道</string>
|
<string name="test_sender_name">测试通道</string>
|
||||||
@ -540,7 +579,7 @@
|
|||||||
<string name="no">No</string>
|
<string name="no">No</string>
|
||||||
<string name="refresh">刷新</string>
|
<string name="refresh">刷新</string>
|
||||||
<string name="tip_can_not_get_sim_infos">无法获取卡槽信息,请确认应用权限【获取手机信息】为【始终允许】</string>
|
<string name="tip_can_not_get_sim_infos">无法获取卡槽信息,请确认应用权限【获取手机信息】为【始终允许】</string>
|
||||||
<string name="tip_can_not_get_sim_info">未获取到卡槽%s中的SIM卡信息</string>
|
<string name="tip_can_not_get_sim_info">未获取到卡槽%d中的SIM卡信息</string>
|
||||||
<string name="auto_check">启动时检查</string>
|
<string name="auto_check">启动时检查</string>
|
||||||
<string name="check_update">检查更新</string>
|
<string name="check_update">检查更新</string>
|
||||||
<string name="join_preview_program">加入SmsF预览体验计划</string>
|
<string name="join_preview_program">加入SmsF预览体验计划</string>
|
||||||
@ -562,12 +601,13 @@
|
|||||||
|
|
||||||
<string name="bark_server">Bark-Server</string>
|
<string name="bark_server">Bark-Server</string>
|
||||||
<string name="bark_server_tips">例:https://api.day.app/XXXXXXXX/</string>
|
<string name="bark_server_tips">例:https://api.day.app/XXXXXXXX/</string>
|
||||||
<string name="bark_server_regex">^https?://[^/]+/[^/]+/$</string>
|
<string name="bark_server_regex">^https?://[^/]+/[^/]+/.*</string>
|
||||||
<string name="bark_server_error">Url格式错误,例:https://api.day.app/XXXXXXXX/</string>
|
<string name="bark_server_error">Url格式错误,例:https://api.day.app/XXXXXXXX/</string>
|
||||||
<string name="bark_group">分组名称</string>
|
<string name="bark_group">分组名称</string>
|
||||||
<string name="bark_group_tips">可选,例:短信转发器</string>
|
<string name="bark_group_tips">可选,例:短信转发器</string>
|
||||||
<string name="bark_icon">消息图标</string>
|
<string name="bark_icon">消息图标</string>
|
||||||
<string name="bark_icon_tips">可选,填写Url,图片不要太大</string>
|
<string name="bark_icon_tips">可选,填写Url,图片不要太大</string>
|
||||||
|
<string name="bark_call">持续提醒</string>
|
||||||
<string name="bark_sound">消息声音</string>
|
<string name="bark_sound">消息声音</string>
|
||||||
<string name="bark_sound_tips">可选,例:minuet.caf</string>
|
<string name="bark_sound_tips">可选,例:minuet.caf</string>
|
||||||
<string name="bark_badge">消息角标</string>
|
<string name="bark_badge">消息角标</string>
|
||||||
@ -634,7 +674,7 @@
|
|||||||
<string name="extra_app">额外消除应用通知</string>
|
<string name="extra_app">额外消除应用通知</string>
|
||||||
<string name="extra_app_hint">一行一个包名\n开启异步加载App列表以便选择</string>
|
<string name="extra_app_hint">一行一个包名\n开启异步加载App列表以便选择</string>
|
||||||
<string name="choose_app_hint">下拉选择获取包名,关键字模糊匹配APP名称</string>
|
<string name="choose_app_hint">下拉选择获取包名,关键字模糊匹配APP名称</string>
|
||||||
<string name="regex_multi_match" tools:ignore="TypographyDashes">^\\s*(并且|或者)\\s(是|不是)\\s(手机号|APP包名|短信内容|通知内容|通知标题|卡槽信息|通话类型)\\s(相等|包含|不包含|开头|结尾|正则匹配)\\s(.*)$</string>
|
<string name="regex_multi_match" tools:ignore="TypographyDashes">^\\s*(并且|或者)\\s(是|不是)\\s(手机号|APP包名|短信内容|通知内容|通知标题|卡槽信息|通话类型|UID)\\s(相等|包含|不包含|开头|结尾|正则匹配)\\s(.*)$</string>
|
||||||
<string name="privacy_content_1">欢迎使用</string>
|
<string name="privacy_content_1">欢迎使用</string>
|
||||||
<string name="privacy_content_2">我们深知个人信息对你的重要性,也感谢你对我们的信任。\n</string>
|
<string name="privacy_content_2">我们深知个人信息对你的重要性,也感谢你对我们的信任。\n</string>
|
||||||
<string name="privacy_content_3">为了更好地保护你的权益,同时遵守相关监管的要求,我们将通过 </string>
|
<string name="privacy_content_3">为了更好地保护你的权益,同时遵守相关监管的要求,我们将通过 </string>
|
||||||
@ -722,7 +762,7 @@
|
|||||||
<string name="api_location_tips">远程查询手机定位,方便找回手机/防止老少走丢</string>
|
<string name="api_location_tips">远程查询手机定位,方便找回手机/防止老少走丢</string>
|
||||||
<string name="api_location_permission_tips">请先在【通用设置】中【启用GPS定位功能】</string>
|
<string name="api_location_permission_tips">请先在【通用设置】中【启用GPS定位功能】</string>
|
||||||
<string name="location_longitude">经度:%s</string>
|
<string name="location_longitude">经度:%s</string>
|
||||||
<string name="location_latitude">维度:%s</string>
|
<string name="location_latitude">纬度:%s</string>
|
||||||
<string name="location_address">地址:%s</string>
|
<string name="location_address">地址:%s</string>
|
||||||
<string name="location_time">时间:%s</string>
|
<string name="location_time">时间:%s</string>
|
||||||
<string name="location_provider">供应商:%s</string>
|
<string name="location_provider">供应商:%s</string>
|
||||||
@ -831,7 +871,7 @@
|
|||||||
<string name="debug_mode_tips">将Log.*写入文件,以便排查问题;可导出到下载目录</string>
|
<string name="debug_mode_tips">将Log.*写入文件,以便排查问题;可导出到下载目录</string>
|
||||||
<string name="optional_components">可选组件:</string>
|
<string name="optional_components">可选组件:</string>
|
||||||
<string name="enable_cactus">启用 Cactus 增强保活措施(会增加耗电)</string>
|
<string name="enable_cactus">启用 Cactus 增强保活措施(会增加耗电)</string>
|
||||||
<string name="enabe_cactus_tips">双进程前台服务/JobScheduler/WorkManager/1像素/无声音乐</string>
|
<string name="enable_cactus_tips">双进程前台服务/JobScheduler/WorkManager/1像素/无声音乐</string>
|
||||||
<string name="load_app_list">启动时异步获取已安装App列表</string>
|
<string name="load_app_list">启动时异步获取已安装App列表</string>
|
||||||
<string name="load_app_list_tips">用于加速进入应用列表/编辑转发规则下拉选择/替换{{APP_NAME}}</string>
|
<string name="load_app_list_tips">用于加速进入应用列表/编辑转发规则下拉选择/替换{{APP_NAME}}</string>
|
||||||
<string name="load_app_list_toast">开启异步获取已安装App列表时必选一个类型</string>
|
<string name="load_app_list_toast">开启异步获取已安装App列表时必选一个类型</string>
|
||||||
@ -966,6 +1006,7 @@
|
|||||||
<string name="task_battery">电量使用</string>
|
<string name="task_battery">电量使用</string>
|
||||||
<string name="task_battery_tips">当剩余电量满足条件时触发</string>
|
<string name="task_battery_tips">当剩余电量满足条件时触发</string>
|
||||||
<string name="task_charge">充电状态</string>
|
<string name="task_charge">充电状态</string>
|
||||||
|
<string name="task_charge_tips">当充电状态满足条件时触发</string>
|
||||||
<string name="task_lock_screen">锁屏解锁</string>
|
<string name="task_lock_screen">锁屏解锁</string>
|
||||||
<string name="task_lock_screen_tips">在屏幕锁定或解锁后立即或指定时间触发</string>
|
<string name="task_lock_screen_tips">在屏幕锁定或解锁后立即或指定时间触发</string>
|
||||||
<string name="task_sms">短信广播</string>
|
<string name="task_sms">短信广播</string>
|
||||||
@ -991,8 +1032,8 @@
|
|||||||
<string name="task_rule_tips">控制【转发规则】的启用/禁用</string>
|
<string name="task_rule_tips">控制【转发规则】的启用/禁用</string>
|
||||||
<string name="task_sender">启停通道</string>
|
<string name="task_sender">启停通道</string>
|
||||||
<string name="task_sender_tips">控制【发送通道】的启用/禁用</string>
|
<string name="task_sender_tips">控制【发送通道】的启用/禁用</string>
|
||||||
<string name="task_alarm">声音警报</string>
|
<string name="task_alarm">警报提醒</string>
|
||||||
<string name="task_alarm_tips">播放音乐提醒</string>
|
<string name="task_alarm_tips">播放音乐/振动手机提醒</string>
|
||||||
<string name="task_resend">重发消息</string>
|
<string name="task_resend">重发消息</string>
|
||||||
<string name="task_resend_tips">自动重发N小时以来的转发记录,0=全部</string>
|
<string name="task_resend_tips">自动重发N小时以来的转发记录,0=全部</string>
|
||||||
<string name="task_resend_desc" formatted="false">自动重发%s小时以来%s的转发记录</string>
|
<string name="task_resend_desc" formatted="false">自动重发%s小时以来%s的转发记录</string>
|
||||||
@ -1086,7 +1127,7 @@
|
|||||||
<string name="calc_type_distance">根据GPS坐标计算距离</string>
|
<string name="calc_type_distance">根据GPS坐标计算距离</string>
|
||||||
<string name="calc_type_address">根据地址关键字判断</string>
|
<string name="calc_type_address">根据地址关键字判断</string>
|
||||||
<string name="longitude">经度</string>
|
<string name="longitude">经度</string>
|
||||||
<string name="latitude">维度</string>
|
<string name="latitude">纬度</string>
|
||||||
<string name="distance1">以经纬度为中心,</string>
|
<string name="distance1">以经纬度为中心,</string>
|
||||||
<string name="distance2">米半径建立电子围栏</string>
|
<string name="distance2">米半径建立电子围栏</string>
|
||||||
<string name="current_coordinates">当前坐标</string>
|
<string name="current_coordinates">当前坐标</string>
|
||||||
@ -1136,16 +1177,30 @@
|
|||||||
<string name="chat_id">Chat ID</string>
|
<string name="chat_id">Chat ID</string>
|
||||||
<string name="receive_id">消息接收者ID</string>
|
<string name="receive_id">消息接收者ID</string>
|
||||||
<string name="toast_location_not_enabled">位置服务未开启,请先前往系统设置中开启!</string>
|
<string name="toast_location_not_enabled">位置服务未开启,请先前往系统设置中开启!</string>
|
||||||
|
<string name="toast_bluetooth_not_enabled">蓝牙服务未开启,请先前往系统设置中开启!</string>
|
||||||
<string name="task_condition_check_again">延迟执行时再次校验</string>
|
<string name="task_condition_check_again">延迟执行时再次校验</string>
|
||||||
<string name="task_condition_check_again_tips">作为触发条件时,在延迟执行动作时再次校验是否满足</string>
|
<string name="task_condition_check_again_tips">作为触发条件时,在延迟执行动作时再次校验是否满足</string>
|
||||||
|
|
||||||
<string name="start_alarm">启动警报</string>
|
<string name="start_alarm">启动警报</string>
|
||||||
<string name="stop_alarm">停止警报</string>
|
<string name="stop_alarm">停止警报</string>
|
||||||
<string name="alarm_play_settings">播放设置</string>
|
<string name="alarm_play_settings">播放音乐</string>
|
||||||
<string name="alarm_music">指定音乐</string>
|
<string name="alarm_music">指定音乐</string>
|
||||||
<string name="alarm_music_tips">可选,下载 mp3/ogg/wav 到 Download 目录</string>
|
<string name="alarm_music_tips">可选,下载 mp3/ogg/wav 到 Download 目录</string>
|
||||||
<string name="alarm_volume">播放音量</string>
|
<string name="alarm_volume">播放音量</string>
|
||||||
<string name="alarm_play_times">播放次数(0=无限)</string>
|
<string name="alarm_play_times">播放次数(0=无限)</string>
|
||||||
|
<string name="alarm_vibrate_settings">振动手机</string>
|
||||||
|
<string name="alarm_repeat_times">重复次数(0=无限)</string>
|
||||||
|
<string name="alarm_vibration_effect">振动效果</string>
|
||||||
|
<string name="alarm_vibration_effect_tips">语法:=[强振动], -[弱震动], _[不振动], 每次100ms</string>
|
||||||
|
<string name="alarm_vibration_effect_1">强振动 100ms</string>
|
||||||
|
<string name="alarm_vibration_effect_2">弱振动 100ms</string>
|
||||||
|
<string name="alarm_vibration_effect_3">不振动 100ms</string>
|
||||||
|
<string name="alarm_flash_settings">闪烁手机</string>
|
||||||
|
<string name="alarm_flash_effect">闪光效果</string>
|
||||||
|
<string name="alarm_flash_effect_tips">语法:1或X[开启闪光灯], 0或O[关闭闪光灯], 每次100ms</string>
|
||||||
|
<string name="alarm_flash_effect_1">开启闪光灯 100ms</string>
|
||||||
|
<string name="alarm_flash_effect_2">关闭闪光灯 100ms</string>
|
||||||
|
<string name="alarm_settings_error">播放音乐/振动手机/闪烁手机必须至少开启一个</string>
|
||||||
|
|
||||||
<string name="invalid_tag" formatted="false">%s 标签无效:%s</string>
|
<string name="invalid_tag" formatted="false">%s 标签无效:%s</string>
|
||||||
<string name="invalid_task_name">请输入任务名称</string>
|
<string name="invalid_task_name">请输入任务名称</string>
|
||||||
@ -1168,4 +1223,5 @@
|
|||||||
<string name="bluetooth_not_supported">不支持蓝牙设备</string>
|
<string name="bluetooth_not_supported">不支持蓝牙设备</string>
|
||||||
<string name="start_discovery">搜索设备</string>
|
<string name="start_discovery">搜索设备</string>
|
||||||
<string name="invalid_bluetooth_mac_address">蓝牙设备MAC地址无效,例如:AA:BB:CC:DD:EE:FF</string>
|
<string name="invalid_bluetooth_mac_address">蓝牙设备MAC地址无效,例如:AA:BB:CC:DD:EE:FF</string>
|
||||||
|
<string name="auto_start_redmi"><![CDATA[红米手机:授权管理 -> 自启动管理 -> 允许应用自启动]]></string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||||
# Specifies the JVM arguments used for the daemon process.
|
# Specifies the JVM arguments used for the daemon process.
|
||||||
# The setting is particularly useful for tweaking memory settings.
|
# The setting is particularly useful for tweaking memory settings.
|
||||||
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
|
org.gradle.jvmargs=-Xmx4096m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
|
||||||
# When configured, Gradle will run in incubating parallel mode.
|
# When configured, Gradle will run in incubating parallel mode.
|
||||||
# This option should only be used with decoupled projects. More details, visit
|
# This option should only be used with decoupled projects. More details, visit
|
||||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 2.3 MiB After Width: | Height: | Size: 1.4 MiB |
BIN
pic/sponsor.gif
Normal file
BIN
pic/sponsor.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 111 KiB |
@ -2,8 +2,8 @@ import java.util.regex.Matcher
|
|||||||
import java.util.regex.Pattern
|
import java.util.regex.Pattern
|
||||||
|
|
||||||
def build_versions = [:]
|
def build_versions = [:]
|
||||||
build_versions.version_code = 52
|
build_versions.version_code = 54
|
||||||
build_versions.version_name = "3.3.1"
|
build_versions.version_name = "3.3.3"
|
||||||
build_versions.min_sdk = 19
|
build_versions.min_sdk = 19
|
||||||
build_versions.target_sdk = 33
|
build_versions.target_sdk = 33
|
||||||
build_versions.build_tools = "33.0.1"
|
build_versions.build_tools = "33.0.1"
|
||||||
@ -38,13 +38,13 @@ versions.kotlin = '1.7.21'
|
|||||||
|
|
||||||
//========xlibrary start========//
|
//========xlibrary start========//
|
||||||
|
|
||||||
versions.xui = "dev~1.2.2-SNAPSHOT"
|
versions.xui = "1.2.2_250201"
|
||||||
versions.xupdate = "2.1.5"
|
versions.xupdate = "2.1.5"
|
||||||
versions.xaop = "dab6b77b2f" //1.1.0
|
versions.xaop = "1.1.0"
|
||||||
versions.xutil = "2.0.0"
|
versions.xutil = "2.0.0"
|
||||||
versions.xhttp2 = "9115cfcd5a" //2.0.9
|
versions.xhttp2 = "2.0.10"
|
||||||
versions.xpage = "3.3.0"
|
versions.xpage = "3.3.0"
|
||||||
versions.xrouter = "1.0.1"
|
versions.xrouter = "1.1.0"
|
||||||
|
|
||||||
//========xlibrary end========//
|
//========xlibrary end========//
|
||||||
|
|
||||||
@ -132,18 +132,18 @@ deps.leakcanary = "com.squareup.leakcanary:leakcanary-android:$versions.leakcana
|
|||||||
|
|
||||||
def xlibrary = [:]
|
def xlibrary = [:]
|
||||||
|
|
||||||
xlibrary.xui = "com.github.pppscn:XUI:$versions.xui" //com.github.xuexiangjys:XUI
|
xlibrary.xui = "com.github.pppscn:XUI:$versions.xui"
|
||||||
xlibrary.xupdate = "com.github.xuexiangjys:XUpdate:$versions.xupdate"
|
xlibrary.xupdate = "com.github.pppscn:XUpdate:$versions.xupdate"
|
||||||
xlibrary.xaop_runtime = "com.github.pppscn.XAOP:xaop-runtime:$versions.xaop" //com.github.xuexiangjys.XAOP
|
xlibrary.xaop_runtime = "com.github.pppscn.XAOP:xaop-runtime:$versions.xaop"
|
||||||
xlibrary.xaop_plugin = "com.github.pppscn.XAOP:xaop-plugin:$versions.xaop" //com.github.xuexiangjys.XAOP
|
xlibrary.xaop_plugin = "com.github.pppscn.XAOP:xaop-plugin:$versions.xaop"
|
||||||
xlibrary.xutil_core = "com.github.xuexiangjys.XUtil:xutil-core:$versions.xutil"
|
xlibrary.xutil_core = "com.github.pppscn.XUtil:xutil-core:$versions.xutil"
|
||||||
xlibrary.xutil_sub = "com.github.xuexiangjys.XUtil:xutil-sub:$versions.xutil"
|
xlibrary.xutil_sub = "com.github.pppscn.XUtil:xutil-sub:$versions.xutil"
|
||||||
xlibrary.xhttp2 = "com.github.pppscn:XHttp2:$versions.xhttp2" //com.github.xuexiangjys:XHttp2
|
xlibrary.xhttp2 = "com.github.pppscn:XHttp2:$versions.xhttp2"
|
||||||
xlibrary.xpage_lib = "com.github.xuexiangjys.XPage:xpage-lib:$versions.xpage"
|
xlibrary.xpage_lib = "com.github.pppscn.XPage:xpage-lib:$versions.xpage"
|
||||||
xlibrary.xpage_compiler = "com.github.xuexiangjys.XPage:xpage-compiler:$versions.xpage"
|
xlibrary.xpage_compiler = "com.github.pppscn.XPage:xpage-compiler:$versions.xpage"
|
||||||
xlibrary.xrouter_runtime = "com.github.xuexiangjys.XRouter:xrouter-runtime:$versions.xrouter"
|
xlibrary.xrouter_runtime = "com.github.pppscn.XRouter:xrouter-runtime:$versions.xrouter"
|
||||||
xlibrary.xrouter_compiler = "com.github.xuexiangjys.XRouter:xrouter-compiler:$versions.xrouter"
|
xlibrary.xrouter_compiler = "com.github.pppscn.XRouter:xrouter-compiler:$versions.xrouter"
|
||||||
xlibrary.xrouter_plugin = "com.github.xuexiangjys.XRouter:xrouter-plugin:$versions.xrouter"
|
xlibrary.xrouter_plugin = "com.github.pppscn.XRouter:xrouter-plugin:$versions.xrouter"
|
||||||
|
|
||||||
deps.xlibrary = xlibrary
|
deps.xlibrary = xlibrary
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user