修复:重启手机自动启动APP时加载配置失败 #233 #245

pull/286/head
pppscn 1 year ago
parent 4d7146bd7b
commit 5f55d20c83

@ -181,11 +181,11 @@ dependencies {
implementation files('libs/frpclib.aar') implementation files('libs/frpclib.aar')
testImplementation deps.junit testImplementation deps.junit
androidTestImplementation 'androidx.test.ext:junit:1.1.4' androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation deps.espresso.core androidTestImplementation deps.espresso.core
implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.core:core-ktx:1.8.0'
implementation "androidx.activity:activity-ktx:1.6.1" implementation "androidx.activity:activity-ktx:1.5.1"
implementation "androidx.fragment:fragment-ktx:1.5.4" implementation "androidx.fragment:fragment-ktx:1.5.4"
implementation "androidx.cardview:cardview:1.0.0" implementation "androidx.cardview:cardview:1.0.0"
implementation 'androidx.appcompat:appcompat:1.5.1' implementation 'androidx.appcompat:appcompat:1.5.1'
@ -202,8 +202,6 @@ dependencies {
//WebView //WebView
implementation 'com.github.xuexiangjys.AgentWeb:agentweb-core:1.0.0' implementation 'com.github.xuexiangjys.AgentWeb:agentweb-core:1.0.0'
implementation 'com.github.xuexiangjys.AgentWeb:agentweb-download:1.0.0'// implementation 'com.github.xuexiangjys.AgentWeb:agentweb-download:1.0.0'//
//mmkvhttps://github.com/Tencent/MMKV
implementation 'com.tencent:mmkv:1.2.15'
//AutoSizehttps://github.com/JessYanCoding/AndroidAutoSize //AutoSizehttps://github.com/JessYanCoding/AndroidAutoSize
implementation 'me.jessyan:autosize:1.2.1' implementation 'me.jessyan:autosize:1.2.1'
//umeng //umeng

@ -58,6 +58,8 @@
<application <application
android:name=".App" android:name=".App"
android:configChanges="screenSize|keyboardHidden|orientation|keyboard" android:configChanges="screenSize|keyboardHidden|orientation|keyboard"
android:defaultToDeviceProtectedStorage="true"
android:directBootAware="true"
android:fullBackupContent="@xml/backup_descriptor" android:fullBackupContent="@xml/backup_descriptor"
android:hardwareAccelerated="true" android:hardwareAccelerated="true"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
@ -215,6 +217,7 @@
<receiver <receiver
android:name=".receiver.BootReceiver" android:name=".receiver.BootReceiver"
android:defaultToDeviceProtectedStorage="true"
android:directBootAware="true" android:directBootAware="true"
android:exported="true" android:exported="true"
tools:ignore="IntentFilterExportedReceiver"> tools:ignore="IntentFilterExportedReceiver">

@ -173,7 +173,7 @@ class App : Application(), CactusCallback, Configuration.Provider by Core {
setChannelId(FRONT_CHANNEL_ID) //渠道Id setChannelId(FRONT_CHANNEL_ID) //渠道Id
setChannelName(FRONT_CHANNEL_NAME) //渠道名 setChannelName(FRONT_CHANNEL_NAME) //渠道名
setTitle(getString(R.string.app_name)) setTitle(getString(R.string.app_name))
setContent(SettingUtils.notifyContent.toString()) setContent(SettingUtils.notifyContent)
setSmallIcon(R.drawable.ic_forwarder) setSmallIcon(R.drawable.ic_forwarder)
setLargeIcon(R.mipmap.ic_launcher) setLargeIcon(R.mipmap.ic_launcher)
setPendingIntent(pendingIntent) setPendingIntent(pendingIntent)
@ -214,8 +214,10 @@ class App : Application(), CactusCallback, Configuration.Provider by Core {
*/ */
private fun initLibs() { private fun initLibs() {
Core.init(this) Core.init(this)
// 配置文件初始化
SharedPreference.init(applicationContext)
// 转发历史工具类初始化 // 转发历史工具类初始化
HistoryUtils.init(this) HistoryUtils.init(applicationContext)
// X系列基础库初始化 // X系列基础库初始化
XBasicLibInit.init(this) XBasicLibInit.init(this)
// 版本更新初始化 // 版本更新初始化

@ -1,14 +1,11 @@
package com.idormy.sms.forwarder.activity package com.idormy.sms.forwarder.activity
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.util.Log
import android.view.KeyEvent import android.view.KeyEvent
import com.idormy.sms.forwarder.R import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.utils.CommonUtils.Companion.showPrivacyDialog import com.idormy.sms.forwarder.utils.CommonUtils.Companion.showPrivacyDialog
import com.idormy.sms.forwarder.utils.MMKVUtils
import com.idormy.sms.forwarder.utils.SettingUtils import com.idormy.sms.forwarder.utils.SettingUtils
import com.idormy.sms.forwarder.utils.SettingUtils.Companion.isAgreePrivacy import com.idormy.sms.forwarder.utils.SettingUtils.Companion.isAgreePrivacy
import com.idormy.sms.forwarder.utils.SettingUtils.Companion.isFirstOpen
import com.xuexiang.xui.utils.KeyboardUtils import com.xuexiang.xui.utils.KeyboardUtils
import com.xuexiang.xui.widget.activity.BaseSplashActivity import com.xuexiang.xui.widget.activity.BaseSplashActivity
import com.xuexiang.xui.widget.dialog.materialdialog.DialogAction import com.xuexiang.xui.widget.dialog.materialdialog.DialogAction
@ -38,12 +35,6 @@ class SplashActivity : BaseSplashActivity(), CancelAdapt {
* 启动页结束后的动作 * 启动页结束后的动作
*/ */
override fun onSplashFinished() { override fun onSplashFinished() {
if (isFirstOpen) {
isFirstOpen = false
Log.d(TAG, "从SP迁移数据")
MMKVUtils.importSharedPreferences(this)
}
if (isAgreePrivacy) { if (isAgreePrivacy) {
whereToJump() whereToJump()
} else { } else {

@ -65,7 +65,7 @@ class AboutFragment : BaseFragment<FragmentAboutBinding?>(), SuperTextView.OnSup
XUpdateInit.checkUpdate(requireContext(), true) XUpdateInit.checkUpdate(requireContext(), true)
} }
binding!!.btnCache.setOnClickListener { binding!!.btnCache.setOnClickListener {
HistoryUtils.clear() HistoryUtils.clearPreference()
CacheUtils.clearAllCache(requireContext()) CacheUtils.clearAllCache(requireContext())
XToastUtils.success(R.string.about_cache_purged) XToastUtils.success(R.string.about_cache_purged)
binding!!.menuCache.setLeftString(String.format(resources.getString(R.string.about_cache_size), CacheUtils.getTotalCacheSize(requireContext()))) binding!!.menuCache.setLeftString(String.format(resources.getString(R.string.about_cache_size), CacheUtils.getTotalCacheSize(requireContext())))

@ -275,7 +275,7 @@ class ClientFragment : BaseFragment<FragmentClientBinding?>(), View.OnClickListe
val timestamp = System.currentTimeMillis() val timestamp = System.currentTimeMillis()
msgMap["timestamp"] = timestamp msgMap["timestamp"] = timestamp
val clientSignKey = HttpServerUtils.clientSignKey.toString() val clientSignKey = HttpServerUtils.clientSignKey
if (HttpServerUtils.clientSafetyMeasures != 0 && TextUtils.isEmpty(clientSignKey)) { if (HttpServerUtils.clientSafetyMeasures != 0 && TextUtils.isEmpty(clientSignKey)) {
if (needToast) XToastUtils.error("请输入签名密钥/RSA公钥/SM4密钥") if (needToast) XToastUtils.error("请输入签名密钥/RSA公钥/SM4密钥")
return return
@ -298,7 +298,7 @@ class ClientFragment : BaseFragment<FragmentClientBinding?>(), View.OnClickListe
when (HttpServerUtils.clientSafetyMeasures) { when (HttpServerUtils.clientSafetyMeasures) {
2 -> { 2 -> {
try { try {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString()) val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey)
requestMsg = Base64.encode(requestMsg.toByteArray()) requestMsg = Base64.encode(requestMsg.toByteArray())
requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey) requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey)
Log.i(TAG, "requestMsg: $requestMsg") Log.i(TAG, "requestMsg: $requestMsg")
@ -311,7 +311,7 @@ class ClientFragment : BaseFragment<FragmentClientBinding?>(), View.OnClickListe
} }
3 -> { 3 -> {
try { try {
val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey.toString()) val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey)
//requestMsg = Base64.encode(requestMsg.toByteArray()) //requestMsg = Base64.encode(requestMsg.toByteArray())
val encryptCBC = SM4Crypt.encrypt(requestMsg.toByteArray(), sm4Key) val encryptCBC = SM4Crypt.encrypt(requestMsg.toByteArray(), sm4Key)
requestMsg = ConvertTools.bytes2HexString(encryptCBC) requestMsg = ConvertTools.bytes2HexString(encryptCBC)
@ -340,11 +340,11 @@ class ClientFragment : BaseFragment<FragmentClientBinding?>(), View.OnClickListe
try { try {
var json = response var json = response
if (HttpServerUtils.clientSafetyMeasures == 2) { if (HttpServerUtils.clientSafetyMeasures == 2) {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString()) val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey)
json = RSACrypt.decryptByPublicKey(json, publicKey) json = RSACrypt.decryptByPublicKey(json, publicKey)
json = String(Base64.decode(json)) json = String(Base64.decode(json))
} else if (HttpServerUtils.clientSafetyMeasures == 3) { } else if (HttpServerUtils.clientSafetyMeasures == 3) {
val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey.toString()) val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey)
val encryptCBC = ConvertTools.hexStringToByteArray(json) val encryptCBC = ConvertTools.hexStringToByteArray(json)
val decryptCBC = SM4Crypt.decrypt(encryptCBC, sm4Key) val decryptCBC = SM4Crypt.decrypt(encryptCBC, sm4Key)
json = String(decryptCBC) json = String(decryptCBC)
@ -354,9 +354,9 @@ class ClientFragment : BaseFragment<FragmentClientBinding?>(), View.OnClickListe
serverConfig = resp.data!! serverConfig = resp.data!!
if (needToast) XToastUtils.success(ResUtils.getString(R.string.request_succeeded)) if (needToast) XToastUtils.success(ResUtils.getString(R.string.request_succeeded))
//删除3.0.8之前保存的记录 //删除3.0.8之前保存的记录
serverHistory.remove(HttpServerUtils.serverAddress.toString()) serverHistory.remove(HttpServerUtils.serverAddress)
//添加到历史记录 //添加到历史记录
val key = "${serverConfig?.extraDeviceMark}${HttpServerUtils.serverAddress.toString()}" val key = "${serverConfig?.extraDeviceMark}${HttpServerUtils.serverAddress}"
if (TextUtils.isEmpty(HttpServerUtils.clientSignKey)) { if (TextUtils.isEmpty(HttpServerUtils.clientSignKey)) {
serverHistory[key] = "SMSFORWARDER##" + HttpServerUtils.clientSafetyMeasures.toString() serverHistory[key] = "SMSFORWARDER##" + HttpServerUtils.clientSafetyMeasures.toString()
} else { } else {

@ -79,23 +79,15 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
switchEnableSms(binding!!.sbEnableSms) switchEnableSms(binding!!.sbEnableSms)
//转发通话记录 //转发通话记录
switchEnablePhone( switchEnablePhone(
binding!!.sbEnablePhone, binding!!.sbEnablePhone, binding!!.scbCallType1, binding!!.scbCallType2, binding!!.scbCallType3, binding!!.scbCallType4
binding!!.scbCallType1,
binding!!.scbCallType2,
binding!!.scbCallType3,
binding!!.scbCallType4
) )
//转发应用通知 //转发应用通知
switchEnableAppNotify( switchEnableAppNotify(
binding!!.sbEnableAppNotify, binding!!.sbEnableAppNotify, binding!!.scbCancelAppNotify, binding!!.scbNotUserPresent
binding!!.scbCancelAppNotify,
binding!!.scbNotUserPresent
) )
//启动时异步获取已安装App信息 //启动时异步获取已安装App信息
switchEnableLoadAppList( switchEnableLoadAppList(
binding!!.sbEnableLoadAppList, binding!!.sbEnableLoadAppList, binding!!.scbLoadUserApp, binding!!.scbLoadSystemApp
binding!!.scbLoadUserApp,
binding!!.scbLoadSystemApp
) )
//过滤多久内重复消息 //过滤多久内重复消息
binding!!.xsbDuplicateMessagesLimits.setDefaultValue(SettingUtils.duplicateMessagesLimits) binding!!.xsbDuplicateMessagesLimits.setDefaultValue(SettingUtils.duplicateMessagesLimits)
@ -103,8 +95,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
SettingUtils.duplicateMessagesLimits = newValue SettingUtils.duplicateMessagesLimits = newValue
} }
//免打扰(禁用转发)时间段 //免打扰(禁用转发)时间段
binding!!.tvSilentPeriod.text = binding!!.tvSilentPeriod.text = mTimeOption[SettingUtils.silentPeriodStart] + " ~ " + mTimeOption[SettingUtils.silentPeriodEnd]
mTimeOption[SettingUtils.silentPeriodStart] + " ~ " + mTimeOption[SettingUtils.silentPeriodEnd]
//自动删除N天前的转发记录 //自动删除N天前的转发记录
binding!!.xsbAutoCleanLogs.setDefaultValue(SettingUtils.autoCleanLogsDays) binding!!.xsbAutoCleanLogs.setDefaultValue(SettingUtils.autoCleanLogsDays)
binding!!.xsbAutoCleanLogs.setOnSeekBarListener { _: XSeekBar?, newValue: Int -> binding!!.xsbAutoCleanLogs.setOnSeekBarListener { _: XSeekBar?, newValue: Int ->
@ -129,9 +120,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
//Cactus增强保活措施 //Cactus增强保活措施
switchEnableCactus( switchEnableCactus(
binding!!.sbEnableCactus, binding!!.sbEnableCactus, binding!!.scbPlaySilenceMusic, binding!!.scbOnePixelActivity
binding!!.scbPlaySilenceMusic,
binding!!.scbOnePixelActivity
) )
//接口请求失败重试时间间隔 //接口请求失败重试时间间隔
@ -176,18 +165,14 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
val etSmsTemplate: EditText = binding!!.etSmsTemplate val etSmsTemplate: EditText = binding!!.etSmsTemplate
when (v.id) { when (v.id) {
R.id.btn_silent_period -> { R.id.btn_silent_period -> {
OptionsPickerBuilder( OptionsPickerBuilder(context, OnOptionsSelectListener { _: View?, options1: Int, options2: Int, _: Int ->
context,
OnOptionsSelectListener { _: View?, options1: Int, options2: Int, _: Int ->
SettingUtils.silentPeriodStart = options1 SettingUtils.silentPeriodStart = options1
SettingUtils.silentPeriodEnd = options2 SettingUtils.silentPeriodEnd = options2
val txt = mTimeOption[options1] + " ~ " + mTimeOption[options2] val txt = mTimeOption[options1] + " ~ " + mTimeOption[options2]
binding!!.tvSilentPeriod.text = txt binding!!.tvSilentPeriod.text = txt
XToastUtils.toast(txt) XToastUtils.toast(txt)
return@OnOptionsSelectListener false return@OnOptionsSelectListener false
}).setTitleText(getString(R.string.select_time_period)) }).setTitleText(getString(R.string.select_time_period)).setSelectOptions(SettingUtils.silentPeriodStart, SettingUtils.silentPeriodEnd).build<Any>().also {
.setSelectOptions(SettingUtils.silentPeriodStart, SettingUtils.silentPeriodEnd)
.build<Any>().also {
it.setNPicker(mTimeOption, mTimeOption) it.setNPicker(mTimeOption, mTimeOption)
it.show() it.show()
} }
@ -201,8 +186,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
if (App.SimInfoList.isEmpty()) { if (App.SimInfoList.isEmpty()) {
XToastUtils.error(R.string.tip_can_not_get_sim_infos) XToastUtils.error(R.string.tip_can_not_get_sim_infos)
XXPermissions.startPermissionActivity( XXPermissions.startPermissionActivity(
requireContext(), requireContext(), "android.permission.READ_PHONE_STATE"
"android.permission.READ_PHONE_STATE"
) )
return return
} }
@ -210,8 +194,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
if (!App.SimInfoList.containsKey(0)) { if (!App.SimInfoList.containsKey(0)) {
XToastUtils.error( XToastUtils.error(
String.format( String.format(
getString(R.string.tip_can_not_get_sim_info), getString(R.string.tip_can_not_get_sim_info), 1
1
) )
) )
return return
@ -225,8 +208,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
if (App.SimInfoList.isEmpty()) { if (App.SimInfoList.isEmpty()) {
XToastUtils.error(R.string.tip_can_not_get_sim_infos) XToastUtils.error(R.string.tip_can_not_get_sim_infos)
XXPermissions.startPermissionActivity( XXPermissions.startPermissionActivity(
requireContext(), requireContext(), "android.permission.READ_PHONE_STATE"
"android.permission.READ_PHONE_STATE"
) )
return return
} }
@ -234,8 +216,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
if (!App.SimInfoList.containsKey(1)) { if (!App.SimInfoList.containsKey(1)) {
XToastUtils.error( XToastUtils.error(
String.format( String.format(
getString(R.string.tip_can_not_get_sim_info), getString(R.string.tip_can_not_get_sim_info), 2
2
) )
) )
return return
@ -254,22 +235,19 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
} }
R.id.bt_insert_extra -> { R.id.bt_insert_extra -> {
CommonUtils.insertOrReplaceText2Cursor( CommonUtils.insertOrReplaceText2Cursor(
etSmsTemplate, etSmsTemplate, getString(R.string.tag_card_slot)
getString(R.string.tag_card_slot)
) )
return return
} }
R.id.bt_insert_time -> { R.id.bt_insert_time -> {
CommonUtils.insertOrReplaceText2Cursor( CommonUtils.insertOrReplaceText2Cursor(
etSmsTemplate, etSmsTemplate, getString(R.string.tag_receive_time)
getString(R.string.tag_receive_time)
) )
return return
} }
R.id.bt_insert_device_name -> { R.id.bt_insert_device_name -> {
CommonUtils.insertOrReplaceText2Cursor( CommonUtils.insertOrReplaceText2Cursor(
etSmsTemplate, etSmsTemplate, getString(R.string.tag_device_name)
getString(R.string.tag_device_name)
) )
return return
} }
@ -291,8 +269,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
// 发送短信 // 发送短信
//.permission(Permission.SEND_SMS) //.permission(Permission.SEND_SMS)
// 读取短信 // 读取短信
.permission(Permission.READ_SMS) .permission(Permission.READ_SMS).request(object : OnPermissionCallback {
.request(object : OnPermissionCallback {
override fun onGranted(permissions: List<String>, all: Boolean) { override fun onGranted(permissions: List<String>, all: Boolean) {
if (all) { if (all) {
XToastUtils.info(R.string.toast_granted_all) XToastUtils.info(R.string.toast_granted_all)
@ -320,11 +297,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
//转发通话 //转发通话
@SuppressLint("UseSwitchCompatOrMaterialCode") @SuppressLint("UseSwitchCompatOrMaterialCode")
fun switchEnablePhone( fun switchEnablePhone(
sbEnablePhone: SwitchButton, sbEnablePhone: SwitchButton, scbCallType1: SmoothCheckBox, scbCallType2: SmoothCheckBox, scbCallType3: SmoothCheckBox, scbCallType4: SmoothCheckBox
scbCallType1: SmoothCheckBox,
scbCallType2: SmoothCheckBox,
scbCallType3: SmoothCheckBox,
scbCallType4: SmoothCheckBox
) { ) {
sbEnablePhone.isChecked = SettingUtils.enablePhone sbEnablePhone.isChecked = SettingUtils.enablePhone
scbCallType1.isChecked = SettingUtils.enableCallType1 scbCallType1.isChecked = SettingUtils.enableCallType1
@ -349,8 +322,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
// 读取通话记录 // 读取通话记录
.permission(Permission.READ_CALL_LOG) .permission(Permission.READ_CALL_LOG)
// 读取联系人 // 读取联系人
.permission(Permission.READ_CONTACTS) .permission(Permission.READ_CONTACTS).request(object : OnPermissionCallback {
.request(object : OnPermissionCallback {
override fun onGranted(permissions: List<String>, all: Boolean) { override fun onGranted(permissions: List<String>, all: Boolean) {
if (all) { if (all) {
XToastUtils.info(R.string.toast_granted_all) XToastUtils.info(R.string.toast_granted_all)
@ -410,9 +382,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
//转发应用通知 //转发应用通知
@SuppressLint("UseSwitchCompatOrMaterialCode") @SuppressLint("UseSwitchCompatOrMaterialCode")
fun switchEnableAppNotify( fun switchEnableAppNotify(
sbEnableAppNotify: SwitchButton, sbEnableAppNotify: SwitchButton, scbCancelAppNotify: SmoothCheckBox, scbNotUserPresent: SmoothCheckBox
scbCancelAppNotify: SmoothCheckBox,
scbNotUserPresent: SmoothCheckBox
) { ) {
val layoutOptionalAction: LinearLayout = binding!!.layoutOptionalAction val layoutOptionalAction: LinearLayout = binding!!.layoutOptionalAction
val isEnable: Boolean = SettingUtils.enableAppNotify val isEnable: Boolean = SettingUtils.enableAppNotify
@ -428,8 +398,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
// 通知栏监听权限 // 通知栏监听权限
.permission(Permission.BIND_NOTIFICATION_LISTENER_SERVICE) .permission(Permission.BIND_NOTIFICATION_LISTENER_SERVICE)
// 通知栏权限 // 通知栏权限
.permission(Permission.NOTIFICATION_SERVICE) .permission(Permission.NOTIFICATION_SERVICE).request(object : OnPermissionCallback {
.request(object : OnPermissionCallback {
override fun onGranted(permissions: List<String>, all: Boolean) { override fun onGranted(permissions: List<String>, all: Boolean) {
SettingUtils.enableAppNotify = true SettingUtils.enableAppNotify = true
sbEnableAppNotify.isChecked = true sbEnableAppNotify.isChecked = true
@ -441,17 +410,11 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
sbEnableAppNotify.isChecked = false sbEnableAppNotify.isChecked = false
XToastUtils.error(R.string.tips_notification_listener) XToastUtils.error(R.string.tips_notification_listener)
// 如果是被永久拒绝就跳转到应用权限系统设置页面 // 如果是被永久拒绝就跳转到应用权限系统设置页面
MaterialDialog.Builder(context!!) MaterialDialog.Builder(context!!).content(R.string.toast_denied_never).positiveText(R.string.lab_yes).negativeText(R.string.lab_no).onPositive { _: MaterialDialog?, _: DialogAction? ->
.content(R.string.toast_denied_never)
.positiveText(R.string.lab_yes)
.negativeText(R.string.lab_no)
.onPositive { _: MaterialDialog?, _: DialogAction? ->
XXPermissions.startPermissionActivity( XXPermissions.startPermissionActivity(
requireContext(), requireContext(), permissions
permissions
) )
} }.show()
.show()
} }
}) })
} }
@ -469,9 +432,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
//启动时异步获取已安装App信息 (binding!!.sbEnableLoadAppList, binding!!.scbLoadUserApp, binding!!.scbLoadSystemApp) //启动时异步获取已安装App信息 (binding!!.sbEnableLoadAppList, binding!!.scbLoadUserApp, binding!!.scbLoadSystemApp)
@SuppressLint("UseSwitchCompatOrMaterialCode") @SuppressLint("UseSwitchCompatOrMaterialCode")
fun switchEnableLoadAppList( fun switchEnableLoadAppList(
sbEnableLoadAppList: SwitchButton, sbEnableLoadAppList: SwitchButton, scbLoadUserApp: SmoothCheckBox, scbLoadSystemApp: SmoothCheckBox
scbLoadUserApp: SmoothCheckBox,
scbLoadSystemApp: SmoothCheckBox
) { ) {
val isEnable: Boolean = SettingUtils.enableLoadAppList val isEnable: Boolean = SettingUtils.enableLoadAppList
sbEnableLoadAppList.isChecked = isEnable sbEnableLoadAppList.isChecked = isEnable
@ -516,12 +477,10 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
//设置低电量报警 //设置低电量报警
private fun editBatteryLevelAlarm( private fun editBatteryLevelAlarm(
xrsBatteryLevelAlarm: XRangeSlider, xrsBatteryLevelAlarm: XRangeSlider, scbBatteryLevelAlarmOnce: SmoothCheckBox
scbBatteryLevelAlarmOnce: SmoothCheckBox
) { ) {
xrsBatteryLevelAlarm.setStartingMinMax( xrsBatteryLevelAlarm.setStartingMinMax(
SettingUtils.batteryLevelMin, SettingUtils.batteryLevelMin, SettingUtils.batteryLevelMax
SettingUtils.batteryLevelMax
) )
xrsBatteryLevelAlarm.setOnRangeSliderListener(object : OnRangeSliderListener { xrsBatteryLevelAlarm.setOnRangeSliderListener(object : OnRangeSliderListener {
override fun onMaxChanged(slider: XRangeSlider, maxValue: Int) { override fun onMaxChanged(slider: XRangeSlider, maxValue: Int) {
@ -548,8 +507,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
@SuppressLint("UseSwitchCompatOrMaterialCode") @SuppressLint("UseSwitchCompatOrMaterialCode")
fun switchBatteryCron(sbBatteryCron: SwitchButton) { fun switchBatteryCron(sbBatteryCron: SwitchButton) {
sbBatteryCron.isChecked = SettingUtils.enableBatteryCron sbBatteryCron.isChecked = SettingUtils.enableBatteryCron
binding!!.layoutBatteryCron.visibility = binding!!.layoutBatteryCron.visibility = if (SettingUtils.enableBatteryCron) View.VISIBLE else View.GONE
if (SettingUtils.enableBatteryCron) View.VISIBLE else View.GONE
sbBatteryCron.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean -> sbBatteryCron.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean ->
binding!!.layoutBatteryCron.visibility = if (isChecked) View.VISIBLE else View.GONE binding!!.layoutBatteryCron.visibility = if (isChecked) View.VISIBLE else View.GONE
SettingUtils.enableBatteryCron = isChecked SettingUtils.enableBatteryCron = isChecked
@ -560,8 +518,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
//设置推送电池状态时机 //设置推送电池状态时机
private fun editBatteryCronTiming( private fun editBatteryCronTiming(
etBatteryCronStartTime: EditText, etBatteryCronStartTime: EditText, etBatteryCronInterval: EditText
etBatteryCronInterval: EditText
) { ) {
etBatteryCronStartTime.setText(SettingUtils.batteryCronStartTime) etBatteryCronStartTime.setText(SettingUtils.batteryCronStartTime)
etBatteryCronStartTime.setOnClickListener { etBatteryCronStartTime.setOnClickListener {
@ -573,12 +530,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
//BatteryReportCronTask.getSingleton().updateTimer() //BatteryReportCronTask.getSingleton().updateTimer()
} }
//.setTimeSelectChangeListener { date: Date? -> etBatteryCronStartTime.setText(DateUtils.date2String(date, DateUtils.HHmm.get())) } //.setTimeSelectChangeListener { date: Date? -> etBatteryCronStartTime.setText(DateUtils.date2String(date, DateUtils.HHmm.get())) }
.setType(false, false, false, true, true, false) .setType(false, false, false, true, true, false).setTitleText(getString(R.string.time_picker)).setSubmitText(getString(R.string.ok)).setCancelText(getString(R.string.cancel)).setDate(calendar).build()
.setTitleText(getString(R.string.time_picker))
.setSubmitText(getString(R.string.ok))
.setCancelText(getString(R.string.cancel))
.setDate(calendar)
.build()
mTimePicker.show() mTimePicker.show()
} }
@ -601,8 +553,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
//开机启动 //开机启动
private fun checkWithReboot( private fun checkWithReboot(
@SuppressLint("UseSwitchCompatOrMaterialCode") sbWithReboot: SwitchButton, @SuppressLint("UseSwitchCompatOrMaterialCode") sbWithReboot: SwitchButton, tvAutoStartup: TextView
tvAutoStartup: TextView
) { ) {
tvAutoStartup.text = getAutoStartTips() tvAutoStartup.text = getAutoStartTips()
@ -610,12 +561,10 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
val cm = ComponentName(getAppPackageName(), BootReceiver::class.java.name) val cm = ComponentName(getAppPackageName(), BootReceiver::class.java.name)
val pm: PackageManager = getPackageManager() val pm: PackageManager = getPackageManager()
val state = pm.getComponentEnabledSetting(cm) val state = pm.getComponentEnabledSetting(cm)
sbWithReboot.isChecked = sbWithReboot.isChecked = !(state == PackageManager.COMPONENT_ENABLED_STATE_DISABLED || state == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER)
(state != PackageManager.COMPONENT_ENABLED_STATE_DISABLED && state != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER)
sbWithReboot.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean -> sbWithReboot.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean ->
try { try {
val newState = val newState = if (isChecked) PackageManager.COMPONENT_ENABLED_STATE_ENABLED else PackageManager.COMPONENT_ENABLED_STATE_DISABLED
if (isChecked) PackageManager.COMPONENT_ENABLED_STATE_ENABLED else PackageManager.COMPONENT_ENABLED_STATE_DISABLED
pm.setComponentEnabledSetting(cm, newState, PackageManager.DONT_KILL_APP) pm.setComponentEnabledSetting(cm, newState, PackageManager.DONT_KILL_APP)
if (isChecked) startToAutoStartSetting(requireContext()) if (isChecked) startToAutoStartSetting(requireContext())
} catch (e: Exception) { } catch (e: Exception) {
@ -635,8 +584,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
} }
try { try {
val isIgnoreBatteryOptimization: Boolean = val isIgnoreBatteryOptimization: Boolean = KeepAliveUtils.isIgnoreBatteryOptimization(requireActivity())
KeepAliveUtils.isIgnoreBatteryOptimization(requireActivity())
sbBatterySetting.isChecked = isIgnoreBatteryOptimization sbBatterySetting.isChecked = isIgnoreBatteryOptimization
sbBatterySetting.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean -> sbBatterySetting.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean ->
if (isChecked && !isIgnoreBatteryOptimization) { if (isChecked && !isIgnoreBatteryOptimization) {
@ -657,8 +605,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
//不在最近任务列表中显示 //不在最近任务列表中显示
@SuppressLint("ObsoleteSdkInt,UseSwitchCompatOrMaterialCode") @SuppressLint("ObsoleteSdkInt,UseSwitchCompatOrMaterialCode")
fun switchExcludeFromRecents( fun switchExcludeFromRecents(
layoutExcludeFromRecents: LinearLayout, layoutExcludeFromRecents: LinearLayout, sbExcludeFromRecents: SwitchButton
sbExcludeFromRecents: SwitchButton
) { ) {
//安卓6.0以下没有不在最近任务列表中显示 //安卓6.0以下没有不在最近任务列表中显示
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
@ -683,9 +630,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
//转发应用通知 //转发应用通知
@SuppressLint("UseSwitchCompatOrMaterialCode") @SuppressLint("UseSwitchCompatOrMaterialCode")
fun switchEnableCactus( fun switchEnableCactus(
sbEnableCactus: SwitchButton, sbEnableCactus: SwitchButton, scbPlaySilenceMusic: SmoothCheckBox, scbOnePixelActivity: SmoothCheckBox
scbPlaySilenceMusic: SmoothCheckBox,
scbOnePixelActivity: SmoothCheckBox
) { ) {
val layoutCactusOptional: LinearLayout = binding!!.layoutCactusOptional val layoutCactusOptional: LinearLayout = binding!!.layoutCactusOptional
val isEnable: Boolean = SettingUtils.enableCactus val isEnable: Boolean = SettingUtils.enableCactus
@ -716,9 +661,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
//接口请求失败重试时间间隔 //接口请求失败重试时间间隔
private fun editRetryDelayTime( private fun editRetryDelayTime(
etRetryTimes: EditText, etRetryTimes: EditText, etDelayTime: EditText, etTimeout: EditText
etDelayTime: EditText,
etTimeout: EditText
) { ) {
etRetryTimes.setText(java.lang.String.valueOf(SettingUtils.requestRetryTimes)) etRetryTimes.setText(java.lang.String.valueOf(SettingUtils.requestRetryTimes))
etRetryTimes.addTextChangedListener(object : TextWatcher { etRetryTimes.addTextChangedListener(object : TextWatcher {
@ -818,8 +761,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {} override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
override fun afterTextChanged(s: Editable) { override fun afterTextChanged(s: Editable) {
SettingUtils.notifyContent = etNotifyContent.text.toString().trim() SettingUtils.notifyContent = etNotifyContent.text.toString().trim()
LiveEventBus.get(EVENT_UPDATE_NOTIFY, String::class.java) LiveEventBus.get(EVENT_UPDATE_NOTIFY, String::class.java).post(SettingUtils.notifyContent)
.post(SettingUtils.notifyContent.toString())
} }
}) })
} }
@ -875,14 +817,9 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
switchDirectlyToClient.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean -> switchDirectlyToClient.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean ->
SettingUtils.enablePureClientMode = isChecked SettingUtils.enablePureClientMode = isChecked
if (isChecked) { if (isChecked) {
MaterialDialog.Builder(requireContext()) MaterialDialog.Builder(requireContext()).content(getString(R.string.enabling_pure_client_mode)).positiveText(R.string.lab_yes).onPositive { _: MaterialDialog?, _: DialogAction? ->
.content(getString(R.string.enabling_pure_client_mode))
.positiveText(R.string.lab_yes)
.onPositive { _: MaterialDialog?, _: DialogAction? ->
XUtil.exitApp() XUtil.exitApp()
} }.negativeText(R.string.lab_no).show()
.negativeText(R.string.lab_no)
.show()
} }
} }
} }
@ -914,37 +851,19 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
) )
put( put(
"samsung", listOf( "samsung", listOf(
"com.samsung.android.sm_cn/com.samsung.android.sm.ui.ram.AutoRunActivity", "com.samsung.android.sm_cn/com.samsung.android.sm.ui.ram.AutoRunActivity", "com.samsung.android.sm_cn/com.samsung.android.sm.ui.appmanagement.AppManagementActivity", "com.samsung.android.sm_cn/com.samsung.android.sm.ui.cstyleboard.SmartManagerDashBoardActivity", "com.samsung.android.sm_cn/.ui.ram.RamActivity", "com.samsung.android.sm_cn/.app.dashboard.SmartManagerDashBoardActivity", "com.samsung.android.sm/com.samsung.android.sm.ui.ram.AutoRunActivity", "com.samsung.android.sm/com.samsung.android.sm.ui.appmanagement.AppManagementActivity", "com.samsung.android.sm/com.samsung.android.sm.ui.cstyleboard.SmartManagerDashBoardActivity", "com.samsung.android.sm/.ui.ram.RamActivity", "com.samsung.android.sm/.app.dashboard.SmartManagerDashBoardActivity", "com.samsung.android.lool/com.samsung.android.sm.ui.battery.BatteryActivity", "com.samsung.android.sm_cn", "com.samsung.android.sm"
"com.samsung.android.sm_cn/com.samsung.android.sm.ui.appmanagement.AppManagementActivity",
"com.samsung.android.sm_cn/com.samsung.android.sm.ui.cstyleboard.SmartManagerDashBoardActivity",
"com.samsung.android.sm_cn/.ui.ram.RamActivity",
"com.samsung.android.sm_cn/.app.dashboard.SmartManagerDashBoardActivity",
"com.samsung.android.sm/com.samsung.android.sm.ui.ram.AutoRunActivity",
"com.samsung.android.sm/com.samsung.android.sm.ui.appmanagement.AppManagementActivity",
"com.samsung.android.sm/com.samsung.android.sm.ui.cstyleboard.SmartManagerDashBoardActivity",
"com.samsung.android.sm/.ui.ram.RamActivity",
"com.samsung.android.sm/.app.dashboard.SmartManagerDashBoardActivity",
"com.samsung.android.lool/com.samsung.android.sm.ui.battery.BatteryActivity",
"com.samsung.android.sm_cn",
"com.samsung.android.sm"
) )
) )
put( put(
"HUAWEI", listOf( "HUAWEI", listOf(
"com.huawei.systemmanager/.startupmgr.ui.StartupNormalAppListActivity", //EMUI9.1.0(方舟,9.0) "com.huawei.systemmanager/.startupmgr.ui.StartupNormalAppListActivity", //EMUI9.1.0(方舟,9.0)
"com.huawei.systemmanager/.appcontrol.activity.StartupAppControlActivity", "com.huawei.systemmanager/.appcontrol.activity.StartupAppControlActivity", "com.huawei.systemmanager/.optimize.process.ProtectActivity", "com.huawei.systemmanager/.optimize.bootstart.BootStartActivity", "com.huawei.systemmanager" //最后一行可以写包名, 这样如果签名的类路径在某些新版本的ROM中没找到 就直接跳转到对应的安全中心/手机管家 首页.
"com.huawei.systemmanager/.optimize.process.ProtectActivity",
"com.huawei.systemmanager/.optimize.bootstart.BootStartActivity",
"com.huawei.systemmanager" //最后一行可以写包名, 这样如果签名的类路径在某些新版本的ROM中没找到 就直接跳转到对应的安全中心/手机管家 首页.
) )
) )
put( put(
"vivo", listOf( "vivo", listOf(
"com.iqoo.secure/.ui.phoneoptimize.BgStartUpManager", "com.iqoo.secure/.ui.phoneoptimize.BgStartUpManager", "com.iqoo.secure/.safeguard.PurviewTabActivity", "com.vivo.permissionmanager/.activity.BgStartUpManagerActivity", //"com.iqoo.secure/.ui.phoneoptimize.AddWhiteListActivity", //这是白名单, 不是自启动
"com.iqoo.secure/.safeguard.PurviewTabActivity", "com.iqoo.secure", "com.vivo.permissionmanager"
"com.vivo.permissionmanager/.activity.BgStartUpManagerActivity", //"com.iqoo.secure/.ui.phoneoptimize.AddWhiteListActivity", //这是白名单, 不是自启动
"com.iqoo.secure",
"com.vivo.permissionmanager"
) )
) )
put( put(
@ -956,95 +875,77 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
) )
put( put(
"OPPO", listOf( "OPPO", listOf(
"com.coloros.safecenter/.startupapp.StartupAppListActivity", "com.coloros.safecenter/.startupapp.StartupAppListActivity", "com.coloros.safecenter/.permission.startup.StartupAppListActivity", "com.oppo.safe/.permission.startup.StartupAppListActivity", "com.coloros.oppoguardelf/com.coloros.powermanager.fuelgaue.PowerUsageModelActivity", "com.coloros.safecenter/com.coloros.privacypermissionsentry.PermissionTopActivity", "com.coloros.safecenter", "com.oppo.safe", "com.coloros.oppoguardelf"
"com.coloros.safecenter/.permission.startup.StartupAppListActivity",
"com.oppo.safe/.permission.startup.StartupAppListActivity",
"com.coloros.oppoguardelf/com.coloros.powermanager.fuelgaue.PowerUsageModelActivity",
"com.coloros.safecenter/com.coloros.privacypermissionsentry.PermissionTopActivity",
"com.coloros.safecenter",
"com.oppo.safe",
"com.coloros.oppoguardelf"
) )
) )
put( put(
"oneplus", listOf( "oneplus", listOf(
"com.oneplus.security/.chainlaunch.view.ChainLaunchAppListActivity", "com.oneplus.security/.chainlaunch.view.ChainLaunchAppListActivity", "com.oneplus.security"
"com.oneplus.security"
) )
) )
put( put(
"letv", listOf( "letv", listOf(
"com.letv.android.letvsafe/.AutobootManageActivity", "com.letv.android.letvsafe/.AutobootManageActivity", "com.letv.android.letvsafe/.BackgroundAppManageActivity", //应用保护
"com.letv.android.letvsafe/.BackgroundAppManageActivity", //应用保护
"com.letv.android.letvsafe" "com.letv.android.letvsafe"
) )
) )
put( put(
"zte", listOf( "zte", listOf(
"com.zte.heartyservice/.autorun.AppAutoRunManager", "com.zte.heartyservice/.autorun.AppAutoRunManager", "com.zte.heartyservice"
"com.zte.heartyservice"
) )
) )
//金立 //金立
put( put(
"F", listOf( "F", listOf(
"com.gionee.softmanager/.MainActivity", "com.gionee.softmanager/.MainActivity", "com.gionee.softmanager"
"com.gionee.softmanager"
) )
) )
//以下为未确定(厂商名也不确定) //以下为未确定(厂商名也不确定)
put( put(
"smartisanos", listOf( "smartisanos", listOf(
"com.smartisanos.security/.invokeHistory.InvokeHistoryActivity", "com.smartisanos.security/.invokeHistory.InvokeHistoryActivity", "com.smartisanos.security"
"com.smartisanos.security"
) )
) )
//360 //360
put( put(
"360", listOf( "360", listOf(
"com.yulong.android.coolsafe/.ui.activity.autorun.AutoRunListActivity", "com.yulong.android.coolsafe/.ui.activity.autorun.AutoRunListActivity", "com.yulong.android.coolsafe"
"com.yulong.android.coolsafe"
) )
) )
//360 //360
put( put(
"ulong", listOf( "ulong", listOf(
"com.yulong.android.coolsafe/.ui.activity.autorun.AutoRunListActivity", "com.yulong.android.coolsafe/.ui.activity.autorun.AutoRunListActivity", "com.yulong.android.coolsafe"
"com.yulong.android.coolsafe"
) )
) )
//酷派 //酷派
put( put(
"coolpad" /*厂商名称不确定是否正确*/, listOf( "coolpad" /*厂商名称不确定是否正确*/, listOf(
"com.yulong.android.security/com.yulong.android.seccenter.tabbarmain", "com.yulong.android.security/com.yulong.android.seccenter.tabbarmain", "com.yulong.android.security"
"com.yulong.android.security"
) )
) )
//联想 //联想
put( put(
"lenovo" /*厂商名称不确定是否正确*/, listOf( "lenovo" /*厂商名称不确定是否正确*/, listOf(
"com.lenovo.security/.purebackground.PureBackgroundActivity", "com.lenovo.security/.purebackground.PureBackgroundActivity", "com.lenovo.security"
"com.lenovo.security"
) )
) )
put( put(
"htc" /*厂商名称不确定是否正确*/, listOf( "htc" /*厂商名称不确定是否正确*/, listOf(
"com.htc.pitroad/.landingpage.activity.LandingPageActivity", "com.htc.pitroad/.landingpage.activity.LandingPageActivity", "com.htc.pitroad"
"com.htc.pitroad"
) )
) )
//华硕 //华硕
put( put(
"asus" /*厂商名称不确定是否正确*/, listOf( "asus" /*厂商名称不确定是否正确*/, listOf(
"com.asus.mobilemanager/.MainActivity", "com.asus.mobilemanager/.MainActivity", "com.asus.mobilemanager"
"com.asus.mobilemanager"
) )
) )
} }
@ -1069,8 +970,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
} else { } else {
//找不到? 网上的做法都是跳转到设置... 这基本上是没意义的 基本上自启动这个功能是第三方厂商自己写的安全管家类app //找不到? 网上的做法都是跳转到设置... 这基本上是没意义的 基本上自启动这个功能是第三方厂商自己写的安全管家类app
//所以我是直接跳转到对应的安全管家/安全中心 //所以我是直接跳转到对应的安全管家/安全中心
intent = intent = act?.let { context.packageManager.getLaunchIntentForPackage(it) }
act?.let { context.packageManager.getLaunchIntentForPackage(it) }
} }
context.startActivity(intent) context.startActivity(intent)
has = true has = true

@ -54,7 +54,7 @@ class BatteryQueryFragment : BaseFragment<FragmentClientBatteryQueryBinding?>()
msgMap["timestamp"] = timestamp msgMap["timestamp"] = timestamp
val clientSignKey = HttpServerUtils.clientSignKey val clientSignKey = HttpServerUtils.clientSignKey
if (!TextUtils.isEmpty(clientSignKey)) { if (!TextUtils.isEmpty(clientSignKey)) {
msgMap["sign"] = HttpServerUtils.calcSign(timestamp.toString(), clientSignKey.toString()) msgMap["sign"] = HttpServerUtils.calcSign(timestamp.toString(), clientSignKey)
} }
val dataMap: MutableMap<String, Any> = mutableMapOf() val dataMap: MutableMap<String, Any> = mutableMapOf()
msgMap["data"] = dataMap msgMap["data"] = dataMap
@ -71,7 +71,7 @@ class BatteryQueryFragment : BaseFragment<FragmentClientBatteryQueryBinding?>()
when (HttpServerUtils.clientSafetyMeasures) { when (HttpServerUtils.clientSafetyMeasures) {
2 -> { 2 -> {
try { try {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString()) val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey)
requestMsg = Base64.encode(requestMsg.toByteArray()) requestMsg = Base64.encode(requestMsg.toByteArray())
requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey) requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey)
Log.i(TAG, "requestMsg: $requestMsg") Log.i(TAG, "requestMsg: $requestMsg")
@ -84,7 +84,7 @@ class BatteryQueryFragment : BaseFragment<FragmentClientBatteryQueryBinding?>()
} }
3 -> { 3 -> {
try { try {
val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey.toString()) val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey)
//requestMsg = Base64.encode(requestMsg.toByteArray()) //requestMsg = Base64.encode(requestMsg.toByteArray())
val encryptCBC = SM4Crypt.encrypt(requestMsg.toByteArray(), sm4Key) val encryptCBC = SM4Crypt.encrypt(requestMsg.toByteArray(), sm4Key)
requestMsg = ConvertTools.bytes2HexString(encryptCBC) requestMsg = ConvertTools.bytes2HexString(encryptCBC)
@ -111,11 +111,11 @@ class BatteryQueryFragment : BaseFragment<FragmentClientBatteryQueryBinding?>()
try { try {
var json = response var json = response
if (HttpServerUtils.clientSafetyMeasures == 2) { if (HttpServerUtils.clientSafetyMeasures == 2) {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString()) val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey)
json = RSACrypt.decryptByPublicKey(json, publicKey) json = RSACrypt.decryptByPublicKey(json, publicKey)
json = String(Base64.decode(json)) json = String(Base64.decode(json))
} else if (HttpServerUtils.clientSafetyMeasures == 3) { } else if (HttpServerUtils.clientSafetyMeasures == 3) {
val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey.toString()) val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey)
val encryptCBC = ConvertTools.hexStringToByteArray(json) val encryptCBC = ConvertTools.hexStringToByteArray(json)
val decryptCBC = SM4Crypt.decrypt(encryptCBC, sm4Key) val decryptCBC = SM4Crypt.decrypt(encryptCBC, sm4Key)
json = String(decryptCBC) json = String(decryptCBC)

@ -202,7 +202,7 @@ class CallQueryFragment : BaseFragment<FragmentClientCallQueryBinding?>() {
msgMap["timestamp"] = timestamp msgMap["timestamp"] = timestamp
val clientSignKey = HttpServerUtils.clientSignKey val clientSignKey = HttpServerUtils.clientSignKey
if (!TextUtils.isEmpty(clientSignKey)) { if (!TextUtils.isEmpty(clientSignKey)) {
msgMap["sign"] = HttpServerUtils.calcSign(timestamp.toString(), clientSignKey.toString()) msgMap["sign"] = HttpServerUtils.calcSign(timestamp.toString(), clientSignKey)
} }
if (refresh) pageNum = 1 if (refresh) pageNum = 1
@ -219,7 +219,7 @@ class CallQueryFragment : BaseFragment<FragmentClientCallQueryBinding?>() {
when (HttpServerUtils.clientSafetyMeasures) { when (HttpServerUtils.clientSafetyMeasures) {
2 -> { 2 -> {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString()) val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey)
try { try {
requestMsg = Base64.encode(requestMsg.toByteArray()) requestMsg = Base64.encode(requestMsg.toByteArray())
requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey) requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey)
@ -233,7 +233,7 @@ class CallQueryFragment : BaseFragment<FragmentClientCallQueryBinding?>() {
} }
3 -> { 3 -> {
try { try {
val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey.toString()) val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey)
//requestMsg = Base64.encode(requestMsg.toByteArray()) //requestMsg = Base64.encode(requestMsg.toByteArray())
val encryptCBC = SM4Crypt.encrypt(requestMsg.toByteArray(), sm4Key) val encryptCBC = SM4Crypt.encrypt(requestMsg.toByteArray(), sm4Key)
requestMsg = ConvertTools.bytes2HexString(encryptCBC) requestMsg = ConvertTools.bytes2HexString(encryptCBC)
@ -260,11 +260,11 @@ class CallQueryFragment : BaseFragment<FragmentClientCallQueryBinding?>() {
try { try {
var json = response var json = response
if (HttpServerUtils.clientSafetyMeasures == 2) { if (HttpServerUtils.clientSafetyMeasures == 2) {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString()) val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey)
json = RSACrypt.decryptByPublicKey(json, publicKey) json = RSACrypt.decryptByPublicKey(json, publicKey)
json = String(Base64.decode(json)) json = String(Base64.decode(json))
} else if (HttpServerUtils.clientSafetyMeasures == 3) { } else if (HttpServerUtils.clientSafetyMeasures == 3) {
val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey.toString()) val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey)
val encryptCBC = ConvertTools.hexStringToByteArray(json) val encryptCBC = ConvertTools.hexStringToByteArray(json)
val decryptCBC = SM4Crypt.decrypt(encryptCBC, sm4Key) val decryptCBC = SM4Crypt.decrypt(encryptCBC, sm4Key)
json = String(decryptCBC) json = String(decryptCBC)

@ -243,7 +243,7 @@ class CloneFragment : BaseFragment<FragmentClientCloneBinding?>(), View.OnClickL
val clientSignKey = HttpServerUtils.clientSignKey val clientSignKey = HttpServerUtils.clientSignKey
if (!TextUtils.isEmpty(clientSignKey)) { if (!TextUtils.isEmpty(clientSignKey)) {
msgMap["sign"] = msgMap["sign"] =
HttpServerUtils.calcSign(timestamp.toString(), clientSignKey.toString()) HttpServerUtils.calcSign(timestamp.toString(), clientSignKey)
} }
msgMap["data"] = HttpServerUtils.exportSettings() msgMap["data"] = HttpServerUtils.exportSettings()
@ -258,7 +258,7 @@ class CloneFragment : BaseFragment<FragmentClientCloneBinding?>(), View.OnClickL
when (HttpServerUtils.clientSafetyMeasures) { when (HttpServerUtils.clientSafetyMeasures) {
2 -> { 2 -> {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString()) val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey)
try { try {
requestMsg = Base64.encode(requestMsg.toByteArray()) requestMsg = Base64.encode(requestMsg.toByteArray())
requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey) requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey)
@ -272,7 +272,7 @@ class CloneFragment : BaseFragment<FragmentClientCloneBinding?>(), View.OnClickL
} }
3 -> { 3 -> {
try { try {
val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey.toString()) val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey)
//requestMsg = Base64.encode(requestMsg.toByteArray()) //requestMsg = Base64.encode(requestMsg.toByteArray())
val encryptCBC = SM4Crypt.encrypt(requestMsg.toByteArray(), sm4Key) val encryptCBC = SM4Crypt.encrypt(requestMsg.toByteArray(), sm4Key)
requestMsg = ConvertTools.bytes2HexString(encryptCBC) requestMsg = ConvertTools.bytes2HexString(encryptCBC)
@ -300,11 +300,11 @@ class CloneFragment : BaseFragment<FragmentClientCloneBinding?>(), View.OnClickL
try { try {
var json = response var json = response
if (HttpServerUtils.clientSafetyMeasures == 2) { if (HttpServerUtils.clientSafetyMeasures == 2) {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString()) val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey)
json = RSACrypt.decryptByPublicKey(json, publicKey) json = RSACrypt.decryptByPublicKey(json, publicKey)
json = String(Base64.decode(json)) json = String(Base64.decode(json))
} else if (HttpServerUtils.clientSafetyMeasures == 3) { } else if (HttpServerUtils.clientSafetyMeasures == 3) {
val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey.toString()) val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey)
val encryptCBC = ConvertTools.hexStringToByteArray(json) val encryptCBC = ConvertTools.hexStringToByteArray(json)
val decryptCBC = SM4Crypt.decrypt(encryptCBC, sm4Key) val decryptCBC = SM4Crypt.decrypt(encryptCBC, sm4Key)
json = String(decryptCBC) json = String(decryptCBC)
@ -343,7 +343,7 @@ class CloneFragment : BaseFragment<FragmentClientCloneBinding?>(), View.OnClickL
val clientSignKey = HttpServerUtils.clientSignKey val clientSignKey = HttpServerUtils.clientSignKey
if (!TextUtils.isEmpty(clientSignKey)) { if (!TextUtils.isEmpty(clientSignKey)) {
msgMap["sign"] = msgMap["sign"] =
HttpServerUtils.calcSign(timestamp.toString(), clientSignKey.toString()) HttpServerUtils.calcSign(timestamp.toString(), clientSignKey)
} }
val dataMap: MutableMap<String, Any> = mutableMapOf() val dataMap: MutableMap<String, Any> = mutableMapOf()
@ -361,7 +361,7 @@ class CloneFragment : BaseFragment<FragmentClientCloneBinding?>(), View.OnClickL
when (HttpServerUtils.clientSafetyMeasures) { when (HttpServerUtils.clientSafetyMeasures) {
2 -> { 2 -> {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString()) val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey)
try { try {
requestMsg = Base64.encode(requestMsg.toByteArray()) requestMsg = Base64.encode(requestMsg.toByteArray())
requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey) requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey)
@ -375,7 +375,7 @@ class CloneFragment : BaseFragment<FragmentClientCloneBinding?>(), View.OnClickL
} }
3 -> { 3 -> {
try { try {
val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey.toString()) val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey)
//requestMsg = Base64.encode(requestMsg.toByteArray()) //requestMsg = Base64.encode(requestMsg.toByteArray())
val encryptCBC = SM4Crypt.encrypt(requestMsg.toByteArray(), sm4Key) val encryptCBC = SM4Crypt.encrypt(requestMsg.toByteArray(), sm4Key)
requestMsg = ConvertTools.bytes2HexString(encryptCBC) requestMsg = ConvertTools.bytes2HexString(encryptCBC)
@ -403,11 +403,11 @@ class CloneFragment : BaseFragment<FragmentClientCloneBinding?>(), View.OnClickL
try { try {
var json = response var json = response
if (HttpServerUtils.clientSafetyMeasures == 2) { if (HttpServerUtils.clientSafetyMeasures == 2) {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString()) val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey)
json = RSACrypt.decryptByPublicKey(json, publicKey) json = RSACrypt.decryptByPublicKey(json, publicKey)
json = String(Base64.decode(json)) json = String(Base64.decode(json))
} else if (HttpServerUtils.clientSafetyMeasures == 3) { } else if (HttpServerUtils.clientSafetyMeasures == 3) {
val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey.toString()) val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey)
val encryptCBC = ConvertTools.hexStringToByteArray(json) val encryptCBC = ConvertTools.hexStringToByteArray(json)
val decryptCBC = SM4Crypt.decrypt(encryptCBC, sm4Key) val decryptCBC = SM4Crypt.decrypt(encryptCBC, sm4Key)
json = String(decryptCBC) json = String(decryptCBC)

@ -184,7 +184,7 @@ class ContactQueryFragment : BaseFragment<FragmentClientContactQueryBinding?>()
msgMap["timestamp"] = timestamp msgMap["timestamp"] = timestamp
val clientSignKey = HttpServerUtils.clientSignKey val clientSignKey = HttpServerUtils.clientSignKey
if (!TextUtils.isEmpty(clientSignKey)) { if (!TextUtils.isEmpty(clientSignKey)) {
msgMap["sign"] = HttpServerUtils.calcSign(timestamp.toString(), clientSignKey.toString()) msgMap["sign"] = HttpServerUtils.calcSign(timestamp.toString(), clientSignKey)
} }
msgMap["data"] = if (keyword.isDigitsOnly()) msgMap["data"] = if (keyword.isDigitsOnly())
ContactQueryData(1, 20, keyword, null) ContactQueryData(1, 20, keyword, null)
@ -202,7 +202,7 @@ class ContactQueryFragment : BaseFragment<FragmentClientContactQueryBinding?>()
when (HttpServerUtils.clientSafetyMeasures) { when (HttpServerUtils.clientSafetyMeasures) {
2 -> { 2 -> {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString()) val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey)
try { try {
requestMsg = Base64.encode(requestMsg.toByteArray()) requestMsg = Base64.encode(requestMsg.toByteArray())
requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey) requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey)
@ -216,7 +216,7 @@ class ContactQueryFragment : BaseFragment<FragmentClientContactQueryBinding?>()
} }
3 -> { 3 -> {
try { try {
val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey.toString()) val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey)
//requestMsg = Base64.encode(requestMsg.toByteArray()) //requestMsg = Base64.encode(requestMsg.toByteArray())
val encryptCBC = SM4Crypt.encrypt(requestMsg.toByteArray(), sm4Key) val encryptCBC = SM4Crypt.encrypt(requestMsg.toByteArray(), sm4Key)
requestMsg = ConvertTools.bytes2HexString(encryptCBC) requestMsg = ConvertTools.bytes2HexString(encryptCBC)
@ -243,11 +243,11 @@ class ContactQueryFragment : BaseFragment<FragmentClientContactQueryBinding?>()
try { try {
var json = response var json = response
if (HttpServerUtils.clientSafetyMeasures == 2) { if (HttpServerUtils.clientSafetyMeasures == 2) {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString()) val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey)
json = RSACrypt.decryptByPublicKey(json, publicKey) json = RSACrypt.decryptByPublicKey(json, publicKey)
json = String(Base64.decode(json)) json = String(Base64.decode(json))
} else if (HttpServerUtils.clientSafetyMeasures == 3) { } else if (HttpServerUtils.clientSafetyMeasures == 3) {
val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey.toString()) val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey)
val encryptCBC = ConvertTools.hexStringToByteArray(json) val encryptCBC = ConvertTools.hexStringToByteArray(json)
val decryptCBC = SM4Crypt.decrypt(encryptCBC, sm4Key) val decryptCBC = SM4Crypt.decrypt(encryptCBC, sm4Key)
json = String(decryptCBC) json = String(decryptCBC)

@ -192,7 +192,7 @@ class SmsQueryFragment : BaseFragment<FragmentClientSmsQueryBinding?>() {
msgMap["timestamp"] = timestamp msgMap["timestamp"] = timestamp
val clientSignKey = HttpServerUtils.clientSignKey val clientSignKey = HttpServerUtils.clientSignKey
if (!TextUtils.isEmpty(clientSignKey)) { if (!TextUtils.isEmpty(clientSignKey)) {
msgMap["sign"] = HttpServerUtils.calcSign(timestamp.toString(), clientSignKey.toString()) msgMap["sign"] = HttpServerUtils.calcSign(timestamp.toString(), clientSignKey)
} }
if (refresh) pageNum = 1 if (refresh) pageNum = 1
@ -209,7 +209,7 @@ class SmsQueryFragment : BaseFragment<FragmentClientSmsQueryBinding?>() {
when (HttpServerUtils.clientSafetyMeasures) { when (HttpServerUtils.clientSafetyMeasures) {
2 -> { 2 -> {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString()) val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey)
try { try {
requestMsg = Base64.encode(requestMsg.toByteArray()) requestMsg = Base64.encode(requestMsg.toByteArray())
requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey) requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey)
@ -223,7 +223,7 @@ class SmsQueryFragment : BaseFragment<FragmentClientSmsQueryBinding?>() {
} }
3 -> { 3 -> {
try { try {
val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey.toString()) val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey)
//requestMsg = Base64.encode(requestMsg.toByteArray()) //requestMsg = Base64.encode(requestMsg.toByteArray())
val encryptCBC = SM4Crypt.encrypt(requestMsg.toByteArray(), sm4Key) val encryptCBC = SM4Crypt.encrypt(requestMsg.toByteArray(), sm4Key)
requestMsg = ConvertTools.bytes2HexString(encryptCBC) requestMsg = ConvertTools.bytes2HexString(encryptCBC)
@ -250,11 +250,11 @@ class SmsQueryFragment : BaseFragment<FragmentClientSmsQueryBinding?>() {
try { try {
var json = response var json = response
if (HttpServerUtils.clientSafetyMeasures == 2) { if (HttpServerUtils.clientSafetyMeasures == 2) {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString()) val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey)
json = RSACrypt.decryptByPublicKey(json, publicKey) json = RSACrypt.decryptByPublicKey(json, publicKey)
json = String(Base64.decode(json)) json = String(Base64.decode(json))
} else if (HttpServerUtils.clientSafetyMeasures == 3) { } else if (HttpServerUtils.clientSafetyMeasures == 3) {
val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey.toString()) val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey)
val encryptCBC = ConvertTools.hexStringToByteArray(json) val encryptCBC = ConvertTools.hexStringToByteArray(json)
val decryptCBC = SM4Crypt.decrypt(encryptCBC, sm4Key) val decryptCBC = SM4Crypt.decrypt(encryptCBC, sm4Key)
json = String(decryptCBC) json = String(decryptCBC)

@ -1,5 +1,6 @@
package com.idormy.sms.forwarder.fragment.client package com.idormy.sms.forwarder.fragment.client
import android.annotation.SuppressLint
import android.util.Log import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
@ -46,6 +47,7 @@ class SmsSendFragment : BaseFragment<FragmentClientSmsSendBinding?>(), View.OnCl
/** /**
* 初始化控件 * 初始化控件
*/ */
@SuppressLint("SetTextI18n")
override fun initViews() { override fun initViews() {
//发送按钮增加倒计时,避免重复点击 //发送按钮增加倒计时,避免重复点击
mCountDownHelper = CountDownButtonHelper(binding!!.btnSubmit, SettingUtils.requestTimeout) mCountDownHelper = CountDownButtonHelper(binding!!.btnSubmit, SettingUtils.requestTimeout)
@ -90,7 +92,7 @@ class SmsSendFragment : BaseFragment<FragmentClientSmsSendBinding?>(), View.OnCl
msgMap["timestamp"] = timestamp msgMap["timestamp"] = timestamp
val clientSignKey = HttpServerUtils.clientSignKey val clientSignKey = HttpServerUtils.clientSignKey
if (!TextUtils.isEmpty(clientSignKey)) { if (!TextUtils.isEmpty(clientSignKey)) {
msgMap["sign"] = HttpServerUtils.calcSign(timestamp.toString(), clientSignKey.toString()) msgMap["sign"] = HttpServerUtils.calcSign(timestamp.toString(), clientSignKey)
} }
val phoneNumbers = binding!!.etPhoneNumbers.text.toString() val phoneNumbers = binding!!.etPhoneNumbers.text.toString()
@ -124,7 +126,7 @@ class SmsSendFragment : BaseFragment<FragmentClientSmsSendBinding?>(), View.OnCl
when (HttpServerUtils.clientSafetyMeasures) { when (HttpServerUtils.clientSafetyMeasures) {
2 -> { 2 -> {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString()) val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey)
try { try {
requestMsg = Base64.encode(requestMsg.toByteArray()) requestMsg = Base64.encode(requestMsg.toByteArray())
requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey) requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey)
@ -138,7 +140,7 @@ class SmsSendFragment : BaseFragment<FragmentClientSmsSendBinding?>(), View.OnCl
} }
3 -> { 3 -> {
try { try {
val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey.toString()) val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey)
//requestMsg = Base64.encode(requestMsg.toByteArray()) //requestMsg = Base64.encode(requestMsg.toByteArray())
val encryptCBC = SM4Crypt.encrypt(requestMsg.toByteArray(), sm4Key) val encryptCBC = SM4Crypt.encrypt(requestMsg.toByteArray(), sm4Key)
requestMsg = ConvertTools.bytes2HexString(encryptCBC) requestMsg = ConvertTools.bytes2HexString(encryptCBC)
@ -167,11 +169,11 @@ class SmsSendFragment : BaseFragment<FragmentClientSmsSendBinding?>(), View.OnCl
try { try {
var json = response var json = response
if (HttpServerUtils.clientSafetyMeasures == 2) { if (HttpServerUtils.clientSafetyMeasures == 2) {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString()) val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey)
json = RSACrypt.decryptByPublicKey(json, publicKey) json = RSACrypt.decryptByPublicKey(json, publicKey)
json = String(Base64.decode(json)) json = String(Base64.decode(json))
} else if (HttpServerUtils.clientSafetyMeasures == 3) { } else if (HttpServerUtils.clientSafetyMeasures == 3) {
val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey.toString()) val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey)
val encryptCBC = ConvertTools.hexStringToByteArray(json) val encryptCBC = ConvertTools.hexStringToByteArray(json)
val decryptCBC = SM4Crypt.decrypt(encryptCBC, sm4Key) val decryptCBC = SM4Crypt.decrypt(encryptCBC, sm4Key)
json = String(decryptCBC) json = String(decryptCBC)

@ -113,7 +113,7 @@ class WolSendFragment : BaseFragment<FragmentClientWolSendBinding?>(), View.OnCl
val clientSignKey = HttpServerUtils.clientSignKey val clientSignKey = HttpServerUtils.clientSignKey
if (!TextUtils.isEmpty(clientSignKey)) { if (!TextUtils.isEmpty(clientSignKey)) {
msgMap["sign"] = msgMap["sign"] =
HttpServerUtils.calcSign(timestamp.toString(), clientSignKey.toString()) HttpServerUtils.calcSign(timestamp.toString(), clientSignKey)
} }
val mac = binding!!.etMac.text.toString() val mac = binding!!.etMac.text.toString()
@ -154,7 +154,7 @@ class WolSendFragment : BaseFragment<FragmentClientWolSendBinding?>(), View.OnCl
when (HttpServerUtils.clientSafetyMeasures) { when (HttpServerUtils.clientSafetyMeasures) {
2 -> { 2 -> {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString()) val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey)
try { try {
requestMsg = Base64.encode(requestMsg.toByteArray()) requestMsg = Base64.encode(requestMsg.toByteArray())
requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey) requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey)
@ -168,7 +168,7 @@ class WolSendFragment : BaseFragment<FragmentClientWolSendBinding?>(), View.OnCl
} }
3 -> { 3 -> {
try { try {
val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey.toString()) val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey)
//requestMsg = Base64.encode(requestMsg.toByteArray()) //requestMsg = Base64.encode(requestMsg.toByteArray())
val encryptCBC = SM4Crypt.encrypt(requestMsg.toByteArray(), sm4Key) val encryptCBC = SM4Crypt.encrypt(requestMsg.toByteArray(), sm4Key)
requestMsg = ConvertTools.bytes2HexString(encryptCBC) requestMsg = ConvertTools.bytes2HexString(encryptCBC)
@ -197,11 +197,11 @@ class WolSendFragment : BaseFragment<FragmentClientWolSendBinding?>(), View.OnCl
try { try {
var json = response var json = response
if (HttpServerUtils.clientSafetyMeasures == 2) { if (HttpServerUtils.clientSafetyMeasures == 2) {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString()) val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey)
json = RSACrypt.decryptByPublicKey(json, publicKey) json = RSACrypt.decryptByPublicKey(json, publicKey)
json = String(Base64.decode(json)) json = String(Base64.decode(json))
} else if (HttpServerUtils.clientSafetyMeasures == 3) { } else if (HttpServerUtils.clientSafetyMeasures == 3) {
val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey.toString()) val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey)
val encryptCBC = ConvertTools.hexStringToByteArray(json) val encryptCBC = ConvertTools.hexStringToByteArray(json)
val decryptCBC = SM4Crypt.decrypt(encryptCBC, sm4Key) val decryptCBC = SM4Crypt.decrypt(encryptCBC, sm4Key)
json = String(decryptCBC) json = String(decryptCBC)

@ -3,11 +3,8 @@ package com.idormy.sms.forwarder.receiver
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Build
import android.util.Log import android.util.Log
import com.idormy.sms.forwarder.activity.SplashActivity import com.idormy.sms.forwarder.activity.SplashActivity
import com.idormy.sms.forwarder.service.ForegroundService
import com.idormy.sms.forwarder.utils.SettingUtils
@Suppress("PropertyName") @Suppress("PropertyName")
class BootReceiver : BroadcastReceiver() { class BootReceiver : BroadcastReceiver() {
@ -17,32 +14,13 @@ class BootReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent?) { override fun onReceive(context: Context, intent: Intent?) {
val receiveAction: String? = intent?.action val receiveAction: String? = intent?.action
Log.d(TAG, "onReceive intent $receiveAction") Log.d(TAG, "onReceive intent $receiveAction")
if (receiveAction == "android.intent.action.BOOT_COMPLETED") { if (receiveAction == "android.intent.action.BOOT_COMPLETED" || receiveAction == "android.intent.action.LOCKED_BOOT_COMPLETED") {
try { try {
val i = Intent(context, SplashActivity::class.java) Log.d(TAG, "强制重启APP一次")
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) val intent1 = Intent(context, SplashActivity::class.java)
context.startActivity(i) intent1.flags = Intent.FLAG_ACTIVITY_NEW_TASK
context.startActivity(intent1)
//纯客户端模式 android.os.Process.killProcess(android.os.Process.myPid()) //杀掉以前进程
if (SettingUtils.enablePureClientMode) return
//前台服务
val frontServiceIntent = Intent(context, ForegroundService::class.java)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(frontServiceIntent)
} else {
context.startService(frontServiceIntent)
}
/*InitUtils.init(context)
//电池状态监听
val batteryServiceIntent = Intent(context, BatteryService::class.java)
context.startService(batteryServiceIntent)
//后台播放无声音乐
if (SettingUtils.getPlaySilenceMusic()) {
context.startService(Intent(context, MusicService::class.java))
}*/
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
} }

@ -16,10 +16,7 @@ import com.google.gson.Gson
import com.idormy.sms.forwarder.R import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.entity.CallInfo import com.idormy.sms.forwarder.entity.CallInfo
import com.idormy.sms.forwarder.entity.MsgInfo import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.utils.MMKVUtils import com.idormy.sms.forwarder.utils.*
import com.idormy.sms.forwarder.utils.PhoneUtils
import com.idormy.sms.forwarder.utils.SettingUtils
import com.idormy.sms.forwarder.utils.Worker
import com.idormy.sms.forwarder.workers.SendWorker import com.idormy.sms.forwarder.workers.SendWorker
import com.xuexiang.xutil.resource.ResUtils.getString import com.xuexiang.xutil.resource.ResUtils.getString
import java.util.* import java.util.*
@ -40,8 +37,7 @@ class PhoneStateReceiver : BroadcastReceiver() {
//权限判断 //权限判断
if (ActivityCompat.checkSelfPermission( if (ActivityCompat.checkSelfPermission(
context, context, Manifest.permission.READ_PHONE_STATE
Manifest.permission.READ_PHONE_STATE
) != PackageManager.PERMISSION_GRANTED ) != PackageManager.PERMISSION_GRANTED
) return ) return
@ -66,25 +62,25 @@ class PhoneStateReceiver : BroadcastReceiver() {
//Incoming call- goes from IDLE to RINGING when it rings, to OFFHOOK when it's answered, to IDLE when its hung up //Incoming call- goes from IDLE to RINGING when it rings, to OFFHOOK when it's answered, to IDLE when its hung up
//Outgoing call- goes from IDLE to OFFHOOK when it dials out, to IDLE when hung up //Outgoing call- goes from IDLE to OFFHOOK when it dials out, to IDLE when hung up
private fun onCallStateChanged(context: Context, state: Int, number: String?) { private fun onCallStateChanged(context: Context, state: Int, number: String?) {
val lastState = MMKVUtils.getInt("CALL_LAST_STATE", TelephonyManager.CALL_STATE_IDLE) var lastState: Int by SharedPreference("CALL_LAST_STATE", TelephonyManager.CALL_STATE_IDLE)
if (lastState == state || (state == TelephonyManager.CALL_STATE_RINGING && number == null)) { if (lastState == state || (state == TelephonyManager.CALL_STATE_RINGING && number == null)) {
//No change, debounce extras //No change, debounce extras
return return
} }
MMKVUtils.put("CALL_LAST_STATE", state) lastState = state
var callIsIncoming: Boolean by SharedPreference("CALL_IS_INCOMING", false)
var callSavedNumber: String by SharedPreference("CALL_SAVED_NUMBER", "")
when (state) { when (state) {
TelephonyManager.CALL_STATE_RINGING -> { TelephonyManager.CALL_STATE_RINGING -> {
Log.d(TAG, "来电响铃") Log.d(TAG, "来电响铃")
MMKVUtils.put("CALL_IS_INCOMING", true) callIsIncoming = true
//MMKVUtils.put("CALL_START_TIME", Date()) callSavedNumber = number.toString()
MMKVUtils.put("CALL_SAVED_NUMBER", number)
//来电提醒 //来电提醒
if (!TextUtils.isEmpty(number) && SettingUtils.enableCallType4) { if (!TextUtils.isEmpty(number) && SettingUtils.enableCallType4) {
val contacts = PhoneUtils.getContactByNumber(number) val contacts = PhoneUtils.getContactByNumber(number)
val contactName = val contactName = if (contacts.isNotEmpty()) contacts[0].name else getString(R.string.unknown_number)
if (contacts.isNotEmpty()) contacts[0].name else getString(R.string.unknown_number)
val sb = StringBuilder() val sb = StringBuilder()
sb.append(getString(R.string.linkman)).append(contactName).append("\n") sb.append(getString(R.string.linkman)).append(contactName).append("\n")
@ -92,28 +88,24 @@ class PhoneStateReceiver : BroadcastReceiver() {
sb.append(getString(R.string.incoming_call)) sb.append(getString(R.string.incoming_call))
val msgInfo = MsgInfo("call", number.toString(), sb.toString(), Date(), "", -1) val msgInfo = MsgInfo("call", number.toString(), sb.toString(), Date(), "", -1)
val request = OneTimeWorkRequestBuilder<SendWorker>() val request = OneTimeWorkRequestBuilder<SendWorker>().setInputData(
.setInputData(
workDataOf( workDataOf(
Worker.sendMsgInfo to Gson().toJson(msgInfo) Worker.sendMsgInfo to Gson().toJson(msgInfo)
) )
) ).build()
.build()
WorkManager.getInstance(context).enqueue(request) WorkManager.getInstance(context).enqueue(request)
} }
} }
TelephonyManager.CALL_STATE_OFFHOOK -> TelephonyManager.CALL_STATE_OFFHOOK ->
//Transition of ringing->offhook are pickups of incoming calls. Nothing done on them //Transition of ringing->offhook are pickups of incoming calls. Nothing done on them
when { callIsIncoming = when {
lastState != TelephonyManager.CALL_STATE_RINGING -> { lastState != TelephonyManager.CALL_STATE_RINGING -> {
Log.d(TAG, "去电接通") Log.d(TAG, "去电接通")
MMKVUtils.put("CALL_IS_INCOMING", false) false
//MMKVUtils.put("CALL_START_TIME", Date())
} }
else -> { else -> {
Log.d(TAG, "来电接通") Log.d(TAG, "来电接通")
MMKVUtils.put("CALL_IS_INCOMING", true) true
//MMKVUtils.put("CALL_START_TIME", Date())
} }
} }
TelephonyManager.CALL_STATE_IDLE -> TelephonyManager.CALL_STATE_IDLE ->
@ -121,27 +113,15 @@ class PhoneStateReceiver : BroadcastReceiver() {
when { when {
lastState == TelephonyManager.CALL_STATE_RINGING -> { lastState == TelephonyManager.CALL_STATE_RINGING -> {
Log.d(TAG, "来电未接") Log.d(TAG, "来电未接")
sendReceiveCallMsg( sendReceiveCallMsg(context, 3, callSavedNumber)
context,
3,
MMKVUtils.getString("CALL_SAVED_NUMBER", null)
)
} }
MMKVUtils.getBoolean("CALL_IS_INCOMING", false) -> { callIsIncoming -> {
Log.d(TAG, "来电挂机") Log.d(TAG, "来电挂机")
sendReceiveCallMsg( sendReceiveCallMsg(context, 1, callSavedNumber)
context,
1,
MMKVUtils.getString("CALL_SAVED_NUMBER", null)
)
} }
else -> { else -> {
Log.d(TAG, "去电挂机") Log.d(TAG, "去电挂机")
sendReceiveCallMsg( sendReceiveCallMsg(context, 2, callSavedNumber)
context,
2,
MMKVUtils.getString("CALL_SAVED_NUMBER", null)
)
} }
} }
} }
@ -157,10 +137,7 @@ class PhoneStateReceiver : BroadcastReceiver() {
if (callInfo?.number == null) return if (callInfo?.number == null) return
//判断是否开启该类型转发 //判断是否开启该类型转发
if ((callInfo.type == 1 && !SettingUtils.enableCallType1) if ((callInfo.type == 1 && !SettingUtils.enableCallType1) || (callInfo.type == 2 && !SettingUtils.enableCallType2) || (callInfo.type == 3 && !SettingUtils.enableCallType3)) {
|| (callInfo.type == 2 && !SettingUtils.enableCallType2)
|| (callInfo.type == 3 && !SettingUtils.enableCallType3)
) {
Log.w(TAG, "未开启该类型转发type=" + callInfo.type) Log.w(TAG, "未开启该类型转发type=" + callInfo.type)
return return
} }
@ -177,25 +154,17 @@ class PhoneStateReceiver : BroadcastReceiver() {
//获取联系人姓名 //获取联系人姓名
if (TextUtils.isEmpty(callInfo.name)) { if (TextUtils.isEmpty(callInfo.name)) {
val contacts = PhoneUtils.getContactByNumber(phoneNumber) val contacts = PhoneUtils.getContactByNumber(phoneNumber)
callInfo.name = callInfo.name = if (contacts.isNotEmpty()) contacts[0].name else getString(R.string.unknown_number)
if (contacts.isNotEmpty()) contacts[0].name else getString(R.string.unknown_number)
} }
val msgInfo = MsgInfo( val msgInfo = MsgInfo(
"call", "call", callInfo.number, PhoneUtils.getCallMsg(callInfo), Date(), simInfo, simSlot
callInfo.number,
PhoneUtils.getCallMsg(callInfo),
Date(),
simInfo,
simSlot
) )
val request = OneTimeWorkRequestBuilder<SendWorker>() val request = OneTimeWorkRequestBuilder<SendWorker>().setInputData(
.setInputData(
workDataOf( workDataOf(
Worker.sendMsgInfo to Gson().toJson(msgInfo) Worker.sendMsgInfo to Gson().toJson(msgInfo)
) )
) ).build()
.build()
WorkManager.getInstance(context).enqueue(request) WorkManager.getInstance(context).enqueue(request)
} }

@ -16,7 +16,7 @@ class AppConfig : WebConfig {
val serverWebPath = HttpServerUtils.serverWebPath val serverWebPath = HttpServerUtils.serverWebPath
if (!TextUtils.isEmpty(serverWebPath)) { if (!TextUtils.isEmpty(serverWebPath)) {
// 增加一个位于/sdcard/Download/目录下的网站 // 增加一个位于/sdcard/Download/目录下的网站
delegate.addWebsite(StorageWebsite(serverWebPath.toString())) delegate.addWebsite(StorageWebsite(serverWebPath))
} else { } else {
// 增加一个位于assets的web目录的网站 // 增加一个位于assets的web目录的网站
delegate.addWebsite(AssetsWebsite(context, "/web/")) delegate.addWebsite(AssetsWebsite(context, "/web/"))

@ -36,13 +36,13 @@ class AppExceptionResolver : ExceptionResolver {
Log.d(TAG, "resp: $resp") Log.d(TAG, "resp: $resp")
when (HttpServerUtils.safetyMeasures) { when (HttpServerUtils.safetyMeasures) {
2 -> { 2 -> {
val privateKey = RSACrypt.getPrivateKey(HttpServerUtils.serverPrivateKey.toString()) val privateKey = RSACrypt.getPrivateKey(HttpServerUtils.serverPrivateKey)
resp = Base64.encode(resp.toByteArray()) resp = Base64.encode(resp.toByteArray())
resp = RSACrypt.encryptByPrivateKey(resp, privateKey) resp = RSACrypt.encryptByPrivateKey(resp, privateKey)
response.setBody(StringBody(resp)) response.setBody(StringBody(resp))
} }
3 -> { 3 -> {
val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.serverSm4Key.toString()) val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.serverSm4Key)
//response = Base64.encode(response.toByteArray()) //response = Base64.encode(response.toByteArray())
val encryptCBC = SM4Crypt.encrypt(resp.toByteArray(), sm4Key) val encryptCBC = SM4Crypt.encrypt(resp.toByteArray(), sm4Key)
response.setBody(StringBody(ConvertTools.bytes2HexString(encryptCBC))) response.setBody(StringBody(ConvertTools.bytes2HexString(encryptCBC)))

@ -36,13 +36,13 @@ class AppMessageConverter : MessageConverter {
return when (HttpServerUtils.safetyMeasures) { return when (HttpServerUtils.safetyMeasures) {
2 -> { 2 -> {
val privateKey = RSACrypt.getPrivateKey(HttpServerUtils.serverPrivateKey.toString()) val privateKey = RSACrypt.getPrivateKey(HttpServerUtils.serverPrivateKey)
response = Base64.encode(response.toByteArray()) response = Base64.encode(response.toByteArray())
response = RSACrypt.encryptByPrivateKey(response, privateKey) response = RSACrypt.encryptByPrivateKey(response, privateKey)
StringBody(response) StringBody(response)
} }
3 -> { 3 -> {
val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.serverSm4Key.toString()) val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.serverSm4Key)
//response = Base64.encode(response.toByteArray()) //response = Base64.encode(response.toByteArray())
val encryptCBC = SM4Crypt.encrypt(response.toByteArray(), sm4Key) val encryptCBC = SM4Crypt.encrypt(response.toByteArray(), sm4Key)
StringBody(ConvertTools.bytes2HexString(encryptCBC)) StringBody(ConvertTools.bytes2HexString(encryptCBC))
@ -65,7 +65,7 @@ class AppMessageConverter : MessageConverter {
throw HttpException(500, "服务端未配置私钥") throw HttpException(500, "服务端未配置私钥")
} }
val privateKey = RSACrypt.getPrivateKey(HttpServerUtils.serverPrivateKey.toString()) val privateKey = RSACrypt.getPrivateKey(HttpServerUtils.serverPrivateKey)
json = RSACrypt.decryptByPrivateKey(json, privateKey) json = RSACrypt.decryptByPrivateKey(json, privateKey)
json = String(Base64.decode(json)) json = String(Base64.decode(json))
Log.d(TAG, "Json: $json") Log.d(TAG, "Json: $json")
@ -75,7 +75,7 @@ class AppMessageConverter : MessageConverter {
throw HttpException(500, "服务端未配置SM4密钥") throw HttpException(500, "服务端未配置SM4密钥")
} }
val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.serverSm4Key.toString()) val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.serverSm4Key)
val encryptCBC = ConvertTools.hexStringToByteArray(json) val encryptCBC = ConvertTools.hexStringToByteArray(json)
val decryptCBC = SM4Crypt.decrypt(encryptCBC, sm4Key) val decryptCBC = SM4Crypt.decrypt(encryptCBC, sm4Key)
//json = String(Base64.decode(decryptCBC.toString())) //json = String(Base64.decode(decryptCBC.toString()))

@ -37,9 +37,9 @@ class ConfigController {
HttpServerUtils.enableApiContactQuery, HttpServerUtils.enableApiContactQuery,
HttpServerUtils.enableApiBatteryQuery, HttpServerUtils.enableApiBatteryQuery,
HttpServerUtils.enableApiWol, HttpServerUtils.enableApiWol,
SettingUtils.extraDeviceMark.toString(), SettingUtils.extraDeviceMark,
SettingUtils.extraSim1.toString(), SettingUtils.extraSim1,
SettingUtils.extraSim2.toString(), SettingUtils.extraSim2,
App.SimInfoList, App.SimInfoList,
AppUtils.getAppVersionCode(), AppUtils.getAppVersionCode(),
AppUtils.getAppVersionName(), AppUtils.getAppVersionName(),

@ -2,31 +2,14 @@ package com.idormy.sms.forwarder.utils
object CactusSave { object CactusSave {
//Cactus存活时间 //Cactus存活时间
var timer: Long var timer: Long by SharedPreference(CACTUS_TIMER, 0L)
get() = MMKVUtils.getLong(CACTUS_TIMER, 0L)
set(timer) {
MMKVUtils.put(CACTUS_TIMER, timer)
}
//Cactus上次存活时间 //Cactus上次存活时间
var lastTimer: Long var lastTimer: Long by SharedPreference(CACTUS_LAST_TIMER, 0L)
get() = MMKVUtils.getLong(CACTUS_LAST_TIMER, 0L)
set(timer) {
MMKVUtils.put(CACTUS_LAST_TIMER, timer)
}
//Cactus运行时间 //Cactus运行时间
var date: String? var date: String by SharedPreference(SP_EXTRA_DEVICE_MARK, "0000-01-01 00:00:00")
get() = MMKVUtils.getString(SP_EXTRA_DEVICE_MARK, "0000-01-01 00:00:00")
set(extraDeviceMark) {
MMKVUtils.put(SP_EXTRA_DEVICE_MARK, extraDeviceMark)
}
//Cactus结束时间 //Cactus结束时间
var endDate: String? var endDate: String by SharedPreference(CACTUS_DATE, "0000-01-01 00:00:00")
get() = MMKVUtils.getString(CACTUS_DATE, "0000-01-01 00:00:00")
set(extraDeviceMark) {
MMKVUtils.put(CACTUS_END_DATE, extraDeviceMark)
}
} }

@ -1,8 +1,11 @@
package com.idormy.sms.forwarder.utils package com.idormy.sms.forwarder.utils
import android.content.Context import android.content.Context
import android.os.Parcelable import android.content.SharedPreferences
import com.tencent.mmkv.MMKV import android.os.Build
import java.io.*
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
/** /**
* 转发历史工具类 * 转发历史工具类
@ -11,264 +14,102 @@ import com.tencent.mmkv.MMKV
* @since 2022年5月9日 * @since 2022年5月9日
*/ */
@Suppress("PropertyName", "UNCHECKED_CAST", "MemberVisibilityCanBePrivate", "unused") @Suppress("PropertyName", "UNCHECKED_CAST", "MemberVisibilityCanBePrivate", "unused")
class HistoryUtils private constructor() { class HistoryUtils<T>(private val name: String, private val default: T) : ReadWriteProperty<Any?, T> {
companion object { companion object {
private var sMMKV: MMKV? = null lateinit var preference: SharedPreferences
/**
* 初始化
*
* @param context
*/
fun init(context: Context) { fun init(context: Context) {
MMKV.initialize(context.applicationContext) preference = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
sMMKV = MMKV.mmkvWithID("History") val directBootContext: Context = context.createDeviceProtectedStorageContext()
} directBootContext.getSharedPreferences(context.packageName + ".history", Context.MODE_PRIVATE)
} else {
fun getsMMKV(): MMKV? { context.getSharedPreferences(context.packageName + ".history", Context.MODE_PRIVATE)
if (sMMKV == null) {
sMMKV = MMKV.mmkvWithID("History")
}
return sMMKV
}
//=======================================键值保存==================================================//
/**
* 保存键值
*
* @param key
* @param value
* @return
*/
fun put(key: String?, value: Any?): Boolean {
when (value) {
is Int -> {
return getsMMKV()!!.encode(key, (value as Int?)!!)
}
is Float -> {
return getsMMKV()!!.encode(key, (value as Float?)!!)
}
is String -> {
return getsMMKV()!!.encode(key, value as String?)
}
is Boolean -> {
return getsMMKV()!!.encode(key, (value as Boolean?)!!)
}
is Long -> {
return getsMMKV()!!.encode(key, (value as Long?)!!)
}
is Double -> {
return getsMMKV()!!.encode(key, (value as Double?)!!)
}
is Parcelable -> {
return getsMMKV()!!.encode(key, value as Parcelable?)
}
is ByteArray -> {
return getsMMKV()!!.encode(key, value as ByteArray?)
}
is Set<*> -> {
return getsMMKV()!!.encode(key, value as Set<String?>?)
}
else -> return false
}
}
//=======================================键值获取==================================================//
/**
* 获取键值
*
* @param key
* @param defaultValue
* @return
*/
operator fun get(key: String?, defaultValue: Any?): Any? {
when (defaultValue) {
is Int -> {
return getsMMKV()!!
.decodeInt(key, (defaultValue as Int?)!!)
}
is Float -> {
return getsMMKV()!!
.decodeFloat(key, (defaultValue as Float?)!!)
}
is String -> {
return getsMMKV()!!.decodeString(key, defaultValue as String?)
}
is Boolean -> {
return getsMMKV()!!
.decodeBool(key, (defaultValue as Boolean?)!!)
}
is Long -> {
return getsMMKV()!!
.decodeLong(key, (defaultValue as Long?)!!)
}
is Double -> {
return getsMMKV()!!
.decodeDouble(key, (defaultValue as Double?)!!)
}
is ByteArray -> {
return getsMMKV()!!.decodeBytes(key)
}
is Set<*> -> {
return getsMMKV()!!.decodeStringSet(key, defaultValue as Set<String?>?)
}
else -> return null
} }
} }
/** //删除全部数据
* 根据key获取boolean值 fun clearPreference() = preference.edit().clear().apply()
*
* @param key
* @param defValue
* @return
*/
fun getBoolean(key: String?, defValue: Boolean): Boolean {
try {
return getsMMKV()!!.getBoolean(key, defValue)
} catch (e: Exception) {
e.printStackTrace()
}
return defValue
}
/** //根据key删除存储数据
* 根据key获取long值 fun clearPreference(key: String) = preference.edit().remove(key).commit()
*
* @param key
* @param defValue
* @return
*/
fun getLong(key: String?, defValue: Long): Long {
try {
return getsMMKV()!!.getLong(key, defValue)
} catch (e: Exception) {
e.printStackTrace()
}
return defValue
} }
/** override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
* 根据key获取float值 return putPreference(name, value)
*
* @param key
* @param defValue
* @return
*/
fun getFloat(key: String?, defValue: Float): Float {
try {
return getsMMKV()!!.getFloat(key, defValue)
} catch (e: Exception) {
e.printStackTrace()
}
return defValue
} }
/** override fun getValue(thisRef: Any?, property: KProperty<*>): T {
* 根据key获取String值 return getPreference(name, default)
*
* @param key
* @param defValue
* @return
*/
fun getString(key: String?, defValue: String?): String? {
try {
return getsMMKV()!!.getString(key, defValue)
} catch (e: Exception) {
e.printStackTrace()
}
return defValue
} }
/** /**
* 根据key获取int值 * 查找数据 返回给调用方法一个具体的对象
* * 如果查找不到类型就采用反序列化方法来返回类型
* @param key * default是默认对象 以防止会返回空对象的异常
* @param defValue * 即如果name没有查找到value 就返回默认的序列化对象然后经过反序列化返回
* @return
*/
fun getInt(key: String?, defValue: Int): Int {
try {
return getsMMKV()!!.getInt(key, defValue)
} catch (e: Exception) {
e.printStackTrace()
}
return defValue
}
/**
* 根据key获取double值
*
* @param key
* @param defValue
* @return
*/ */
fun getDouble(key: String?, defValue: Double): Double { private fun getPreference(name: String, default: T): T = with(preference) {
try { val res: Any = when (default) {
return getsMMKV()!!.decodeDouble(key, defValue) is Long -> getLong(name, default)
} catch (e: Exception) { is String -> this.getString(name, default)!!
e.printStackTrace() is Int -> getInt(name, default)
is Boolean -> getBoolean(name, default)
is Float -> getFloat(name, default)
//else -> throw IllegalArgumentException("This type can be get from Preferences")
else -> deSerialization(getString(name, serialize(default)).toString())
} }
return defValue return res as T
} }
/** private fun putPreference(name: String, value: T) = with(preference.edit()) {
* 获取对象 when (value) {
* is Long -> putLong(name, value)
* @param key is Int -> putInt(name, value)
* @param tClass 类型 is String -> putString(name, value)
* @param <T> is Boolean -> putBoolean(name, value)
* @return is Float -> putFloat(name, value)
</T> */ //else -> throw IllegalArgumentException("This type can be saved into Preferences")
fun <T : Parcelable?> getObject(key: String?, tClass: Class<T>?): T? { else -> putString(name, serialize(value))
return getsMMKV()!!.decodeParcelable(key, tClass) }.apply()
}
/**
* 获取对象
*
* @param key
* @param tClass 类型
* @param <T>
* @return
</T> */
fun <T : Parcelable?> getObject(key: String?, tClass: Class<T>?, defValue: T): T? {
try {
return getsMMKV()!!.decodeParcelable(key, tClass, defValue)
} catch (e: Exception) {
e.printStackTrace()
}
return defValue
}
/**
* 判断键值对是否存在
*
* @param key
* @return 键值对是否存在
*/
fun containsKey(key: String?): Boolean {
return getsMMKV()!!.containsKey(key)
} }
/** /**
* 清除指定键值对 * 序列化对象
* * @throws IOException
* @param key
*/ */
fun remove(key: String?) { @Throws(IOException::class)
getsMMKV()!!.remove(key).apply() private fun <T> serialize(obj: T): String {
val byteArrayOutputStream = ByteArrayOutputStream()
val objectOutputStream = ObjectOutputStream(
byteArrayOutputStream
)
objectOutputStream.writeObject(obj)
var serStr = byteArrayOutputStream.toString("ISO-8859-1")
serStr = java.net.URLEncoder.encode(serStr, "UTF-8")
objectOutputStream.close()
byteArrayOutputStream.close()
return serStr
} }
/** /**
* 清除所有键值对 * 反序列化对象
* @param str
* @throws IOException
* @throws ClassNotFoundException
*/ */
fun clear() { @Throws(IOException::class, ClassNotFoundException::class)
getsMMKV()!!.clearAll() private fun <T> deSerialization(str: String): T {
} val redStr = java.net.URLDecoder.decode(str, "UTF-8")
val byteArrayInputStream = ByteArrayInputStream(
} redStr.toByteArray(charset("ISO-8859-1"))
)
init { val objectInputStream = ObjectInputStream(
throw UnsupportedOperationException("u can't instantiate me...") byteArrayInputStream
)
val obj = objectInputStream.readObject() as T
objectInputStream.close()
byteArrayInputStream.close()
return obj
} }
} }

@ -25,172 +25,67 @@ class HttpServerUtils private constructor() {
companion object { companion object {
//是否启用HttpServer开机自启 //是否启用HttpServer开机自启
@JvmStatic var enableServerAutorun: Boolean by SharedPreference(SP_ENABLE_SERVER_AUTORUN, true)
var enableServerAutorun: Boolean
get() = MMKVUtils.getBoolean(SP_ENABLE_SERVER_AUTORUN, false) //服务端签名密钥
set(enableServerAutorun) { var serverSignKey: String by SharedPreference(SP_SERVER_SIGN_KEY, "")
MMKVUtils.put(SP_ENABLE_SERVER_AUTORUN, enableServerAutorun)
}
//服务端安全设置 //服务端安全设置
@JvmStatic var safetyMeasures: Int by SharedPreference(SP_SERVER_SAFETY_MEASURES, if (TextUtils.isEmpty(serverSignKey)) 0 else 1)
var safetyMeasures: Int
get() = MMKVUtils.getInt(SP_SERVER_SAFETY_MEASURES, if (TextUtils.isEmpty(serverSignKey)) 0 else 1)
set(safetyMeasures) {
MMKVUtils.put(SP_SERVER_SAFETY_MEASURES, safetyMeasures)
}
//服务端SM4密钥 //服务端SM4密钥
@JvmStatic var serverSm4Key: String by SharedPreference(SP_SERVER_SM4_KEY, "")
var serverSm4Key: String?
get() = MMKVUtils.getString(SP_SERVER_SM4_KEY, "")
set(serverSm4Key) {
MMKVUtils.put(SP_SERVER_SM4_KEY, serverSm4Key)
}
//服务端RSA公钥 //服务端RSA公钥
@JvmStatic var serverPublicKey: String by SharedPreference(SP_SERVER_PUBLIC_KEY, "")
var serverPublicKey: String?
get() = MMKVUtils.getString(SP_SERVER_PUBLIC_KEY, "")
set(serverPublicKey) {
MMKVUtils.put(SP_SERVER_PUBLIC_KEY, serverPublicKey)
}
//服务端RSA私钥 //服务端RSA私钥
@JvmStatic var serverPrivateKey: String by SharedPreference(SP_SERVER_PRIVATE_KEY, "")
var serverPrivateKey: String?
get() = MMKVUtils.getString(SP_SERVER_PRIVATE_KEY, "")
set(serverPrivateKey) {
MMKVUtils.put(SP_SERVER_PRIVATE_KEY, serverPrivateKey)
}
//服务端签名密钥
@JvmStatic
var serverSignKey: String?
get() = MMKVUtils.getString(SP_SERVER_SIGN_KEY, "")
set(serverSignKey) {
MMKVUtils.put(SP_SERVER_SIGN_KEY, serverSignKey)
}
//时间容差 //时间容差
@JvmStatic var timeTolerance: Int by SharedPreference(SP_SERVER_TIME_TOLERANCE, 600)
var timeTolerance: Int
get() = MMKVUtils.getInt(SP_SERVER_TIME_TOLERANCE, 600)
set(timeTolerance) {
MMKVUtils.put(SP_SERVER_TIME_TOLERANCE, timeTolerance)
}
//自定义web客户端目录 //自定义web客户端目录
@JvmStatic var serverWebPath: String by SharedPreference(SP_SERVER_WEB_PATH, "")
var serverWebPath: String?
get() = MMKVUtils.getString(SP_SERVER_WEB_PATH, "")
set(serverWebPath) {
MMKVUtils.put(SP_SERVER_WEB_PATH, serverWebPath)
}
//服务地址 //服务地址
@JvmStatic var serverAddress: String by SharedPreference(SP_SERVER_ADDRESS, "")
var serverAddress: String?
get() = MMKVUtils.getString(SP_SERVER_ADDRESS, "")
set(clientSignKey) {
MMKVUtils.put(SP_SERVER_ADDRESS, clientSignKey)
}
//服务地址历史记录 //服务地址历史记录
@JvmStatic var serverHistory: String by SharedPreference(SP_SERVER_HISTORY, "")
var serverHistory: String?
get() = MMKVUtils.getString(SP_SERVER_HISTORY, "")
set(serverHistory) {
MMKVUtils.put(SP_SERVER_HISTORY, serverHistory)
}
//服务端配置 //服务端配置
@JvmStatic var serverConfig: String by SharedPreference(SP_SERVER_CONFIG, "")
var serverConfig: String?
get() = MMKVUtils.getString(SP_SERVER_CONFIG, "")
set(serverConfig) {
MMKVUtils.put(SP_SERVER_CONFIG, serverConfig)
}
//服务端安全设置
@JvmStatic
var clientSafetyMeasures: Int
get() = MMKVUtils.getInt(SP_CLIENT_SAFETY_MEASURES, if (TextUtils.isEmpty(clientSignKey)) 0 else 1)
set(clientSafetyMeasures) {
MMKVUtils.put(SP_CLIENT_SAFETY_MEASURES, clientSafetyMeasures)
}
//客户端签名密钥/RSA公钥 //客户端签名密钥/RSA公钥
@JvmStatic var clientSignKey: String by SharedPreference(SP_CLIENT_SIGN_KEY, "")
var clientSignKey: String?
get() = MMKVUtils.getString(SP_CLIENT_SIGN_KEY, "") //服务端安全设置
set(clientSignKey) { var clientSafetyMeasures: Int by SharedPreference(SP_CLIENT_SAFETY_MEASURES, if (TextUtils.isEmpty(clientSignKey)) 0 else 1)
MMKVUtils.put(SP_CLIENT_SIGN_KEY, clientSignKey)
}
//是否启用一键克隆 //是否启用一键克隆
@JvmStatic var enableApiClone: Boolean by SharedPreference(SP_ENABLE_API_CLONE, true)
var enableApiClone: Boolean
get() = MMKVUtils.getBoolean(SP_ENABLE_API_CLONE, false)
set(enableApiClone) {
MMKVUtils.put(SP_ENABLE_API_CLONE, enableApiClone)
}
//是否启用远程发短信 //是否启用远程发短信
@JvmStatic var enableApiSmsSend: Boolean by SharedPreference(SP_ENABLE_API_SMS_SEND, true)
var enableApiSmsSend: Boolean
get() = MMKVUtils.getBoolean(SP_ENABLE_API_SMS_SEND, false)
set(enableApiSendSms) {
MMKVUtils.put(SP_ENABLE_API_SMS_SEND, enableApiSendSms)
}
//是否启用远程查短信 //是否启用远程查短信
@JvmStatic var enableApiSmsQuery: Boolean by SharedPreference(SP_ENABLE_API_SMS_QUERY, true)
var enableApiSmsQuery: Boolean
get() = MMKVUtils.getBoolean(SP_ENABLE_API_SMS_QUERY, false)
set(enableApiQuerySms) {
MMKVUtils.put(SP_ENABLE_API_SMS_QUERY, enableApiQuerySms)
}
//是否启用远程查通话 //是否启用远程查通话
@JvmStatic var enableApiCallQuery: Boolean by SharedPreference(SP_ENABLE_API_CALL_QUERY, true)
var enableApiCallQuery: Boolean
get() = MMKVUtils.getBoolean(SP_ENABLE_API_CALL_QUERY, false)
set(enableApiQueryCall) {
MMKVUtils.put(SP_ENABLE_API_CALL_QUERY, enableApiQueryCall)
}
//是否启用远程查话簿 //是否启用远程查话簿
@JvmStatic var enableApiContactQuery: Boolean by SharedPreference(SP_ENABLE_API_CONTACT_QUERY, true)
var enableApiContactQuery: Boolean
get() = MMKVUtils.getBoolean(SP_ENABLE_API_CONTACT_QUERY, false)
set(enableApiQueryLinkman) {
MMKVUtils.put(SP_ENABLE_API_CONTACT_QUERY, enableApiQueryLinkman)
}
//是否启用远程查电量 //是否启用远程查电量
@JvmStatic var enableApiBatteryQuery: Boolean by SharedPreference(SP_ENABLE_API_BATTERY_QUERY, true)
var enableApiBatteryQuery: Boolean
get() = MMKVUtils.getBoolean(SP_ENABLE_API_BATTERY_QUERY, false)
set(enableApiQueryBattery) {
MMKVUtils.put(SP_ENABLE_API_BATTERY_QUERY, enableApiQueryBattery)
}
//是否启用远程WOL //是否启用远程WOL
@JvmStatic var enableApiWol: Boolean by SharedPreference(SP_ENABLE_API_WOL, true)
var enableApiWol: Boolean
get() = MMKVUtils.getBoolean(SP_ENABLE_API_WOL, false)
set(enableApiWol) {
MMKVUtils.put(SP_ENABLE_API_WOL, enableApiWol)
}
//WOL历史记录 //WOL历史记录
@JvmStatic var wolHistory: String by SharedPreference(SP_WOL_HISTORY, "")
var wolHistory: String?
get() = MMKVUtils.getString(SP_WOL_HISTORY, "")
set(wolHistory) {
MMKVUtils.put(SP_WOL_HISTORY, wolHistory)
}
//计算签名 //计算签名
fun calcSign(timestamp: String, signSecret: String): String { fun calcSign(timestamp: String, signSecret: String): String {
@ -217,7 +112,7 @@ class HttpServerUtils private constructor() {
throw HttpException(500, String.format(getString(R.string.timestamp_verify_failed), timestamp, timeTolerance, diffTime)) throw HttpException(500, String.format(getString(R.string.timestamp_verify_failed), timestamp, timeTolerance, diffTime))
} }
val sign = calcSign(req.timestamp.toString(), signSecret.toString()) val sign = calcSign(req.timestamp.toString(), signSecret)
if (sign != req.sign) { if (sign != req.sign) {
Log.e("calcSign", sign) Log.e("calcSign", sign)
Log.e("reqSign", req.sign.toString()) Log.e("reqSign", req.sign.toString())
@ -298,7 +193,7 @@ class HttpServerUtils private constructor() {
SettingUtils.batteryLevelMax = cloneInfo.batteryLevelMax SettingUtils.batteryLevelMax = cloneInfo.batteryLevelMax
SettingUtils.batteryLevelOnce = cloneInfo.batteryLevelOnce SettingUtils.batteryLevelOnce = cloneInfo.batteryLevelOnce
SettingUtils.enableBatteryCron = cloneInfo.enableBatteryCron SettingUtils.enableBatteryCron = cloneInfo.enableBatteryCron
SettingUtils.batteryCronStartTime = cloneInfo.batteryCronStartTime SettingUtils.batteryCronStartTime = cloneInfo.batteryCronStartTime.toString()
SettingUtils.batteryCronInterval = cloneInfo.batteryCronInterval SettingUtils.batteryCronInterval = cloneInfo.batteryCronInterval
SettingUtils.enableExcludeFromRecents = cloneInfo.enableExcludeFromRecents SettingUtils.enableExcludeFromRecents = cloneInfo.enableExcludeFromRecents
SettingUtils.enableCactus = cloneInfo.enableCactus SettingUtils.enableCactus = cloneInfo.enableCactus
@ -307,9 +202,9 @@ class HttpServerUtils private constructor() {
SettingUtils.requestRetryTimes = cloneInfo.requestRetryTimes SettingUtils.requestRetryTimes = cloneInfo.requestRetryTimes
SettingUtils.requestDelayTime = cloneInfo.requestDelayTime SettingUtils.requestDelayTime = cloneInfo.requestDelayTime
SettingUtils.requestTimeout = cloneInfo.requestTimeout SettingUtils.requestTimeout = cloneInfo.requestTimeout
SettingUtils.notifyContent = cloneInfo.notifyContent SettingUtils.notifyContent = cloneInfo.notifyContent.toString()
SettingUtils.enableSmsTemplate = cloneInfo.enableSmsTemplate SettingUtils.enableSmsTemplate = cloneInfo.enableSmsTemplate
SettingUtils.smsTemplate = cloneInfo.smsTemplate SettingUtils.smsTemplate = cloneInfo.smsTemplate.toString()
SettingUtils.enableHelpTip = cloneInfo.enableHelpTip SettingUtils.enableHelpTip = cloneInfo.enableHelpTip
SettingUtils.enablePureClientMode = cloneInfo.enablePureClientMode SettingUtils.enablePureClientMode = cloneInfo.enablePureClientMode
//删除发送通道、转发规则、转发日志 //删除发送通道、转发规则、转发日志
@ -356,7 +251,7 @@ class HttpServerUtils private constructor() {
resp["data"] = output resp["data"] = output
} }
if (safetyMeasures == 1) { if (safetyMeasures == 1) {
resp["sign"] = calcSign(timestamp.toString(), serverSignKey.toString()) resp["sign"] = calcSign(timestamp.toString(), serverSignKey)
} }
} }

@ -1,332 +0,0 @@
package com.idormy.sms.forwarder.utils
import android.content.Context
import android.os.Parcelable
import android.util.Log
import androidx.preference.PreferenceManager
import com.tencent.mmkv.MMKV
/**
* MMKV工具类
*
* @author xuexiang
* @since 2019-07-04 10:20
*/
@Suppress("PropertyName", "UNCHECKED_CAST", "MemberVisibilityCanBePrivate", "unused")
class MMKVUtils private constructor() {
companion object {
private var TAG: String = "MMKVUtils"
private var sMMKV: MMKV? = null
/**
* 初始化
*
* @param context
*/
fun init(context: Context) {
MMKV.initialize(context.applicationContext)
sMMKV = MMKV.defaultMMKV()
}
fun getsMMKV(): MMKV? {
if (sMMKV == null) {
sMMKV = MMKV.defaultMMKV()
}
return sMMKV
}
//=======================================键值保存==================================================//
/**
* 保存键值
*
* @param key
* @param value
* @return
*/
fun put(key: String?, value: Any?): Boolean {
when (value) {
is Int -> {
return getsMMKV()!!.encode(key, (value as Int?)!!)
}
is Float -> {
return getsMMKV()!!.encode(key, (value as Float?)!!)
}
is String -> {
return getsMMKV()!!.encode(key, value as String?)
}
is Boolean -> {
return getsMMKV()!!.encode(key, (value as Boolean?)!!)
}
is Long -> {
return getsMMKV()!!.encode(key, (value as Long?)!!)
}
is Double -> {
return getsMMKV()!!.encode(key, (value as Double?)!!)
}
is Parcelable -> {
return getsMMKV()!!.encode(key, value as Parcelable?)
}
is ByteArray -> {
return getsMMKV()!!.encode(key, value as ByteArray?)
}
is Set<*> -> {
return getsMMKV()!!.encode(key, value as Set<String?>?)
}
else -> return false
}
}
//=======================================键值获取==================================================//
/**
* 获取键值
*
* @param key
* @param defaultValue
* @return
*/
operator fun get(key: String?, defaultValue: Any?): Any? {
when (defaultValue) {
is Int -> {
return getsMMKV()!!
.decodeInt(key, (defaultValue as Int?)!!)
}
is Float -> {
return getsMMKV()!!
.decodeFloat(key, (defaultValue as Float?)!!)
}
is String -> {
return getsMMKV()!!.decodeString(key, defaultValue as String?)
}
is Boolean -> {
return getsMMKV()!!
.decodeBool(key, (defaultValue as Boolean?)!!)
}
is Long -> {
return getsMMKV()!!
.decodeLong(key, (defaultValue as Long?)!!)
}
is Double -> {
return getsMMKV()!!
.decodeDouble(key, (defaultValue as Double?)!!)
}
is ByteArray -> {
return getsMMKV()!!.decodeBytes(key)
}
is Set<*> -> {
return getsMMKV()!!.decodeStringSet(key, defaultValue as Set<String?>?)
}
else -> return null
}
}
/**
* 根据key获取boolean值
*
* @param key
* @param defValue
* @return
*/
fun getBoolean(key: String?, defValue: Boolean): Boolean {
try {
return getsMMKV()!!.getBoolean(key, defValue)
} catch (e: Exception) {
e.printStackTrace()
}
return defValue
}
/**
* 根据key获取long值
*
* @param key
* @param defValue
* @return
*/
fun getLong(key: String?, defValue: Long): Long {
try {
return getsMMKV()!!.getLong(key, defValue)
} catch (e: Exception) {
e.printStackTrace()
}
return defValue
}
/**
* 根据key获取float值
*
* @param key
* @param defValue
* @return
*/
fun getFloat(key: String?, defValue: Float): Float {
try {
return getsMMKV()!!.getFloat(key, defValue)
} catch (e: Exception) {
e.printStackTrace()
}
return defValue
}
/**
* 根据key获取String值
*
* @param key
* @param defValue
* @return
*/
fun getString(key: String?, defValue: String?): String? {
try {
return getsMMKV()!!.getString(key, defValue)
} catch (e: Exception) {
e.printStackTrace()
}
return defValue
}
/**
* 根据key获取int值
*
* @param key
* @param defValue
* @return
*/
fun getInt(key: String?, defValue: Int): Int {
try {
return getsMMKV()!!.getInt(key, defValue)
} catch (e: Exception) {
e.printStackTrace()
}
return defValue
}
/**
* 根据key获取double值
*
* @param key
* @param defValue
* @return
*/
fun getDouble(key: String?, defValue: Double): Double {
try {
return getsMMKV()!!.decodeDouble(key, defValue)
} catch (e: Exception) {
e.printStackTrace()
}
return defValue
}
/**
* 获取对象
*
* @param key
* @param tClass 类型
* @param <T>
* @return
</T> */
fun <T : Parcelable?> getObject(key: String?, tClass: Class<T>?): T? {
return getsMMKV()!!.decodeParcelable(key, tClass)
}
/**
* 获取对象
*
* @param key
* @param tClass 类型
* @param <T>
* @return
</T> */
fun <T : Parcelable?> getObject(key: String?, tClass: Class<T>?, defValue: T): T? {
try {
return getsMMKV()!!.decodeParcelable(key, tClass, defValue)
} catch (e: Exception) {
e.printStackTrace()
}
return defValue
}
/**
* 判断键值对是否存在
*
* @param key
* @return 键值对是否存在
*/
fun containsKey(key: String?): Boolean {
return getsMMKV()!!.containsKey(key)
}
/**
* 清除指定键值对
*
* @param key
*/
fun remove(key: String?) {
getsMMKV()!!.remove(key).apply()
}
/**
* 从SP迁移数据
*/
fun importSharedPreferences(context: Context) {
Log.d(TAG, "从SP迁移数据")
val preferences = PreferenceManager.getDefaultSharedPreferences(context)
val editor = preferences.edit()
getsMMKV()!!.importFromSharedPreferences(preferences)
editor.clear().apply()
Log.d(TAG, "转换旧的SP配置")
loop@ for (key: String in getsMMKV()!!.allKeys()!!) {
when {
key.startsWith("tsms_msg_key_switch_") || key.startsWith("tsms_msg_key_string_enable_") || key.endsWith("battery_level_once") -> {
val newKey = key.replace("tsms_msg_key_switch_", "enable_")
.replace("tsms_msg_key_string_", "enable_")
.replace("enable_enable_", "enable_")
val value = getBoolean(key, false)
Log.d(TAG, String.format("oldKey=%s, newKey=%s, value=%s", key, newKey, value.toString()))
put(newKey, value)
remove(key)
continue@loop
}
key.endsWith("battery_level_alarm") || key.endsWith("battery_level_max") || key.endsWith("battery_level_current") || key.endsWith("battery_status") || key.endsWith("battery_cron_interval") -> {
val newKey = key.replace("tsms_msg_key_switch_", "")
.replace("tsms_msg_key_string_", "")
.replace("alarm", "min")
.replace("tsms_msg_key_", "request_")
val value = getInt(key, 0)
Log.d(TAG, String.format("oldKey=%s, newKey=%s, value=%s", key, newKey, value.toString()))
put(newKey, value)
remove(key)
continue@loop
}
key.startsWith("tsms_msg_key_") -> {
val newKey = key.replace("tsms_msg_key_string_", "")
.replace("add_", "")
.replace("tsms_msg_key_", "request_")
val value = getString(key, "")
Log.d(TAG, String.format("oldKey=%s, newKey=%s, value=%s", key, newKey, value.toString()))
put(newKey, value)
remove(key)
continue@loop
}
}
}
Log.d(TAG, "转换后的数据")
for (key: String in getsMMKV()!!.allKeys()!!) {
when {
key.startsWith("enable_") -> {
Log.d(TAG, String.format("key=%s, value=%s", key, getBoolean(key, false).toString()))
}
key.startsWith("battery_") || key.startsWith("request_") -> {
Log.d(TAG, String.format("key=%s, value=%s", key, getInt(key, 0).toString()))
}
else -> {
Log.d(TAG, String.format("key=%s, value=%s", key, getString(key, "").toString()))
}
}
}
}
}
init {
throw UnsupportedOperationException("u can't instantiate me...")
}
}

@ -7,339 +7,131 @@ class SettingUtils private constructor() {
companion object { companion object {
//是否是第一次启动 //是否是第一次启动
var isFirstOpen: Boolean var isFirstOpen: Boolean by SharedPreference(IS_FIRST_OPEN_KEY, true)
get() = MMKVUtils.getBoolean(IS_FIRST_OPEN_KEY, true)
set(isFirstOpen) {
MMKVUtils.put(IS_FIRST_OPEN_KEY, isFirstOpen)
}
//是否同意隐私政策 //是否同意隐私政策
@JvmStatic var isAgreePrivacy: Boolean by SharedPreference(IS_AGREE_PRIVACY_KEY, false)
var isAgreePrivacy: Boolean
get() = MMKVUtils.getBoolean(IS_AGREE_PRIVACY_KEY, false)
set(isAgreePrivacy) {
MMKVUtils.put(IS_AGREE_PRIVACY_KEY, isAgreePrivacy)
}
//是否转发短信 //是否转发短信
@JvmStatic var enableSms: Boolean by SharedPreference(SP_ENABLE_SMS, false)
var enableSms: Boolean
get() = MMKVUtils.getBoolean(SP_ENABLE_SMS, false)
set(enableSms) {
MMKVUtils.put(SP_ENABLE_SMS, enableSms)
}
//是否转发通话 //是否转发通话
@JvmStatic var enablePhone: Boolean by SharedPreference(SP_ENABLE_PHONE, false)
var enablePhone: Boolean
get() = MMKVUtils.getBoolean(SP_ENABLE_PHONE, false)
set(enablePhone) {
MMKVUtils.put(SP_ENABLE_PHONE, enablePhone)
}
//是否转发通话——已接来电 //是否转发通话——已接来电
@JvmStatic var enableCallType1: Boolean by SharedPreference(SP_ENABLE_CALL_TYPE_1, false)
var enableCallType1: Boolean
get() = MMKVUtils.getBoolean(SP_ENABLE_CALL_TYPE_1, false)
set(enableCallType1) {
MMKVUtils.put(SP_ENABLE_CALL_TYPE_1, enableCallType1)
}
//是否转发通话——本机去电 //是否转发通话——本机去电
@JvmStatic var enableCallType2: Boolean by SharedPreference(SP_ENABLE_CALL_TYPE_2, false)
var enableCallType2: Boolean
get() = MMKVUtils.getBoolean(SP_ENABLE_CALL_TYPE_2, false)
set(enableCallType2) {
MMKVUtils.put(SP_ENABLE_CALL_TYPE_2, enableCallType2)
}
//是否转发通话——未接来电 //是否转发通话——未接来电
@JvmStatic var enableCallType3: Boolean by SharedPreference(SP_ENABLE_CALL_TYPE_3, false)
var enableCallType3: Boolean
get() = MMKVUtils.getBoolean(SP_ENABLE_CALL_TYPE_3, false)
set(enableCallType3) {
MMKVUtils.put(SP_ENABLE_CALL_TYPE_3, enableCallType3)
}
//是否转发通话——来电提醒 //是否转发通话——来电提醒
@JvmStatic var enableCallType4: Boolean by SharedPreference(SP_ENABLE_CALL_TYPE_4, false)
var enableCallType4: Boolean
get() = MMKVUtils.getBoolean(SP_ENABLE_CALL_TYPE_4, false)
set(enableCallType4) {
MMKVUtils.put(SP_ENABLE_CALL_TYPE_4, enableCallType4)
}
//是否转发应用通知 //是否转发应用通知
@JvmStatic var enableAppNotify: Boolean by SharedPreference(SP_ENABLE_APP_NOTIFY, false)
var enableAppNotify: Boolean
get() = MMKVUtils.getBoolean(SP_ENABLE_APP_NOTIFY, false)
set(enableAppNotify) {
MMKVUtils.put(SP_ENABLE_APP_NOTIFY, enableAppNotify)
}
//是否转发应用通知——自动消除通知 //是否转发应用通知——自动消除通知
@JvmStatic var enableCancelAppNotify: Boolean by SharedPreference(SP_ENABLE_CANCEL_APP_NOTIFY, false)
var enableCancelAppNotify: Boolean
get() = MMKVUtils.getBoolean(SP_ENABLE_CANCEL_APP_NOTIFY, false)
set(enableCancelAppNotify) {
MMKVUtils.put(SP_ENABLE_CANCEL_APP_NOTIFY, enableCancelAppNotify)
}
//是否转发应用通知——仅锁屏状态 //是否转发应用通知——仅锁屏状态
@JvmStatic var enableNotUserPresent: Boolean by SharedPreference(SP_ENABLE_NOT_USER_PRESENT, false)
var enableNotUserPresent: Boolean
get() = MMKVUtils.getBoolean(SP_ENABLE_NOT_USER_PRESENT, false)
set(enableNotUserPresent) {
MMKVUtils.put(SP_ENABLE_NOT_USER_PRESENT, enableNotUserPresent)
}
//是否加载应用列表 //是否加载应用列表
@JvmStatic var enableLoadAppList: Boolean by SharedPreference(ENABLE_LOAD_APP_LIST, false)
var enableLoadAppList: Boolean
get() = MMKVUtils.getBoolean(ENABLE_LOAD_APP_LIST, false)
set(enableLoadAppList) {
MMKVUtils.put(ENABLE_LOAD_APP_LIST, enableLoadAppList)
}
//是否加载应用列表——用户应用 //是否加载应用列表——用户应用
@JvmStatic var enableLoadUserAppList: Boolean by SharedPreference(ENABLE_LOAD_USER_APP_LIST, false)
var enableLoadUserAppList: Boolean
get() = MMKVUtils.getBoolean(ENABLE_LOAD_USER_APP_LIST, false)
set(enableLoadUserAppList) {
MMKVUtils.put(ENABLE_LOAD_USER_APP_LIST, enableLoadUserAppList)
}
//是否加载应用列表——系统应用 //是否加载应用列表——系统应用
@JvmStatic var enableLoadSystemAppList: Boolean by SharedPreference(ENABLE_LOAD_SYSTEM_APP_LIST, false)
var enableLoadSystemAppList: Boolean
get() = MMKVUtils.getBoolean(ENABLE_LOAD_SYSTEM_APP_LIST, false)
set(enableLoadSystemAppList) {
MMKVUtils.put(ENABLE_LOAD_SYSTEM_APP_LIST, enableLoadSystemAppList)
}
//过滤多久内重复消息 //过滤多久内重复消息
@JvmStatic var duplicateMessagesLimits: Int by SharedPreference(SP_DUPLICATE_MESSAGES_LIMITS, 0)
var duplicateMessagesLimits: Int
get() = MMKVUtils.getInt(SP_DUPLICATE_MESSAGES_LIMITS, 0)
set(duplicateMessagesLimits) {
MMKVUtils.put(SP_DUPLICATE_MESSAGES_LIMITS, duplicateMessagesLimits)
}
//免打扰(禁用转发)时间段——开始 //免打扰(禁用转发)时间段——开始
@JvmStatic var silentPeriodStart: Int by SharedPreference(SP_SILENT_PERIOD_START, 0)
var silentPeriodStart: Int
get() = MMKVUtils.getInt(SP_SILENT_PERIOD_START, 0)
set(silentPeriodStart) {
MMKVUtils.put(SP_SILENT_PERIOD_START, silentPeriodStart)
}
//免打扰(禁用转发)时间段——结束 //免打扰(禁用转发)时间段——结束
@JvmStatic var silentPeriodEnd: Int by SharedPreference(SP_SILENT_PERIOD_END, 0)
var silentPeriodEnd: Int
get() = MMKVUtils.getInt(SP_SILENT_PERIOD_END, 0)
set(silentPeriodEnd) {
MMKVUtils.put(SP_SILENT_PERIOD_END, silentPeriodEnd)
}
//自动删除N天前的转发记录 //自动删除N天前的转发记录
@JvmStatic var autoCleanLogsDays: Int by SharedPreference(SP_AUTO_CLEAN_LOGS_DAYS, 0)
var autoCleanLogsDays: Int
get() = MMKVUtils.getInt(SP_AUTO_CLEAN_LOGS_DAYS, 0)
set(autoCleanLogsDays) {
MMKVUtils.put(SP_AUTO_CLEAN_LOGS_DAYS, autoCleanLogsDays)
}
//是否监听电池状态变化 //是否监听电池状态变化
@JvmStatic var enableBatteryReceiver: Boolean by SharedPreference(SP_BATTERY_RECEIVER, false)
var enableBatteryReceiver: Boolean
get() = MMKVUtils.getBoolean(SP_BATTERY_RECEIVER, false)
set(enableBatteryReceiver) {
MMKVUtils.put(SP_BATTERY_RECEIVER, enableBatteryReceiver)
}
//电量预警当前状态 //电量预警当前状态
@JvmStatic var batteryStatus: Int by SharedPreference(SP_BATTERY_STATUS, 0)
var batteryStatus: Int
get() = MMKVUtils.getInt(SP_BATTERY_STATUS, 0)
set(batteryStatus) {
MMKVUtils.put(SP_BATTERY_STATUS, batteryStatus)
}
//电量预警当前值 //电量预警当前值
@JvmStatic var batteryLevelCurrent: Int by SharedPreference(SP_BATTERY_LEVEL_CURRENT, 0)
var batteryLevelCurrent: Int
get() = MMKVUtils.getInt(SP_BATTERY_LEVEL_CURRENT, 0)
set(batteryLevelCurrent) {
MMKVUtils.put(SP_BATTERY_LEVEL_CURRENT, batteryLevelCurrent)
}
//电量预警最低值 //电量预警最低值
@JvmStatic var batteryLevelMin: Int by SharedPreference(SP_BATTERY_LEVEL_MIN, 0)
var batteryLevelMin: Int
get() = MMKVUtils.getInt(SP_BATTERY_LEVEL_MIN, 0)
set(batteryLevelMin) {
MMKVUtils.put(SP_BATTERY_LEVEL_MIN, batteryLevelMin)
}
//电量预警最高值 //电量预警最高值
@JvmStatic var batteryLevelMax: Int by SharedPreference(SP_BATTERY_LEVEL_MAX, 100)
var batteryLevelMax: Int
get() = MMKVUtils.getInt(SP_BATTERY_LEVEL_MAX, 100)
set(batteryLevelMax) {
MMKVUtils.put(SP_BATTERY_LEVEL_MAX, batteryLevelMax)
}
//是否持续电量预警 //是否持续电量预警
@JvmStatic var batteryLevelOnce: Boolean by SharedPreference(SP_BATTERY_LEVEL_ONCE, false)
var batteryLevelOnce: Boolean
get() = MMKVUtils.getBoolean(SP_BATTERY_LEVEL_ONCE, false)
set(batteryLevelOnce) {
MMKVUtils.put(SP_BATTERY_LEVEL_ONCE, batteryLevelOnce)
}
//是否定时推送电池状态 //是否定时推送电池状态
@JvmStatic var enableBatteryCron: Boolean by SharedPreference(SP_BATTERY_CRON, false)
var enableBatteryCron: Boolean
get() = MMKVUtils.getBoolean(SP_BATTERY_CRON, false)
set(enableBatteryCron) {
MMKVUtils.put(SP_BATTERY_CRON, enableBatteryCron)
}
//是否定时推送电池状态——开始时间 //是否定时推送电池状态——开始时间
@JvmStatic var batteryCronStartTime: String by SharedPreference(SP_BATTERY_CRON_START_TIME, "00:00")
var batteryCronStartTime: String?
get() = MMKVUtils.getString(SP_BATTERY_CRON_START_TIME, "00:00")
set(batteryCronStartTime) {
MMKVUtils.put(SP_BATTERY_CRON_START_TIME, batteryCronStartTime)
}
//是否定时推送电池状态——间隔时间(分钟) //是否定时推送电池状态——间隔时间(分钟)
@JvmStatic var batteryCronInterval: Int by SharedPreference(SP_BATTERY_CRON_INTERVAL, 60)
var batteryCronInterval: Int
get() = MMKVUtils.getInt(SP_BATTERY_CRON_INTERVAL, 60)
set(batteryCronInterval) {
MMKVUtils.put(SP_BATTERY_CRON_INTERVAL, batteryCronInterval)
}
//是否不在最近任务列表中显示 //是否不在最近任务列表中显示
@JvmStatic var enableExcludeFromRecents: Boolean by SharedPreference(SP_ENABLE_EXCLUDE_FROM_RECENTS, false)
var enableExcludeFromRecents: Boolean
get() = MMKVUtils.getBoolean(SP_ENABLE_EXCLUDE_FROM_RECENTS, false)
set(enableExcludeFromRecents) {
MMKVUtils.put(SP_ENABLE_EXCLUDE_FROM_RECENTS, enableExcludeFromRecents)
}
//是否转发应用通知 //是否转发应用通知
@JvmStatic var enableCactus: Boolean by SharedPreference(SP_ENABLE_CACTUS, false)
var enableCactus: Boolean
get() = MMKVUtils.getBoolean(SP_ENABLE_CACTUS, false)
set(enableAppNotify) {
MMKVUtils.put(SP_ENABLE_CACTUS, enableAppNotify)
}
//是否播放静音音乐 //是否播放静音音乐
@JvmStatic var enablePlaySilenceMusic: Boolean by SharedPreference(SP_ENABLE_PLAY_SILENCE_MUSIC, false)
var enablePlaySilenceMusic: Boolean
get() = MMKVUtils.getBoolean(SP_ENABLE_PLAY_SILENCE_MUSIC, false)
set(enablePlaySilenceMusic) {
MMKVUtils.put(SP_ENABLE_PLAY_SILENCE_MUSIC, enablePlaySilenceMusic)
}
//是否启用1像素 //是否启用1像素
@JvmStatic var enableOnePixelActivity: Boolean by SharedPreference(SP_ENABLE_ONE_PIXEL_ACTIVITY, false)
var enableOnePixelActivity: Boolean
get() = MMKVUtils.getBoolean(SP_ENABLE_ONE_PIXEL_ACTIVITY, false)
set(enableOnePixelActivity) {
MMKVUtils.put(SP_ENABLE_ONE_PIXEL_ACTIVITY, enableOnePixelActivity)
}
//请求接口失败重试次数 //请求接口失败重试次数
@JvmStatic var requestRetryTimes: Int by SharedPreference(SP_REQUEST_RETRY_TIMES, 0)
var requestRetryTimes: Int
get() = MMKVUtils.getInt(SP_REQUEST_RETRY_TIMES, 0)
set(requestRetryTimes) {
MMKVUtils.put(SP_REQUEST_RETRY_TIMES, requestRetryTimes)
}
//请求接口失败重试间隔(秒) //请求接口失败重试间隔(秒)
@JvmStatic var requestDelayTime: Int by SharedPreference(SP_REQUEST_DELAY_TIME, 1)
var requestDelayTime: Int
get() = MMKVUtils.getInt(SP_REQUEST_DELAY_TIME, 1)
set(requestDelayTime) {
MMKVUtils.put(SP_REQUEST_DELAY_TIME, requestDelayTime)
}
//请求接口失败超时时间(秒) //请求接口失败超时时间(秒)
@JvmStatic var requestTimeout: Int by SharedPreference(SP_REQUEST_TIMEOUT, 10)
var requestTimeout: Int
get() = MMKVUtils.getInt(SP_REQUEST_TIMEOUT, 10)
set(requestTimeout) {
MMKVUtils.put(SP_REQUEST_TIMEOUT, requestTimeout)
}
//通知内容 //通知内容
@JvmStatic var notifyContent: String by SharedPreference(SP_NOTIFY_CONTENT, getString(R.string.notification_content))
var notifyContent: String?
get() = MMKVUtils.getString(SP_NOTIFY_CONTENT, getString(R.string.notification_content))
set(notificationContent) {
MMKVUtils.put(SP_NOTIFY_CONTENT, notificationContent)
}
//设备名称 //设备名称
@JvmStatic var extraDeviceMark: String by SharedPreference(SP_EXTRA_DEVICE_MARK, "")
var extraDeviceMark: String?
get() = MMKVUtils.getString(SP_EXTRA_DEVICE_MARK, "")
set(extraDeviceMark) {
MMKVUtils.put(SP_EXTRA_DEVICE_MARK, extraDeviceMark)
}
//SM1备注 //SM1备注
@JvmStatic var extraSim1: String by SharedPreference(SP_EXTRA_SIM1, "")
var extraSim1: String?
get() = MMKVUtils.getString(SP_EXTRA_SIM1, "")
set(extraSim1) {
MMKVUtils.put(SP_EXTRA_SIM1, extraSim1)
}
//SM2备注 //SM2备注
@JvmStatic var extraSim2: String by SharedPreference(SP_EXTRA_SIM2, "")
var extraSim2: String?
get() = MMKVUtils.getString(SP_EXTRA_SIM2, "")
set(extraSim2) {
MMKVUtils.put(SP_EXTRA_SIM2, extraSim2)
}
//是否启用自定义模板 //是否启用自定义模板
@JvmStatic var enableSmsTemplate: Boolean by SharedPreference(SP_ENABLE_SMS_TEMPLATE, false)
var enableSmsTemplate: Boolean
get() = MMKVUtils.getBoolean(SP_ENABLE_SMS_TEMPLATE, false)
set(enableSmsTemplate) {
MMKVUtils.put(SP_ENABLE_SMS_TEMPLATE, enableSmsTemplate)
}
//自定义模板 //自定义模板
@JvmStatic var smsTemplate: String by SharedPreference(SP_SMS_TEMPLATE, "")
var smsTemplate: String?
get() = MMKVUtils.getString(SP_SMS_TEMPLATE, "")
set(smsTemplate) {
MMKVUtils.put(SP_SMS_TEMPLATE, smsTemplate)
}
//是否显示页面帮助 //是否显示页面帮助
@JvmStatic var enableHelpTip: Boolean by SharedPreference(SP_ENABLE_HELP_TIP, false)
var enableHelpTip: Boolean
get() = MMKVUtils.getBoolean(SP_ENABLE_HELP_TIP, false)
set(enableHelpTip) {
MMKVUtils.put(SP_ENABLE_HELP_TIP, enableHelpTip)
}
//是否纯客户端模式 //是否纯客户端模式
@JvmStatic var enablePureClientMode: Boolean by SharedPreference(SP_PURE_CLIENT_MODE, false)
var enablePureClientMode: Boolean
get() = MMKVUtils.getBoolean(SP_PURE_CLIENT_MODE, false)
set(enablePureClientMode) {
MMKVUtils.put(SP_PURE_CLIENT_MODE, enablePureClientMode)
}
} }
init { init {

@ -0,0 +1,108 @@
package com.idormy.sms.forwarder.utils
import android.content.Context
import android.content.SharedPreferences
import android.os.Build
import java.io.*
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
class SharedPreference<T>(private val name: String, private val default: T) : ReadWriteProperty<Any?, T> {
companion object {
lateinit var preference: SharedPreferences
fun init(context: Context) {
preference = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
val directBootContext: Context = context.createDeviceProtectedStorageContext()
directBootContext.getSharedPreferences(context.packageName, Context.MODE_PRIVATE)
} else {
context.getSharedPreferences(context.packageName, Context.MODE_PRIVATE)
}
}
//删除全部数据
fun clearPreference() = preference.edit().clear().apply()
//根据key删除存储数据
fun clearPreference(key: String) = preference.edit().remove(key).commit()
}
override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
return putPreference(name, value)
}
override fun getValue(thisRef: Any?, property: KProperty<*>): T {
return getPreference(name, default)
}
/**
* 查找数据 返回给调用方法一个具体的对象
* 如果查找不到类型就采用反序列化方法来返回类型
* default是默认对象 以防止会返回空对象的异常
* 即如果name没有查找到value 就返回默认的序列化对象然后经过反序列化返回
*/
private fun getPreference(name: String, default: T): T = with(preference) {
val res: Any = when (default) {
is Long -> getLong(name, default)
is String -> this.getString(name, default)!!
is Int -> getInt(name, default)
is Boolean -> getBoolean(name, default)
is Float -> getFloat(name, default)
//else -> throw IllegalArgumentException("This type can be get from Preferences")
else -> deSerialization(getString(name, serialize(default)).toString())
}
return res as T
}
private fun putPreference(name: String, value: T) = with(preference.edit()) {
when (value) {
is Long -> putLong(name, value)
is Int -> putInt(name, value)
is String -> putString(name, value)
is Boolean -> putBoolean(name, value)
is Float -> putFloat(name, value)
//else -> throw IllegalArgumentException("This type can be saved into Preferences")
else -> putString(name, serialize(value))
}.apply()
}
/**
* 序列化对象
* @throws IOException
*/
@Throws(IOException::class)
private fun <T> serialize(obj: T): String {
val byteArrayOutputStream = ByteArrayOutputStream()
val objectOutputStream = ObjectOutputStream(
byteArrayOutputStream
)
objectOutputStream.writeObject(obj)
var serStr = byteArrayOutputStream.toString("ISO-8859-1")
serStr = java.net.URLEncoder.encode(serStr, "UTF-8")
objectOutputStream.close()
byteArrayOutputStream.close()
return serStr
}
/**
* 反序列化对象
* @param str
* @throws IOException
* @throws ClassNotFoundException
*/
@Throws(IOException::class, ClassNotFoundException::class)
private fun <T> deSerialization(str: String): T {
val redStr = java.net.URLDecoder.decode(str, "UTF-8")
val byteArrayInputStream = ByteArrayInputStream(
redStr.toByteArray(charset("ISO-8859-1"))
)
val objectInputStream = ObjectInputStream(
byteArrayInputStream
)
val obj = objectInputStream.readObject() as T
objectInputStream.close()
byteArrayInputStream.close()
return obj
}
}

@ -8,9 +8,9 @@ import com.idormy.sms.forwarder.database.entity.Rule
import com.idormy.sms.forwarder.entity.MsgInfo import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.entity.result.DingtalkInnerRobotResult import com.idormy.sms.forwarder.entity.result.DingtalkInnerRobotResult
import com.idormy.sms.forwarder.entity.setting.DingtalkInnerRobotSetting import com.idormy.sms.forwarder.entity.setting.DingtalkInnerRobotSetting
import com.idormy.sms.forwarder.utils.MMKVUtils
import com.idormy.sms.forwarder.utils.SendUtils import com.idormy.sms.forwarder.utils.SendUtils
import com.idormy.sms.forwarder.utils.SettingUtils import com.idormy.sms.forwarder.utils.SettingUtils
import com.idormy.sms.forwarder.utils.SharedPreference
import com.xuexiang.xhttp2.XHttp import com.xuexiang.xhttp2.XHttp
import com.xuexiang.xhttp2.cache.model.CacheMode import com.xuexiang.xhttp2.cache.model.CacheMode
import com.xuexiang.xhttp2.callback.SimpleCallBack import com.xuexiang.xhttp2.callback.SimpleCallBack
@ -38,9 +38,8 @@ class DingtalkInnerRobotUtils private constructor() {
rule: Rule?, rule: Rule?,
logId: Long?, logId: Long?,
) { ) {
var accessToken: String by SharedPreference("accessToken_" + setting.agentID, "")
val accessToken: String? = MMKVUtils.getString("accessToken_" + setting.agentID, "") var expiresIn: Long by SharedPreference("expiresIn_" + setting.agentID, 0L)
val expiresIn: Long = MMKVUtils.getLong("expiresIn_" + setting.agentID, 0L)
if (!TextUtils.isEmpty(accessToken) && expiresIn > System.currentTimeMillis()) { if (!TextUtils.isEmpty(accessToken) && expiresIn > System.currentTimeMillis()) {
return sendTextMsg(setting, msgInfo, rule, logId) return sendTextMsg(setting, msgInfo, rule, logId)
} }
@ -57,9 +56,7 @@ class DingtalkInnerRobotUtils private constructor() {
val request = XHttp.post(requestUrl) val request = XHttp.post(requestUrl)
//设置代理 //设置代理
if ((setting.proxyType == Proxy.Type.HTTP || setting.proxyType == Proxy.Type.SOCKS) if ((setting.proxyType == Proxy.Type.HTTP || setting.proxyType == Proxy.Type.SOCKS) && !TextUtils.isEmpty(setting.proxyHost) && !TextUtils.isEmpty(setting.proxyPort)) {
&& !TextUtils.isEmpty(setting.proxyHost) && !TextUtils.isEmpty(setting.proxyPort)
) {
//代理服务器的IP和端口号 //代理服务器的IP和端口号
Log.d(TAG, "proxyHost = ${setting.proxyHost}, proxyPort = ${setting.proxyPort}") Log.d(TAG, "proxyHost = ${setting.proxyHost}, proxyPort = ${setting.proxyPort}")
val proxyHost = if (NetworkUtils.isIP(setting.proxyHost)) setting.proxyHost else NetworkUtils.getDomainAddress(setting.proxyHost) val proxyHost = if (NetworkUtils.isIP(setting.proxyHost)) setting.proxyHost else NetworkUtils.getDomainAddress(setting.proxyHost)
@ -72,18 +69,14 @@ class DingtalkInnerRobotUtils private constructor() {
request.okproxy(Proxy(setting.proxyType, InetSocketAddress(proxyHost, proxyPort))) request.okproxy(Proxy(setting.proxyType, InetSocketAddress(proxyHost, proxyPort)))
//代理的鉴权账号密码 //代理的鉴权账号密码
if (setting.proxyAuthenticator == true if (setting.proxyAuthenticator == true && (!TextUtils.isEmpty(setting.proxyUsername) || !TextUtils.isEmpty(setting.proxyPassword))) {
&& (!TextUtils.isEmpty(setting.proxyUsername) || !TextUtils.isEmpty(setting.proxyPassword))
) {
Log.i(TAG, "proxyUsername = ${setting.proxyUsername}, proxyPassword = ${setting.proxyPassword}") Log.i(TAG, "proxyUsername = ${setting.proxyUsername}, proxyPassword = ${setting.proxyPassword}")
if (setting.proxyType == Proxy.Type.HTTP) { if (setting.proxyType == Proxy.Type.HTTP) {
request.okproxyAuthenticator { _: Route?, response: Response -> request.okproxyAuthenticator { _: Route?, response: Response ->
//设置代理服务器账号密码 //设置代理服务器账号密码
val credential = Credentials.basic(setting.proxyUsername.toString(), setting.proxyPassword.toString()) val credential = Credentials.basic(setting.proxyUsername.toString(), setting.proxyPassword.toString())
response.request().newBuilder() response.request().newBuilder().header("Proxy-Authorization", credential).build()
.header("Proxy-Authorization", credential)
.build()
} }
} else { } else {
Authenticator.setDefault(object : Authenticator() { Authenticator.setDefault(object : Authenticator() {
@ -95,13 +88,8 @@ class DingtalkInnerRobotUtils private constructor() {
} }
} }
request.upJson(requestMsg) request.upJson(requestMsg).keepJson(true).ignoreHttpsCert().timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s
.keepJson(true) .cacheMode(CacheMode.NO_CACHE).timeStamp(true).execute(object : SimpleCallBack<String>() {
.ignoreHttpsCert()
.timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s
.cacheMode(CacheMode.NO_CACHE)
.timeStamp(true)
.execute(object : SimpleCallBack<String>() {
override fun onError(e: ApiException) { override fun onError(e: ApiException) {
Log.e(TAG, e.detailMessage) Log.e(TAG, e.detailMessage)
@ -113,8 +101,8 @@ class DingtalkInnerRobotUtils private constructor() {
val resp = Gson().fromJson(response, DingtalkInnerRobotResult::class.java) val resp = Gson().fromJson(response, DingtalkInnerRobotResult::class.java)
if (!TextUtils.isEmpty(resp?.accessToken)) { if (!TextUtils.isEmpty(resp?.accessToken)) {
MMKVUtils.put("accessToken_" + setting.agentID, resp.accessToken) accessToken = resp.accessToken.toString()
MMKVUtils.put("expiresIn_" + setting.agentID, System.currentTimeMillis() + ((resp.expireIn ?: 7200) - 120) * 1000L) //提前2分钟过期 expiresIn = System.currentTimeMillis() + ((resp.expireIn ?: 7200) - 120) * 1000L //提前2分钟过期
sendTextMsg(setting, msgInfo, rule, logId) sendTextMsg(setting, msgInfo, rule, logId)
} else { } else {
SendUtils.updateLogs(logId, 0, String.format(getString(R.string.request_failed_tips), response)) SendUtils.updateLogs(logId, 0, String.format(getString(R.string.request_failed_tips), response))
@ -165,9 +153,7 @@ class DingtalkInnerRobotUtils private constructor() {
val request = XHttp.post(requestUrl) val request = XHttp.post(requestUrl)
//设置代理 //设置代理
if ((setting.proxyType == Proxy.Type.HTTP || setting.proxyType == Proxy.Type.SOCKS) if ((setting.proxyType == Proxy.Type.HTTP || setting.proxyType == Proxy.Type.SOCKS) && !TextUtils.isEmpty(setting.proxyHost) && !TextUtils.isEmpty(setting.proxyPort)) {
&& !TextUtils.isEmpty(setting.proxyHost) && !TextUtils.isEmpty(setting.proxyPort)
) {
//代理服务器的IP和端口号 //代理服务器的IP和端口号
Log.d(TAG, "proxyHost = ${setting.proxyHost}, proxyPort = ${setting.proxyPort}") Log.d(TAG, "proxyHost = ${setting.proxyHost}, proxyPort = ${setting.proxyPort}")
val proxyHost = if (NetworkUtils.isIP(setting.proxyHost)) setting.proxyHost else NetworkUtils.getDomainAddress(setting.proxyHost) val proxyHost = if (NetworkUtils.isIP(setting.proxyHost)) setting.proxyHost else NetworkUtils.getDomainAddress(setting.proxyHost)
@ -180,18 +166,14 @@ class DingtalkInnerRobotUtils private constructor() {
request.okproxy(Proxy(setting.proxyType, InetSocketAddress(proxyHost, proxyPort))) request.okproxy(Proxy(setting.proxyType, InetSocketAddress(proxyHost, proxyPort)))
//代理的鉴权账号密码 //代理的鉴权账号密码
if (setting.proxyAuthenticator == true if (setting.proxyAuthenticator == true && (!TextUtils.isEmpty(setting.proxyUsername) || !TextUtils.isEmpty(setting.proxyPassword))) {
&& (!TextUtils.isEmpty(setting.proxyUsername) || !TextUtils.isEmpty(setting.proxyPassword))
) {
Log.i(TAG, "proxyUsername = ${setting.proxyUsername}, proxyPassword = ${setting.proxyPassword}") Log.i(TAG, "proxyUsername = ${setting.proxyUsername}, proxyPassword = ${setting.proxyPassword}")
if (setting.proxyType == Proxy.Type.HTTP) { if (setting.proxyType == Proxy.Type.HTTP) {
request.okproxyAuthenticator { _: Route?, response: Response -> request.okproxyAuthenticator { _: Route?, response: Response ->
//设置代理服务器账号密码 //设置代理服务器账号密码
val credential = Credentials.basic(setting.proxyUsername.toString(), setting.proxyPassword.toString()) val credential = Credentials.basic(setting.proxyUsername.toString(), setting.proxyPassword.toString())
response.request().newBuilder() response.request().newBuilder().header("Proxy-Authorization", credential).build()
.header("Proxy-Authorization", credential)
.build()
} }
} else { } else {
Authenticator.setDefault(object : Authenticator() { Authenticator.setDefault(object : Authenticator() {
@ -203,17 +185,15 @@ class DingtalkInnerRobotUtils private constructor() {
} }
} }
request.upJson(requestMsg) val accessToken: String by SharedPreference("accessToken_" + setting.agentID, "")
.headers("x-acs-dingtalk-access-token", MMKVUtils.getString("accessToken_" + setting.agentID, "")) request.upJson(requestMsg).headers("x-acs-dingtalk-access-token", accessToken)
.keepJson(true) .keepJson(true)
.ignoreHttpsCert() .ignoreHttpsCert()
.timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s .timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s
.cacheMode(CacheMode.NO_CACHE) .cacheMode(CacheMode.NO_CACHE).retryCount(SettingUtils.requestRetryTimes) //超时重试的次数
.retryCount(SettingUtils.requestRetryTimes) //超时重试的次数
.retryDelay(SettingUtils.requestDelayTime) //超时重试的延迟时间 .retryDelay(SettingUtils.requestDelayTime) //超时重试的延迟时间
.retryIncreaseDelay(SettingUtils.requestDelayTime) //超时重试叠加延时 .retryIncreaseDelay(SettingUtils.requestDelayTime) //超时重试叠加延时
.timeStamp(true) .timeStamp(true).execute(object : SimpleCallBack<String>() {
.execute(object : SimpleCallBack<String>() {
override fun onError(e: ApiException) { override fun onError(e: ApiException) {
Log.e(TAG, e.detailMessage) Log.e(TAG, e.detailMessage)

@ -8,9 +8,9 @@ import com.idormy.sms.forwarder.database.entity.Rule
import com.idormy.sms.forwarder.entity.MsgInfo import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.entity.result.FeishuAppResult import com.idormy.sms.forwarder.entity.result.FeishuAppResult
import com.idormy.sms.forwarder.entity.setting.FeishuAppSetting import com.idormy.sms.forwarder.entity.setting.FeishuAppSetting
import com.idormy.sms.forwarder.utils.MMKVUtils
import com.idormy.sms.forwarder.utils.SendUtils import com.idormy.sms.forwarder.utils.SendUtils
import com.idormy.sms.forwarder.utils.SettingUtils import com.idormy.sms.forwarder.utils.SettingUtils
import com.idormy.sms.forwarder.utils.SharedPreference
import com.xuexiang.xhttp2.XHttp import com.xuexiang.xhttp2.XHttp
import com.xuexiang.xhttp2.cache.model.CacheMode import com.xuexiang.xhttp2.cache.model.CacheMode
import com.xuexiang.xhttp2.callback.SimpleCallBack import com.xuexiang.xhttp2.callback.SimpleCallBack
@ -31,8 +31,8 @@ class FeishuAppUtils private constructor() {
logId: Long?, logId: Long?,
) { ) {
val accessToken: String? = MMKVUtils.getString("feishu_access_token_" + setting.appId, "") var accessToken: String by SharedPreference("feishu_access_token_" + setting.appId, "")
val expiresIn: Long = MMKVUtils.getLong("feishu_expires_in_" + setting.appId, 0L) var expiresIn: Long by SharedPreference("feishu_expires_in_" + setting.appId, 0L)
if (!TextUtils.isEmpty(accessToken) && expiresIn > System.currentTimeMillis()) { if (!TextUtils.isEmpty(accessToken) && expiresIn > System.currentTimeMillis()) {
return sendTextMsg(setting, msgInfo, rule, logId) return sendTextMsg(setting, msgInfo, rule, logId)
} }
@ -46,14 +46,8 @@ class FeishuAppUtils private constructor() {
val requestMsg: String = Gson().toJson(msgMap) val requestMsg: String = Gson().toJson(msgMap)
Log.i(TAG, "requestMsg:$requestMsg") Log.i(TAG, "requestMsg:$requestMsg")
XHttp.post(requestUrl) XHttp.post(requestUrl).upJson(requestMsg).keepJson(true).ignoreHttpsCert().timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s
.upJson(requestMsg) .cacheMode(CacheMode.NO_CACHE).timeStamp(true).execute(object : SimpleCallBack<String>() {
.keepJson(true)
.ignoreHttpsCert()
.timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s
.cacheMode(CacheMode.NO_CACHE)
.timeStamp(true)
.execute(object : SimpleCallBack<String>() {
override fun onError(e: ApiException) { override fun onError(e: ApiException) {
Log.e(TAG, e.detailMessage) Log.e(TAG, e.detailMessage)
@ -65,8 +59,8 @@ class FeishuAppUtils private constructor() {
val resp = Gson().fromJson(response, FeishuAppResult::class.java) val resp = Gson().fromJson(response, FeishuAppResult::class.java)
if (!TextUtils.isEmpty(resp?.tenant_access_token)) { if (!TextUtils.isEmpty(resp?.tenant_access_token)) {
MMKVUtils.put("feishu_access_token_" + setting.appId, resp.tenant_access_token) accessToken = resp.tenant_access_token.toString()
MMKVUtils.put("feishu_expires_in_" + setting.appId, System.currentTimeMillis() + ((resp.expire ?: 7010) - 120) * 1000L) //提前2分钟过期 expiresIn = System.currentTimeMillis() + ((resp.expire ?: 7010) - 120) * 1000L //提前2分钟过期
sendTextMsg(setting, msgInfo, rule, logId) sendTextMsg(setting, msgInfo, rule, logId)
} else { } else {
SendUtils.updateLogs(logId, 0, String.format(getString(R.string.request_failed_tips), response)) SendUtils.updateLogs(logId, 0, String.format(getString(R.string.request_failed_tips), response))
@ -99,9 +93,7 @@ class FeishuAppUtils private constructor() {
} else { } else {
msgInfo.getTitleForSend(setting.titleTemplate) msgInfo.getTitleForSend(setting.titleTemplate)
} }
"{\"elements\":[{\"tag\":\"markdown\",\"content\":\"**[{{MSG_TITLE}}]({{MSG_URL}})**\\n --------------\\n{{MSG_CONTENT}}\"}]}".trimIndent().replace("{{MSG_TITLE}}", jsonInnerStr(title)) "{\"elements\":[{\"tag\":\"markdown\",\"content\":\"**[{{MSG_TITLE}}]({{MSG_URL}})**\\n --------------\\n{{MSG_CONTENT}}\"}]}".trimIndent().replace("{{MSG_TITLE}}", jsonInnerStr(title)).replace("{{MSG_URL}}", jsonInnerStr("https://github.com/pppscn/SmsForwarder")).replace("{{MSG_CONTENT}}", jsonInnerStr(content))
.replace("{{MSG_URL}}", jsonInnerStr("https://github.com/pppscn/SmsForwarder"))
.replace("{{MSG_CONTENT}}", jsonInnerStr(content))
} else { } else {
"{\"text\":\"{{MSG_CONTENT}}\"}".trimIndent().replace("{{MSG_CONTENT}}", jsonInnerStr(content)) "{\"text\":\"{{MSG_CONTENT}}\"}".trimIndent().replace("{{MSG_CONTENT}}", jsonInnerStr(content))
} }
@ -114,18 +106,14 @@ class FeishuAppUtils private constructor() {
val requestMsg: String = Gson().toJson(textMsgMap) val requestMsg: String = Gson().toJson(textMsgMap)
Log.i(TAG, "requestMsg:$requestMsg") Log.i(TAG, "requestMsg:$requestMsg")
XHttp.post(requestUrl) val accessToken: String by SharedPreference("feishu_access_token_" + setting.appId, "")
.upJson(requestMsg) XHttp.post(requestUrl).upJson(requestMsg).headers("Authorization", "Bearer $accessToken").keepJson(true)
.headers("Authorization", "Bearer " + MMKVUtils.getString("feishu_access_token_" + setting.appId, ""))
.keepJson(true)
//.ignoreHttpsCert() //.ignoreHttpsCert()
.timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s .timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s
.cacheMode(CacheMode.NO_CACHE) .cacheMode(CacheMode.NO_CACHE).retryCount(SettingUtils.requestRetryTimes) //超时重试的次数
.retryCount(SettingUtils.requestRetryTimes) //超时重试的次数
.retryDelay(SettingUtils.requestDelayTime) //超时重试的延迟时间 .retryDelay(SettingUtils.requestDelayTime) //超时重试的延迟时间
.retryIncreaseDelay(SettingUtils.requestDelayTime) //超时重试叠加延时 .retryIncreaseDelay(SettingUtils.requestDelayTime) //超时重试叠加延时
.timeStamp(true) .timeStamp(true).execute(object : SimpleCallBack<String>() {
.execute(object : SimpleCallBack<String>() {
override fun onError(e: ApiException) { override fun onError(e: ApiException) {
Log.e(TAG, e.detailMessage) Log.e(TAG, e.detailMessage)

@ -9,9 +9,9 @@ import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.entity.result.DingtalkResult import com.idormy.sms.forwarder.entity.result.DingtalkResult
import com.idormy.sms.forwarder.entity.result.WeworkAgentResult import com.idormy.sms.forwarder.entity.result.WeworkAgentResult
import com.idormy.sms.forwarder.entity.setting.WeworkAgentSetting import com.idormy.sms.forwarder.entity.setting.WeworkAgentSetting
import com.idormy.sms.forwarder.utils.MMKVUtils
import com.idormy.sms.forwarder.utils.SendUtils import com.idormy.sms.forwarder.utils.SendUtils
import com.idormy.sms.forwarder.utils.SettingUtils import com.idormy.sms.forwarder.utils.SettingUtils
import com.idormy.sms.forwarder.utils.SharedPreference
import com.xuexiang.xhttp2.XHttp import com.xuexiang.xhttp2.XHttp
import com.xuexiang.xhttp2.cache.model.CacheMode import com.xuexiang.xhttp2.cache.model.CacheMode
import com.xuexiang.xhttp2.callback.SimpleCallBack import com.xuexiang.xhttp2.callback.SimpleCallBack
@ -39,8 +39,8 @@ class WeworkAgentUtils private constructor() {
logId: Long?, logId: Long?,
) { ) {
val accessToken: String? = MMKVUtils.getString("access_token_" + setting.agentID, "") var accessToken: String by SharedPreference("access_token_" + setting.agentID, "")
val expiresIn: Long = MMKVUtils.getLong("expires_in_" + setting.agentID, 0L) var expiresIn: Long by SharedPreference("expires_in_" + setting.agentID, 0L)
if (!TextUtils.isEmpty(accessToken) && expiresIn > System.currentTimeMillis()) { if (!TextUtils.isEmpty(accessToken) && expiresIn > System.currentTimeMillis()) {
return sendTextMsg(setting, msgInfo, rule, logId) return sendTextMsg(setting, msgInfo, rule, logId)
} }
@ -53,9 +53,7 @@ class WeworkAgentUtils private constructor() {
val request = XHttp.get(getTokenUrl) val request = XHttp.get(getTokenUrl)
//设置代理 //设置代理
if ((setting.proxyType == Proxy.Type.HTTP || setting.proxyType == Proxy.Type.SOCKS) if ((setting.proxyType == Proxy.Type.HTTP || setting.proxyType == Proxy.Type.SOCKS) && !TextUtils.isEmpty(setting.proxyHost) && !TextUtils.isEmpty(setting.proxyPort)) {
&& !TextUtils.isEmpty(setting.proxyHost) && !TextUtils.isEmpty(setting.proxyPort)
) {
//代理服务器的IP和端口号 //代理服务器的IP和端口号
Log.d(TAG, "proxyHost = ${setting.proxyHost}, proxyPort = ${setting.proxyPort}") Log.d(TAG, "proxyHost = ${setting.proxyHost}, proxyPort = ${setting.proxyPort}")
val proxyHost = if (NetworkUtils.isIP(setting.proxyHost)) setting.proxyHost else NetworkUtils.getDomainAddress(setting.proxyHost) val proxyHost = if (NetworkUtils.isIP(setting.proxyHost)) setting.proxyHost else NetworkUtils.getDomainAddress(setting.proxyHost)
@ -68,18 +66,14 @@ class WeworkAgentUtils private constructor() {
request.okproxy(Proxy(setting.proxyType, InetSocketAddress(proxyHost, proxyPort))) request.okproxy(Proxy(setting.proxyType, InetSocketAddress(proxyHost, proxyPort)))
//代理的鉴权账号密码 //代理的鉴权账号密码
if (setting.proxyAuthenticator == true if (setting.proxyAuthenticator == true && (!TextUtils.isEmpty(setting.proxyUsername) || !TextUtils.isEmpty(setting.proxyPassword))) {
&& (!TextUtils.isEmpty(setting.proxyUsername) || !TextUtils.isEmpty(setting.proxyPassword))
) {
Log.i(TAG, "proxyUsername = ${setting.proxyUsername}, proxyPassword = ${setting.proxyPassword}") Log.i(TAG, "proxyUsername = ${setting.proxyUsername}, proxyPassword = ${setting.proxyPassword}")
if (setting.proxyType == Proxy.Type.HTTP) { if (setting.proxyType == Proxy.Type.HTTP) {
request.okproxyAuthenticator { _: Route?, response: Response -> request.okproxyAuthenticator { _: Route?, response: Response ->
//设置代理服务器账号密码 //设置代理服务器账号密码
val credential = Credentials.basic(setting.proxyUsername.toString(), setting.proxyPassword.toString()) val credential = Credentials.basic(setting.proxyUsername.toString(), setting.proxyPassword.toString())
response.request().newBuilder() response.request().newBuilder().header("Proxy-Authorization", credential).build()
.header("Proxy-Authorization", credential)
.build()
} }
} else { } else {
Authenticator.setDefault(object : Authenticator() { Authenticator.setDefault(object : Authenticator() {
@ -91,12 +85,8 @@ class WeworkAgentUtils private constructor() {
} }
} }
request.keepJson(true) request.keepJson(true).ignoreHttpsCert().timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s
.ignoreHttpsCert() .cacheMode(CacheMode.NO_CACHE).timeStamp(true).execute(object : SimpleCallBack<String>() {
.timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s
.cacheMode(CacheMode.NO_CACHE)
.timeStamp(true)
.execute(object : SimpleCallBack<String>() {
override fun onError(e: ApiException) { override fun onError(e: ApiException) {
Log.e(TAG, e.detailMessage) Log.e(TAG, e.detailMessage)
@ -108,8 +98,8 @@ class WeworkAgentUtils private constructor() {
val resp = Gson().fromJson(response, WeworkAgentResult::class.java) val resp = Gson().fromJson(response, WeworkAgentResult::class.java)
if (resp?.errcode == 0L) { if (resp?.errcode == 0L) {
MMKVUtils.put("access_token_" + setting.agentID, resp.access_token) accessToken = resp.access_token.toString()
MMKVUtils.put("expires_in_" + setting.agentID, System.currentTimeMillis() + ((resp.expires_in ?: 7200) - 120) * 1000L) //提前2分钟过期 expiresIn = System.currentTimeMillis() + ((resp.expires_in ?: 7200) - 120) * 1000L //提前2分钟过期
sendTextMsg(setting, msgInfo, rule, logId) sendTextMsg(setting, msgInfo, rule, logId)
} else { } else {
SendUtils.updateLogs(logId, 0, String.format(getString(R.string.request_failed_tips), response)) SendUtils.updateLogs(logId, 0, String.format(getString(R.string.request_failed_tips), response))
@ -142,7 +132,8 @@ class WeworkAgentUtils private constructor() {
val textText: MutableMap<String, Any> = mutableMapOf() val textText: MutableMap<String, Any> = mutableMapOf()
textText["content"] = content textText["content"] = content
textMsgMap["text"] = textText textMsgMap["text"] = textText
val requestUrl = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=" + MMKVUtils.getString("access_token_" + setting.agentID, "") var accessToken: String by SharedPreference("access_token_" + setting.agentID, "")
val requestUrl = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=$accessToken"
Log.i(TAG, "requestUrl:$requestUrl") Log.i(TAG, "requestUrl:$requestUrl")
val requestMsg: String = Gson().toJson(textMsgMap) val requestMsg: String = Gson().toJson(textMsgMap)
Log.i(TAG, "requestMsg:$requestMsg") Log.i(TAG, "requestMsg:$requestMsg")
@ -150,9 +141,7 @@ class WeworkAgentUtils private constructor() {
val request = XHttp.post(requestUrl) val request = XHttp.post(requestUrl)
//设置代理 //设置代理
if ((setting.proxyType == Proxy.Type.HTTP || setting.proxyType == Proxy.Type.SOCKS) if ((setting.proxyType == Proxy.Type.HTTP || setting.proxyType == Proxy.Type.SOCKS) && !TextUtils.isEmpty(setting.proxyHost) && !TextUtils.isEmpty(setting.proxyPort)) {
&& !TextUtils.isEmpty(setting.proxyHost) && !TextUtils.isEmpty(setting.proxyPort)
) {
//代理服务器的IP和端口号 //代理服务器的IP和端口号
Log.d(TAG, "proxyHost = ${setting.proxyHost}, proxyPort = ${setting.proxyPort}") Log.d(TAG, "proxyHost = ${setting.proxyHost}, proxyPort = ${setting.proxyPort}")
val proxyHost = if (NetworkUtils.isIP(setting.proxyHost)) setting.proxyHost else NetworkUtils.getDomainAddress(setting.proxyHost) val proxyHost = if (NetworkUtils.isIP(setting.proxyHost)) setting.proxyHost else NetworkUtils.getDomainAddress(setting.proxyHost)
@ -165,18 +154,14 @@ class WeworkAgentUtils private constructor() {
request.okproxy(Proxy(setting.proxyType, InetSocketAddress(proxyHost, proxyPort))) request.okproxy(Proxy(setting.proxyType, InetSocketAddress(proxyHost, proxyPort)))
//代理的鉴权账号密码 //代理的鉴权账号密码
if (setting.proxyAuthenticator == true if (setting.proxyAuthenticator == true && (!TextUtils.isEmpty(setting.proxyUsername) || !TextUtils.isEmpty(setting.proxyPassword))) {
&& (!TextUtils.isEmpty(setting.proxyUsername) || !TextUtils.isEmpty(setting.proxyPassword))
) {
Log.i(TAG, "proxyUsername = ${setting.proxyUsername}, proxyPassword = ${setting.proxyPassword}") Log.i(TAG, "proxyUsername = ${setting.proxyUsername}, proxyPassword = ${setting.proxyPassword}")
if (setting.proxyType == Proxy.Type.HTTP) { if (setting.proxyType == Proxy.Type.HTTP) {
request.okproxyAuthenticator { _: Route?, response: Response -> request.okproxyAuthenticator { _: Route?, response: Response ->
//设置代理服务器账号密码 //设置代理服务器账号密码
val credential = Credentials.basic(setting.proxyUsername.toString(), setting.proxyPassword.toString()) val credential = Credentials.basic(setting.proxyUsername.toString(), setting.proxyPassword.toString())
response.request().newBuilder() response.request().newBuilder().header("Proxy-Authorization", credential).build()
.header("Proxy-Authorization", credential)
.build()
} }
} else { } else {
Authenticator.setDefault(object : Authenticator() { Authenticator.setDefault(object : Authenticator() {
@ -188,16 +173,11 @@ class WeworkAgentUtils private constructor() {
} }
} }
request.upJson(requestMsg) request.upJson(requestMsg).keepJson(true).ignoreHttpsCert().timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s
.keepJson(true) .cacheMode(CacheMode.NO_CACHE).retryCount(SettingUtils.requestRetryTimes) //超时重试的次数
.ignoreHttpsCert()
.timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s
.cacheMode(CacheMode.NO_CACHE)
.retryCount(SettingUtils.requestRetryTimes) //超时重试的次数
.retryDelay(SettingUtils.requestDelayTime) //超时重试的延迟时间 .retryDelay(SettingUtils.requestDelayTime) //超时重试的延迟时间
.retryIncreaseDelay(SettingUtils.requestDelayTime) //超时重试叠加延时 .retryIncreaseDelay(SettingUtils.requestDelayTime) //超时重试叠加延时
.timeStamp(true) .timeStamp(true).execute(object : SimpleCallBack<String>() {
.execute(object : SimpleCallBack<String>() {
override fun onError(e: ApiException) { override fun onError(e: ApiException) {
Log.e(TAG, e.detailMessage) Log.e(TAG, e.detailMessage)

@ -10,7 +10,7 @@ import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.core.http.api.ApiService.IGetService 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.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.MMKVUtils import com.idormy.sms.forwarder.utils.SharedPreference
import com.xuexiang.constant.TimeConstants 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
@ -175,11 +175,12 @@ class GuideTipsDialog(context: Context?, tips: List<TipInfo>) :
} }
fun setIsIgnoreTips(isIgnore: Boolean): Boolean { fun setIsIgnoreTips(isIgnore: Boolean): Boolean {
return MMKVUtils.put(KEY_IS_IGNORE_TIPS + AppUtils.getAppVersionCode(), isIgnore) this.isIgnoreTips = isIgnore
return true
} }
val isIgnoreTips: Boolean var isIgnoreTips: Boolean by SharedPreference(KEY_IS_IGNORE_TIPS + AppUtils.getAppVersionCode(), false)
get() = MMKVUtils.getBoolean(KEY_IS_IGNORE_TIPS + AppUtils.getAppVersionCode(), false)
} }
init { init {

@ -43,17 +43,15 @@ class SendWorker(
val dateFmt = SimpleDateFormat("yyyy-MM-dd") val dateFmt = SimpleDateFormat("yyyy-MM-dd")
val mTimeOption = DataProvider.timePeriodOption val mTimeOption = DataProvider.timePeriodOption
val periodStartStr = val periodStartStr = dateFmt.format(periodStartDay) + " " + mTimeOption[SettingUtils.silentPeriodStart] + ":00"
dateFmt.format(periodStartDay) + " " + mTimeOption[SettingUtils.silentPeriodStart] + ":00" val periodEndStr = dateFmt.format(periodStartEnd) + " " + mTimeOption[SettingUtils.silentPeriodEnd] + ":00"
val periodEndStr =
dateFmt.format(periodStartEnd) + " " + mTimeOption[SettingUtils.silentPeriodEnd] + ":00"
val timeFmt = SimpleDateFormat("yyyy-MM-dd HH:mm:ss") val timeFmt = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
val periodStart = timeFmt.parse(periodStartStr, ParsePosition(0)).time val periodStart = timeFmt.parse(periodStartStr, ParsePosition(0))?.time
val periodEnd = timeFmt.parse(periodEndStr, ParsePosition(0)).time val periodEnd = timeFmt.parse(periodEndStr, ParsePosition(0))?.time
val now = System.currentTimeMillis() val now = System.currentTimeMillis()
if (now in periodStart..periodEnd) { if (periodStart != null && periodEnd != null && now in periodStart..periodEnd) {
Log.e("SendWorker", "免打扰(禁用转发)时间段") Log.e("SendWorker", "免打扰(禁用转发)时间段")
return@withContext Result.failure(workDataOf("send" to "failed")) return@withContext Result.failure(workDataOf("send" to "failed"))
} }
@ -67,20 +65,17 @@ class SendWorker(
if (SettingUtils.duplicateMessagesLimits > 0) { if (SettingUtils.duplicateMessagesLimits > 0) {
val key = CipherUtils.md5(msgInfo.type + msgInfo.from + msgInfo.content) val key = CipherUtils.md5(msgInfo.type + msgInfo.from + msgInfo.content)
val timestamp: Long = System.currentTimeMillis() / 1000L val timestamp: Long = System.currentTimeMillis() / 1000L
if (HistoryUtils.containsKey(key)) { var timestampPrev: Long by HistoryUtils(key, timestamp)
val timestampPrev = HistoryUtils.getLong(key, timestamp) if (timestampPrev != timestamp && timestamp - timestampPrev <= SettingUtils.duplicateMessagesLimits) {
if (timestamp - timestampPrev <= SettingUtils.duplicateMessagesLimits) {
Log.e("SendWorker", "过滤重复消息机制") Log.e("SendWorker", "过滤重复消息机制")
return@withContext Result.failure(workDataOf("send" to "failed")) return@withContext Result.failure(workDataOf("send" to "failed"))
} }
} timestampPrev = timestamp
HistoryUtils.put(key, timestamp)
} }
//【注意】卡槽id-1=获取失败、0=卡槽1、1=卡槽2但是 Rule 表里存的是 SIM1/SIM2 //【注意】卡槽id-1=获取失败、0=卡槽1、1=卡槽2但是 Rule 表里存的是 SIM1/SIM2
val simSlot = "SIM" + (msgInfo.simSlot + 1) val simSlot = "SIM" + (msgInfo.simSlot + 1)
val ruleList: List<RuleAndSender> = val ruleList: List<RuleAndSender> = Core.rule.getRuleAndSender(msgInfo.type, 1, simSlot)
Core.rule.getRuleAndSender(msgInfo.type, 1, simSlot)
if (ruleList.isEmpty()) { if (ruleList.isEmpty()) {
return@withContext Result.failure(workDataOf("send" to "failed")) return@withContext Result.failure(workDataOf("send" to "failed"))
} }
@ -88,12 +83,7 @@ class SendWorker(
for (rule in ruleList) { for (rule in ruleList) {
if (!rule.rule.checkMsg(msgInfo)) continue if (!rule.rule.checkMsg(msgInfo)) continue
val log = Logs( val log = Logs(
0, 0, msgInfo.type, msgInfo.from, msgInfo.content, rule.rule.id, msgInfo.simInfo
msgInfo.type,
msgInfo.from,
msgInfo.content,
rule.rule.id,
msgInfo.simInfo
) )
val logId = Core.logs.insert(log) val logId = Core.logs.insert(log)
SendUtils.sendMsgSender(msgInfo, rule.rule, rule.sender, logId) SendUtils.sendMsgSender(msgInfo, rule.rule, rule.sender, logId)

@ -5,8 +5,8 @@ def build_versions = [:]
build_versions.version_code = 49 build_versions.version_code = 49
build_versions.version_name = "3.1.1" build_versions.version_name = "3.1.1"
build_versions.min_sdk = 19 build_versions.min_sdk = 19
build_versions.target_sdk = 33 build_versions.target_sdk = 32
build_versions.build_tools = "33.0.0" build_versions.build_tools = "33.0.1"
ext.build_versions = build_versions ext.build_versions = build_versions
ext.deps = [:] ext.deps = [:]

Loading…
Cancel
Save