优化:短信/通话转发获取卡槽信息机制(自行备注卡槽SubId对应)#228 #235

pull/286/head
pppscn 2 years ago
parent 442c29fd3d
commit 65e861ba62

@ -144,8 +144,8 @@ class App : Application(), CactusCallback, Configuration.Provider by Core {
runCatching { runCatching {
get.await() get.await()
Log.d("GlobalScope", "AppUtils.getAppsInfo() Done") Log.d("GlobalScope", "AppUtils.getAppsInfo() Done")
Log.d("GlobalScope", "UserAppList = $UserAppList") //Log.d("GlobalScope", "UserAppList = $UserAppList")
Log.d("GlobalScope", "SystemAppList = $SystemAppList") //Log.d("GlobalScope", "SystemAppList = $SystemAppList")
}.onFailure { }.onFailure {
//Log.e("GlobalScope", it.message.toString()) //Log.e("GlobalScope", it.message.toString())
} }

@ -20,7 +20,7 @@ import com.idormy.sms.forwarder.utils.DATABASE_NAME
@Database( @Database(
entities = [Frpc::class, Logs::class, Rule::class, Sender::class], entities = [Frpc::class, Logs::class, Rule::class, Sender::class],
version = 10, version = 11,
exportSchema = false exportSchema = false
) )
@TypeConverters(Converters::class) @TypeConverters(Converters::class)
@ -95,6 +95,7 @@ custom_domains = smsf.demo.com
MIGRATION_7_8, MIGRATION_7_8,
MIGRATION_8_9, MIGRATION_8_9,
MIGRATION_9_10, MIGRATION_9_10,
MIGRATION_10_11,
) )
/*if (BuildConfig.DEBUG) { /*if (BuildConfig.DEBUG) {
@ -277,6 +278,12 @@ CREATE TABLE "Sender" (
} }
} }
//转发日志添加SIM卡槽ID
private val MIGRATION_10_11 = object : Migration(10, 11) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("Alter table Logs add column sub_id INTEGER NOT NULL DEFAULT 0 ")
}
}
} }
} }

@ -1,61 +1,62 @@
package com.idormy.sms.forwarder.database.entity package com.idormy.sms.forwarder.database.entity
import android.os.Parcelable import android.os.Parcelable
import androidx.room.* import androidx.room.*
import com.idormy.sms.forwarder.R import com.idormy.sms.forwarder.R
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
import java.util.* import java.util.*
@Parcelize @Parcelize
@Entity( @Entity(
tableName = "Logs", tableName = "Logs",
foreignKeys = [ foreignKeys = [
ForeignKey( ForeignKey(
entity = Rule::class, entity = Rule::class,
parentColumns = ["id"], parentColumns = ["id"],
childColumns = ["rule_id"], childColumns = ["rule_id"],
onDelete = ForeignKey.CASCADE, //级联操作 onDelete = ForeignKey.CASCADE, //级联操作
onUpdate = ForeignKey.CASCADE //级联操作 onUpdate = ForeignKey.CASCADE //级联操作
) )
], ],
indices = [ indices = [
Index(value = ["id"], unique = true), Index(value = ["id"], unique = true),
Index(value = ["rule_id"]) Index(value = ["rule_id"])
] ]
) )
data class Logs( data class Logs(
@PrimaryKey(autoGenerate = true) @PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "id") var id: Long, @ColumnInfo(name = "id") var id: Long,
@ColumnInfo(name = "type", defaultValue = "sms") var type: String, @ColumnInfo(name = "type", defaultValue = "sms") var type: String,
@ColumnInfo(name = "from", defaultValue = "") var from: String, @ColumnInfo(name = "from", defaultValue = "") var from: String,
@ColumnInfo(name = "content", defaultValue = "") var content: String, @ColumnInfo(name = "content", defaultValue = "") var content: String,
@ColumnInfo(name = "rule_id", defaultValue = "0") var ruleId: Long = 0, @ColumnInfo(name = "rule_id", defaultValue = "0") var ruleId: Long = 0,
@ColumnInfo(name = "sim_info", defaultValue = "") var simInfo: String = "", @ColumnInfo(name = "sim_info", defaultValue = "") var simInfo: String = "",
@ColumnInfo(name = "forward_status", defaultValue = "1") var forwardStatus: Int = 1, @ColumnInfo(name = "sub_id", defaultValue = "0") var subId: Int = 0,
@ColumnInfo(name = "forward_response", defaultValue = "") var forwardResponse: String = "", @ColumnInfo(name = "forward_status", defaultValue = "1") var forwardStatus: Int = 1,
@ColumnInfo(name = "time") var time: Date = Date(), @ColumnInfo(name = "forward_response", defaultValue = "") var forwardResponse: String = "",
) : Parcelable { @ColumnInfo(name = "time") var time: Date = Date(),
) : Parcelable {
val simImageId: Int
get() { val simImageId: Int
if (simInfo.isNotEmpty()) { get() {
if (simInfo.replace("-", "").startsWith("SIM2")) { if (simInfo.isNotEmpty()) {
return R.drawable.ic_sim2 //mipmap if (simInfo.replace("-", "").startsWith("SIM2")) {
} else if (simInfo.replace("-", "").startsWith("SIM1")) { return R.drawable.ic_sim2 //mipmap
return R.drawable.ic_sim1 } else if (simInfo.replace("-", "").startsWith("SIM1")) {
} return R.drawable.ic_sim1
} }
return R.drawable.ic_sim }
} return R.drawable.ic_sim
}
val statusImageId: Int
get() { val statusImageId: Int
if (forwardStatus == 1) { get() {
return R.drawable.ic_round_warning if (forwardStatus == 1) {
} else if (forwardStatus == 2) { return R.drawable.ic_round_warning
return R.drawable.ic_round_check } else if (forwardStatus == 2) {
} return R.drawable.ic_round_check
return R.drawable.ic_round_cancel }
} return R.drawable.ic_round_cancel
}
} }

@ -1,55 +1,58 @@
package com.idormy.sms.forwarder.entity package com.idormy.sms.forwarder.entity
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName
import com.idormy.sms.forwarder.R import com.idormy.sms.forwarder.R
import java.io.Serializable import java.io.Serializable
data class CallInfo( data class CallInfo(
//姓名 //姓名
var name: String = "", var name: String = "",
//号码 //号码
var number: String = "", var number: String = "",
//获取通话日期 //获取通话日期
var dateLong: Long = 0L, var dateLong: Long = 0L,
//获取通话时长,值为多少秒 //获取通话时长,值为多少秒
var duration: Int = 0, var duration: Int = 0,
//通话类型1=呼入, 2=呼出, 3=未接, 4=未接提醒 //通话类型1=呼入, 2=呼出, 3=未接, 4=未接提醒
var type: Int = 1, var type: Int = 1,
//被呼号码 //被呼号码
@SerializedName("via_number") @SerializedName("via_number")
var viaNumber: String = "", var viaNumber: String = "",
//卡槽ID 0=Sim1, 1=Sim2, -1=获取失败 //卡槽ID 0=Sim1, 1=Sim2, -1=获取失败
@SerializedName("sim_id") @SerializedName("sim_id")
var simId: Int = -1, var simId: Int = -1,
) : Serializable { //卡槽主键
@SerializedName("sub_id")
val typeImageId: Int var subId: Int = 0,
get() { ) : Serializable {
return when (type) {
1 -> R.drawable.ic_phone_in val typeImageId: Int
2 -> R.drawable.ic_phone_out get() {
else -> R.drawable.ic_phone_missed return when (type) {
} 1 -> R.drawable.ic_phone_in
} 2 -> R.drawable.ic_phone_out
else -> R.drawable.ic_phone_missed
val simImageId: Int }
get() { }
return when (simId) {
0 -> R.drawable.ic_sim1 val simImageId: Int
1 -> R.drawable.ic_sim2 get() {
else -> R.drawable.ic_sim return when (simId) {
} 0 -> R.drawable.ic_sim1
} 1 -> R.drawable.ic_sim2
else -> R.drawable.ic_sim
override fun toString(): String { }
return "CallInfo{" + }
"name='" + name + '\'' +
", number='" + number + '\'' + override fun toString(): String {
", dateLong=" + dateLong + return "CallInfo{" +
", duration=" + duration + "name='" + name + '\'' +
", type=" + type + ", number='" + number + '\'' +
", viaNumber=" + viaNumber + ", dateLong=" + dateLong +
", simId=" + simId + ", duration=" + duration +
'}' ", type=" + type +
} ", viaNumber=" + viaNumber +
", simId=" + simId +
'}'
}
} }

@ -23,6 +23,7 @@ data class MsgInfo(
var date: Date, var date: Date,
var simInfo: String, var simInfo: String,
var simSlot: Int = -1, //卡槽id-1=获取失败、0=卡槽1、1=卡槽2 var simSlot: Int = -1, //卡槽id-1=获取失败、0=卡槽1、1=卡槽2
var subId: Int = 0, //卡槽主键
) : Serializable { ) : Serializable {
val titleForSend: String val titleForSend: String
@ -36,13 +37,14 @@ data class MsgInfo(
fun getTitleForSend(titleTemplate: String, regexReplace: String): String { fun getTitleForSend(titleTemplate: String, regexReplace: String): String {
var template = titleTemplate.replace("null", "") var template = titleTemplate.replace("null", "")
if (TextUtils.isEmpty(template)) template = getString(R.string.tag_from) if (TextUtils.isEmpty(template)) template = getString(R.string.tag_from)
val deviceMark = extraDeviceMark!!.trim() val deviceMark = extraDeviceMark.trim()
val versionName = AppUtils.getAppVersionName() val versionName = AppUtils.getAppVersionName()
val titleForSend: String = template.replace(getString(R.string.tag_from), from) val titleForSend: String = template.replace(getString(R.string.tag_from), from)
.replace(getString(R.string.tag_package_name), from) .replace(getString(R.string.tag_package_name), from)
.replace(getString(R.string.tag_sms), content) .replace(getString(R.string.tag_sms), content)
.replace(getString(R.string.tag_msg), content) .replace(getString(R.string.tag_msg), content)
.replace(getString(R.string.tag_card_slot), simInfo) .replace(getString(R.string.tag_card_slot), simInfo)
.replace(getString(R.string.tag_card_subid), subId.toString())
.replace(getString(R.string.tag_title), simInfo) .replace(getString(R.string.tag_title), simInfo)
.replace(getString(R.string.tag_receive_time), SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date)) .replace(getString(R.string.tag_receive_time), SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date))
.replace(getString(R.string.tag_device_name), deviceMark) .replace(getString(R.string.tag_device_name), deviceMark)
@ -60,10 +62,11 @@ data class MsgInfo(
@SuppressLint("SimpleDateFormat") @SuppressLint("SimpleDateFormat")
fun getContentForSend(ruleSmsTemplate: String, regexReplace: String): String { fun getContentForSend(ruleSmsTemplate: String, regexReplace: String): String {
val deviceMark = extraDeviceMark!!.trim() val deviceMark = extraDeviceMark.trim()
var customSmsTemplate: String = getString(R.string.tag_from).toString() + "\n" + var customSmsTemplate: String = getString(R.string.tag_from).toString() + "\n" +
getString(R.string.tag_sms) + "\n" + getString(R.string.tag_sms) + "\n" +
getString(R.string.tag_card_slot) + "\n" + getString(R.string.tag_card_slot) + "\n" +
"SubId" + getString(R.string.tag_card_subid) + "\n" +
getString(R.string.tag_receive_time) + "\n" + getString(R.string.tag_receive_time) + "\n" +
getString(R.string.tag_device_name) getString(R.string.tag_device_name)
@ -72,7 +75,7 @@ data class MsgInfo(
customSmsTemplate = ruleSmsTemplate.replace("null", "") customSmsTemplate = ruleSmsTemplate.replace("null", "")
} else { } else {
val switchSmsTemplate = enableSmsTemplate val switchSmsTemplate = enableSmsTemplate
val smsTemplate = smsTemplate.toString().trim() val smsTemplate = smsTemplate.trim()
if (switchSmsTemplate && smsTemplate.isNotEmpty()) { if (switchSmsTemplate && smsTemplate.isNotEmpty()) {
customSmsTemplate = smsTemplate.replace("null", "") customSmsTemplate = smsTemplate.replace("null", "")
} }
@ -83,6 +86,7 @@ data class MsgInfo(
.replace(getString(R.string.tag_sms), content) .replace(getString(R.string.tag_sms), content)
.replace(getString(R.string.tag_msg), content) .replace(getString(R.string.tag_msg), content)
.replace(getString(R.string.tag_card_slot), simInfo) .replace(getString(R.string.tag_card_slot), simInfo)
.replace(getString(R.string.tag_card_subid), subId.toString())
.replace(getString(R.string.tag_title), simInfo) .replace(getString(R.string.tag_title), simInfo)
.replace(getString(R.string.tag_receive_time), SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date)) .replace(getString(R.string.tag_receive_time), SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date))
.replace(getString(R.string.tag_device_name), deviceMark) .replace(getString(R.string.tag_device_name), deviceMark)

@ -1,37 +1,37 @@
package com.idormy.sms.forwarder.entity package com.idormy.sms.forwarder.entity
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName
import java.io.Serializable import java.io.Serializable
//SIM卡信息 //SIM卡信息
data class SimInfo( data class SimInfo(
//运营商信息:中国移动 中国联通 中国电信 //运营商信息:中国移动 中国联通 中国电信
@SerializedName("carrier_name") @SerializedName("carrier_name")
var mCarrierName: String? = null, var mCarrierName: String? = null,
//集成电路卡识别码即SIM卡卡号 //集成电路卡识别码即SIM卡卡号
@SerializedName("icc_id") @SerializedName("icc_id")
var mIccId: String? = null, var mIccId: String? = null,
//卡槽id-1=没插入、 0=卡槽1 、1=卡槽2 //卡槽id-1=没插入、 0=卡槽1 、1=卡槽2
@SerializedName("sim_slot_index") @SerializedName("sim_slot_index")
var mSimSlotIndex: Int = 0, var mSimSlotIndex: Int = 0,
//号码 //号码
@SerializedName("number") @SerializedName("number")
var mNumber: String? = null, var mNumber: String? = null,
//国家代码 //国家代码
@SerializedName("country_iso") @SerializedName("country_iso")
var mCountryIso: String? = null, var mCountryIso: String? = null,
//SIM的 Subscription Id (SIM插入顺序) //SIM的 Subscription Id (SIM插入顺序)
@SerializedName("subscription_id") @SerializedName("subscription_id")
var mSubscriptionId: Int = 0, var mSubscriptionId: Int = 0,
) : Serializable { ) : Serializable {
override fun toString(): String { override fun toString(): String {
return "SimInfo{" + return "SimInfo{" +
"mCarrierName=" + mCarrierName + "mCarrierName=" + mCarrierName +
", mIccId=" + mIccId + ", mIccId=" + mIccId +
", mSimSlotIndex=" + mSimSlotIndex + ", mSimSlotIndex=" + mSimSlotIndex +
", mNumber=" + mNumber + ", mNumber=" + mNumber +
", mCountryIso=" + mCountryIso + ", mCountryIso=" + mCountryIso +
", mSubscriptionId=" + mSubscriptionId + ", mSubscriptionId=" + mSubscriptionId +
'}' '}'
} }
} }

@ -1,33 +1,36 @@
package com.idormy.sms.forwarder.entity package com.idormy.sms.forwarder.entity
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName
import com.idormy.sms.forwarder.R import com.idormy.sms.forwarder.R
import java.io.Serializable import java.io.Serializable
data class SmsInfo( data class SmsInfo(
// 联系人姓名 // 联系人姓名
var name: String = "", var name: String = "",
// 联系人号码 // 联系人号码
var number: String = "", var number: String = "",
// 短信内容 // 短信内容
var content: String = "", var content: String = "",
// 短信时间 // 短信时间
var date: Long = 0L, var date: Long = 0L,
// 短信类型: 1=接收, 2=发送 // 短信类型: 1=接收, 2=发送
var type: Int = 1, var type: Int = 1,
// 卡槽ID 0=Sim1, 1=Sim2, -1=获取失败 // 卡槽ID 0=Sim1, 1=Sim2, -1=获取失败
@SerializedName("sim_id") @SerializedName("sim_id")
var simId: Int = -1, var simId: Int = -1,
) : Serializable { // 卡槽主键
@SerializedName("sub_id")
val typeImageId: Int = R.drawable.ic_sms var subId: Int = 0,
) : Serializable {
val simImageId: Int
get() { val typeImageId: Int = R.drawable.ic_sms
return when (simId) {
0 -> R.drawable.ic_sim1 val simImageId: Int
1 -> R.drawable.ic_sim2 get() {
else -> R.drawable.ic_sim return when (simId) {
} 0 -> R.drawable.ic_sim1
} 1 -> R.drawable.ic_sim2
} else -> R.drawable.ic_sim
}
}
}

@ -10,6 +10,7 @@ import android.net.Uri
import android.os.Build import android.os.Build
import android.provider.Settings import android.provider.Settings
import android.text.Editable import android.text.Editable
import android.text.TextUtils
import android.text.TextWatcher import android.text.TextWatcher
import android.util.Log import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
@ -128,6 +129,10 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
//设备备注 //设备备注
editAddExtraDeviceMark(binding!!.etExtraDeviceMark) editAddExtraDeviceMark(binding!!.etExtraDeviceMark)
//SIM1主键
editAddSubidSim1(binding!!.etSubidSim1)
//SIM2主键
editAddSubidSim2(binding!!.etSubidSim2)
//SIM1备注 //SIM1备注
editAddExtraSim1(binding!!.etExtraSim1) editAddExtraSim1(binding!!.etExtraSim1)
//SIM2备注 //SIM2备注
@ -200,6 +205,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
return return
} }
val simInfo: SimInfo? = App.SimInfoList[0] val simInfo: SimInfo? = App.SimInfoList[0]
binding!!.etSubidSim1.setText(simInfo?.mSubscriptionId.toString())
binding!!.etExtraSim1.setText(simInfo?.mCarrierName.toString() + "_" + simInfo?.mNumber.toString()) binding!!.etExtraSim1.setText(simInfo?.mCarrierName.toString() + "_" + simInfo?.mNumber.toString())
return return
} }
@ -222,6 +228,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
return return
} }
val simInfo: SimInfo? = App.SimInfoList[1] val simInfo: SimInfo? = App.SimInfoList[1]
binding!!.etSubidSim2.setText(simInfo?.mSubscriptionId.toString())
binding!!.etExtraSim2.setText(simInfo?.mCarrierName.toString() + "_" + simInfo?.mNumber.toString()) binding!!.etExtraSim2.setText(simInfo?.mCarrierName.toString() + "_" + simInfo?.mNumber.toString())
return return
} }
@ -729,6 +736,40 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
}) })
} }
//设置SIM1主键
private fun editAddSubidSim1(etSubidSim1: EditText) {
etSubidSim1.setText(SettingUtils.subidSim1.toString())
etSubidSim1.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
override fun afterTextChanged(s: Editable) {
val v = etSubidSim1.text.toString()
SettingUtils.subidSim1 = if (!TextUtils.isEmpty(v)) {
v.toInt()
} else {
1
}
}
})
}
//设置SIM2主键
private fun editAddSubidSim2(etSubidSim2: EditText) {
etSubidSim2.setText(SettingUtils.subidSim2.toString())
etSubidSim2.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
override fun afterTextChanged(s: Editable) {
val v = etSubidSim2.text.toString()
SettingUtils.subidSim2 = if (!TextUtils.isEmpty(v)) {
v.toInt()
} else {
2
}
}
})
}
//设置SIM1备注 //设置SIM1备注
private fun editAddExtraSim1(etExtraSim1: EditText) { private fun editAddExtraSim1(etExtraSim1: EditText) {
etExtraSim1.setText(SettingUtils.extraSim1) etExtraSim1.setText(SettingUtils.extraSim1)
@ -783,6 +824,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
${getString(R.string.tag_from)} ${getString(R.string.tag_from)}
${getString(R.string.tag_sms)} ${getString(R.string.tag_sms)}
${getString(R.string.tag_card_slot)} ${getString(R.string.tag_card_slot)}
SubId${getString(R.string.tag_card_subid)}
${getString(R.string.tag_receive_time)} ${getString(R.string.tag_receive_time)}
${getString(R.string.tag_device_name)} ${getString(R.string.tag_device_name)}
""".trimIndent() """.trimIndent()

@ -51,79 +51,82 @@ class PhoneStateReceiver : BroadcastReceiver() {
TelephonyManager.EXTRA_STATE_RINGING -> state = TelephonyManager.CALL_STATE_RINGING TelephonyManager.EXTRA_STATE_RINGING -> state = TelephonyManager.CALL_STATE_RINGING
} }
Log.d(TAG, "state=$state, number=$number") Log.d(TAG, "state=$state, number=$number")
var callSavedNumber: String by SharedPreference("CALL_SAVED_NUMBER", "")
onCallStateChanged(context, state, number) if (!TextUtils.isEmpty(number)) callSavedNumber = number.toString()
} catch (e: Exception) { //Incoming call- goes from IDLE to RINGING when it rings, to OFFHOOK when it's answered, to IDLE when its hung up
Log.e(TAG, e.message.toString()) //Outgoing call- goes from IDLE to OFFHOOK when it dials out, to IDLE when hung up
} var lastState: Int by SharedPreference("CALL_LAST_STATE", TelephonyManager.CALL_STATE_IDLE)
} if (lastState == state || (state == TelephonyManager.CALL_STATE_RINGING && number == null)) {
//No change, debounce extras
//Incoming call- goes from IDLE to RINGING when it rings, to OFFHOOK when it's answered, to IDLE when its hung up Log.d(TAG, "状态没变,防止抖动")
//Outgoing call- goes from IDLE to OFFHOOK when it dials out, to IDLE when hung up return
private fun onCallStateChanged(context: Context, state: Int, number: String?) {
var lastState: Int by SharedPreference("CALL_LAST_STATE", TelephonyManager.CALL_STATE_IDLE)
if (lastState == state || (state == TelephonyManager.CALL_STATE_RINGING && number == null)) {
//No change, debounce extras
return
}
lastState = state
var callIsIncoming: Boolean by SharedPreference("CALL_IS_INCOMING", false)
var callSavedNumber: String by SharedPreference("CALL_SAVED_NUMBER", "")
when (state) {
TelephonyManager.CALL_STATE_RINGING -> {
Log.d(TAG, "来电响铃")
callIsIncoming = true
callSavedNumber = number.toString()
//来电提醒
if (!TextUtils.isEmpty(number) && SettingUtils.enableCallType4) {
val contacts = PhoneUtils.getContactByNumber(number)
val contactName = if (contacts.isNotEmpty()) contacts[0].name else getString(R.string.unknown_number)
val sb = StringBuilder()
sb.append(getString(R.string.linkman)).append(contactName).append("\n")
sb.append(getString(R.string.mandatory_type))
sb.append(getString(R.string.incoming_call))
val msgInfo = MsgInfo("call", number.toString(), sb.toString(), Date(), "", -1)
val request = OneTimeWorkRequestBuilder<SendWorker>().setInputData(
workDataOf(
Worker.sendMsgInfo to Gson().toJson(msgInfo)
)
).build()
WorkManager.getInstance(context).enqueue(request)
}
} }
TelephonyManager.CALL_STATE_OFFHOOK ->
//Transition of ringing->offhook are pickups of incoming calls. Nothing done on them lastState = state
callIsIncoming = when { var callIsIncoming: Boolean by SharedPreference("CALL_IS_INCOMING", false)
lastState != TelephonyManager.CALL_STATE_RINGING -> { Log.d(TAG, "lastState=$lastState, callIsIncoming=$callIsIncoming, callSavedNumber=$callSavedNumber")
Log.d(TAG, "去电接通")
false when (state) {
} TelephonyManager.CALL_STATE_RINGING -> {
else -> { Log.d(TAG, "电话响铃")
Log.d(TAG, "来电接通") callIsIncoming = true
true
//来电提醒
if (!TextUtils.isEmpty(number) && SettingUtils.enableCallType4) {
val contacts = PhoneUtils.getContactByNumber(number)
val contactName = if (contacts.isNotEmpty()) contacts[0].name else getString(R.string.unknown_number)
val sb = StringBuilder()
sb.append(getString(R.string.linkman)).append(contactName).append("\n")
sb.append(getString(R.string.mandatory_type))
sb.append(getString(R.string.incoming_call))
val msgInfo = MsgInfo("call", number.toString(), sb.toString(), Date(), "", -1)
val request = OneTimeWorkRequestBuilder<SendWorker>().setInputData(
workDataOf(
Worker.sendMsgInfo to Gson().toJson(msgInfo)
)
).build()
WorkManager.getInstance(context).enqueue(request)
} }
} }
TelephonyManager.CALL_STATE_IDLE -> TelephonyManager.CALL_STATE_OFFHOOK ->
//Went to idle- this is the end of a call. What type depends on previous state(s) //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, "去电接通")
sendReceiveCallMsg(context, 3, callSavedNumber) if (!TextUtils.isEmpty(number)) callSavedNumber = number.toString()
false
}
else -> {
Log.d(TAG, "来电接通")
true
}
} }
callIsIncoming -> { TelephonyManager.CALL_STATE_IDLE ->
Log.d(TAG, "来电挂机") //Went to idle- this is the end of a call. What type depends on previous state(s)
sendReceiveCallMsg(context, 1, callSavedNumber) when {
lastState == TelephonyManager.CALL_STATE_RINGING -> {
Log.d(TAG, "来电未接")
sendReceiveCallMsg(context, 3, callSavedNumber)
callSavedNumber = ""
}
callIsIncoming -> {
Log.d(TAG, "来电挂机")
sendReceiveCallMsg(context, 1, callSavedNumber)
callSavedNumber = ""
}
else -> {
Log.d(TAG, "去电挂机")
sendReceiveCallMsg(context, 2, callSavedNumber)
callSavedNumber = ""
}
} }
else -> { }
Log.d(TAG, "去电挂机")
sendReceiveCallMsg(context, 2, callSavedNumber) } catch (e: Exception) {
} Log.e(TAG, e.message.toString())
}
} }
} }
@ -158,7 +161,7 @@ class PhoneStateReceiver : BroadcastReceiver() {
} }
val msgInfo = MsgInfo( val msgInfo = MsgInfo(
"call", callInfo.number, PhoneUtils.getCallMsg(callInfo), Date(), simInfo, simSlot "call", callInfo.number, PhoneUtils.getCallMsg(callInfo), Date(), simInfo, simSlot, callInfo.subId
) )
val request = OneTimeWorkRequestBuilder<SendWorker>().setInputData( val request = OneTimeWorkRequestBuilder<SendWorker>().setInputData(
workDataOf( workDataOf(

@ -1,95 +1,96 @@
package com.idormy.sms.forwarder.receiver 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.provider.Telephony import android.provider.Telephony
import android.util.Log import android.util.Log
import androidx.work.OneTimeWorkRequestBuilder import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager import androidx.work.WorkManager
import androidx.work.workDataOf import androidx.work.workDataOf
import com.google.gson.Gson import com.google.gson.Gson
import com.idormy.sms.forwarder.App import com.idormy.sms.forwarder.App
import com.idormy.sms.forwarder.entity.MsgInfo import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.utils.PhoneUtils import com.idormy.sms.forwarder.utils.PhoneUtils
import com.idormy.sms.forwarder.utils.SettingUtils import com.idormy.sms.forwarder.utils.SettingUtils
import com.idormy.sms.forwarder.utils.Worker import com.idormy.sms.forwarder.utils.Worker
import com.idormy.sms.forwarder.workers.SendWorker import com.idormy.sms.forwarder.workers.SendWorker
import java.util.* import java.util.*
//短信广播 //短信广播
@Suppress("PrivatePropertyName", "DEPRECATION") @Suppress("PrivatePropertyName", "DEPRECATION")
class SmsReceiver : BroadcastReceiver() { class SmsReceiver : BroadcastReceiver() {
private var TAG = "SmsReceiver" private var TAG = "SmsReceiver"
override fun onReceive(context: Context, intent: Intent) { override fun onReceive(context: Context, intent: Intent) {
try { try {
//纯客户端模式 //纯客户端模式
if (SettingUtils.enablePureClientMode) return if (SettingUtils.enablePureClientMode) return
//总开关 //总开关
if (!SettingUtils.enableSms) return if (!SettingUtils.enableSms) return
//过滤广播 //过滤广播
if (intent.action != Telephony.Sms.Intents.SMS_RECEIVED_ACTION && intent.action != Telephony.Sms.Intents.SMS_DELIVER_ACTION) return if (intent.action != Telephony.Sms.Intents.SMS_RECEIVED_ACTION && intent.action != Telephony.Sms.Intents.SMS_DELIVER_ACTION) return
//权限判断 var from = ""
//if (ActivityCompat.checkSelfPermission(context, Manifest.permission.RECEIVE_SMS) != PackageManager.PERMISSION_GRANTED) return var content = ""
for (smsMessage in Telephony.Sms.Intents.getMessagesFromIntent(intent)) {
var from = "" from = smsMessage.displayOriginatingAddress
var content = "" content += smsMessage.messageBody
for (smsMessage in Telephony.Sms.Intents.getMessagesFromIntent(intent)) { }
from = smsMessage.displayOriginatingAddress Log.d(TAG, "from = $from")
content += smsMessage.messageBody Log.d(TAG, "content = $content")
}
Log.d(TAG, "from = $from") //TODO准确获取卡槽信息目前测试结果只有 subscription 相对靠谱
Log.d(TAG, "content = $content") val slot = intent.extras?.getInt("slot") ?: -1
val simId = intent.extras?.getInt("simId") ?: slot
//获取卡槽信息 val subscription = intent.extras?.getInt("subscription") ?: simId
if (App.SimInfoList.isEmpty()) { Log.d(TAG, "slot = $slot, simId = $simId, subscription = $subscription")
App.SimInfoList = PhoneUtils.getSimMultiInfo()
} //卡槽id-1=获取失败、0=卡槽1、1=卡槽2
Log.e(TAG, "SimInfoList = " + App.SimInfoList.toString()) var simSlot = -1
//以自定义卡槽信息优先
//TODO准确获取卡槽信息目前测试结果只有 subscription 相对靠谱 if (SettingUtils.subidSim1 > 0 || SettingUtils.subidSim2 > 0) {
val slot = intent.extras?.getInt("slot") ?: -1 simSlot = if (subscription == SettingUtils.subidSim1) 0 else 1
val simId = intent.extras?.getInt("simId") ?: slot } else {
val subscription = intent.extras?.getInt("subscription") ?: simId //获取卡槽信息
Log.d(TAG, "slot = $slot, simId = $simId, subscription = $subscription") if (App.SimInfoList.isEmpty()) {
App.SimInfoList = PhoneUtils.getSimMultiInfo()
//卡槽id-1=获取失败、0=卡槽1、1=卡槽2 }
var simSlot = -1 Log.d(TAG, "SimInfoList = " + App.SimInfoList.toString())
if (App.SimInfoList.isNotEmpty()) {
for (simInfo in App.SimInfoList.values) { if (App.SimInfoList.isNotEmpty()) {
if (simInfo.mSubscriptionId == subscription) { for (simInfo in App.SimInfoList.values) {
simSlot = simInfo.mSimSlotIndex if (simInfo.mSubscriptionId == subscription) {
break simSlot = simInfo.mSimSlotIndex
} break
} }
} }
//获取卡槽信息 }
val simInfo = when (simSlot) { }
0 -> "SIM1_" + SettingUtils.extraSim1
1 -> "SIM2_" + SettingUtils.extraSim2 //获取卡槽信息
else -> "" val simInfo = when (simSlot) {
} 0 -> "SIM1_" + SettingUtils.extraSim1
1 -> "SIM2_" + SettingUtils.extraSim2
val msgInfo = MsgInfo("sms", from, content, Date(), simInfo, simSlot) else -> ""
Log.d(TAG, "msgInfo = $msgInfo") }
val request = OneTimeWorkRequestBuilder<SendWorker>() val msgInfo = MsgInfo("sms", from, content, Date(), simInfo, simSlot, subscription)
.setInputData( Log.d(TAG, "msgInfo = $msgInfo")
workDataOf(
Worker.sendMsgInfo to Gson().toJson(msgInfo) val request = OneTimeWorkRequestBuilder<SendWorker>().setInputData(
) workDataOf(
) Worker.sendMsgInfo to Gson().toJson(msgInfo)
.build() )
WorkManager.getInstance(context).enqueue(request) ).build()
WorkManager.getInstance(context).enqueue(request)
} catch (e: Exception) {
Log.e(TAG, "Parsing SMS failed: " + e.message.toString()) } catch (e: Exception) {
} Log.e(TAG, "Parsing SMS failed: " + e.message.toString())
} }
}
} }

@ -1,396 +1,398 @@
@file:Suppress("unused") @file:Suppress("unused")
package com.idormy.sms.forwarder.utils package com.idormy.sms.forwarder.utils
import com.idormy.sms.forwarder.R import com.idormy.sms.forwarder.R
import com.xuexiang.xpage.enums.CoreAnim import com.xuexiang.xpage.enums.CoreAnim
import com.xuexiang.xpage.model.PageInfo import com.xuexiang.xpage.model.PageInfo
import com.xuexiang.xui.utils.ResUtils.getString import com.xuexiang.xui.utils.ResUtils.getString
object Worker { object Worker {
const val sendMsgInfo = "send_msg_info" const val sendMsgInfo = "send_msg_info"
const val sendLogId = "send_log_id" const val sendLogId = "send_log_id"
const val sendSbnId = "send_sbn_id" const val sendSbnId = "send_sbn_id"
const val updateLogs = "update_logs" const val updateLogs = "update_logs"
} }
//初始化相关 //初始化相关
const val IS_FIRST_OPEN_KEY = "is_first_open_key" const val IS_FIRST_OPEN_KEY = "is_first_open_key"
const val IS_AGREE_PRIVACY_KEY = "is_agree_privacy_key" const val IS_AGREE_PRIVACY_KEY = "is_agree_privacy_key"
//数据库 //数据库
const val DATABASE_NAME = "sms_forwarder.db" const val DATABASE_NAME = "sms_forwarder.db"
const val PACKAGE_NAME = "com.idormy.sms.forwarder" const val PACKAGE_NAME = "com.idormy.sms.forwarder"
//通用设置 //通用设置
const val SP_ENABLE_SMS = "enable_sms" const val SP_ENABLE_SMS = "enable_sms"
const val SP_ENABLE_PHONE = "enable_phone" const val SP_ENABLE_PHONE = "enable_phone"
const val SP_ENABLE_CALL_TYPE_1 = "enable_call_type_1" const val SP_ENABLE_CALL_TYPE_1 = "enable_call_type_1"
const val SP_ENABLE_CALL_TYPE_2 = "enable_call_type_2" const val SP_ENABLE_CALL_TYPE_2 = "enable_call_type_2"
const val SP_ENABLE_CALL_TYPE_3 = "enable_call_type_3" const val SP_ENABLE_CALL_TYPE_3 = "enable_call_type_3"
const val SP_ENABLE_CALL_TYPE_4 = "enable_call_type_4" const val SP_ENABLE_CALL_TYPE_4 = "enable_call_type_4"
const val SP_ENABLE_APP_NOTIFY = "enable_app_notify" const val SP_ENABLE_APP_NOTIFY = "enable_app_notify"
const val SP_ENABLE_CANCEL_APP_NOTIFY = "enable_cancel_app_notify" const val SP_ENABLE_CANCEL_APP_NOTIFY = "enable_cancel_app_notify"
const val SP_ENABLE_NOT_USER_PRESENT = "enable_not_user_present" const val SP_ENABLE_NOT_USER_PRESENT = "enable_not_user_present"
const val ENABLE_LOAD_APP_LIST = "enable_load_app_list" const val ENABLE_LOAD_APP_LIST = "enable_load_app_list"
const val ENABLE_LOAD_USER_APP_LIST = "enable_load_user_app_list" const val ENABLE_LOAD_USER_APP_LIST = "enable_load_user_app_list"
const val ENABLE_LOAD_SYSTEM_APP_LIST = "enable_load_system_app_list" const val ENABLE_LOAD_SYSTEM_APP_LIST = "enable_load_system_app_list"
const val SP_DUPLICATE_MESSAGES_LIMITS = "duplicate_messages_limits" const val SP_DUPLICATE_MESSAGES_LIMITS = "duplicate_messages_limits"
const val SP_SILENT_PERIOD_START = "silent_period_start" const val SP_SILENT_PERIOD_START = "silent_period_start"
const val SP_SILENT_PERIOD_END = "silent_period_end" const val SP_SILENT_PERIOD_END = "silent_period_end"
const val SP_AUTO_CLEAN_LOGS_DAYS = "auto_clean_logs_days" const val SP_AUTO_CLEAN_LOGS_DAYS = "auto_clean_logs_days"
const val SP_BATTERY_RECEIVER = "enable_battery_receiver" const val SP_BATTERY_RECEIVER = "enable_battery_receiver"
const val SP_BATTERY_STATUS = "battery_status" const val SP_BATTERY_STATUS = "battery_status"
const val SP_BATTERY_LEVEL_MIN = "battery_level_min" const val SP_BATTERY_LEVEL_MIN = "battery_level_min"
const val SP_BATTERY_LEVEL_MAX = "battery_level_max" const val SP_BATTERY_LEVEL_MAX = "battery_level_max"
const val SP_BATTERY_LEVEL_ONCE = "battery_level_once" const val SP_BATTERY_LEVEL_ONCE = "battery_level_once"
const val SP_BATTERY_LEVEL_CURRENT = "battery_level_current" const val SP_BATTERY_LEVEL_CURRENT = "battery_level_current"
const val SP_BATTERY_CRON = "enable_battery_cron" const val SP_BATTERY_CRON = "enable_battery_cron"
const val SP_BATTERY_CRON_START_TIME = "battery_cron_start_time" const val SP_BATTERY_CRON_START_TIME = "battery_cron_start_time"
const val SP_BATTERY_CRON_INTERVAL = "battery_cron_interval" const val SP_BATTERY_CRON_INTERVAL = "battery_cron_interval"
const val SP_ENABLE_EXCLUDE_FROM_RECENTS = "enable_exclude_from_recents" const val SP_ENABLE_EXCLUDE_FROM_RECENTS = "enable_exclude_from_recents"
const val SP_ENABLE_PLAY_SILENCE_MUSIC = "enable_play_silence_music" const val SP_ENABLE_PLAY_SILENCE_MUSIC = "enable_play_silence_music"
const val SP_ENABLE_ONE_PIXEL_ACTIVITY = "enable_one_pixel_activity" const val SP_ENABLE_ONE_PIXEL_ACTIVITY = "enable_one_pixel_activity"
const val SP_REQUEST_RETRY_TIMES = "request_retry_times" const val SP_REQUEST_RETRY_TIMES = "request_retry_times"
const val SP_REQUEST_DELAY_TIME = "request_delay_time" const val SP_REQUEST_DELAY_TIME = "request_delay_time"
const val SP_REQUEST_TIMEOUT = "request_timeout" const val SP_REQUEST_TIMEOUT = "request_timeout"
const val SP_NOTIFY_CONTENT = "notify_content" const val SP_NOTIFY_CONTENT = "notify_content"
const val SP_EXTRA_DEVICE_MARK = "extra_device_mark" const val SP_EXTRA_DEVICE_MARK = "extra_device_mark"
const val SP_EXTRA_SIM1 = "extra_sim1" const val SP_SUBID_SIM1 = "subid_sim1"
const val SP_EXTRA_SIM2 = "extra_sim2" const val SP_SUBID_SIM2 = "subid_sim2"
const val SP_ENABLE_SMS_TEMPLATE = "enable_sms_template" const val SP_EXTRA_SIM1 = "extra_sim1"
const val SP_SMS_TEMPLATE = "sms_template" const val SP_EXTRA_SIM2 = "extra_sim2"
const val SP_ENABLE_SMS_TEMPLATE = "enable_sms_template"
const val SP_ENABLE_HELP_TIP = "enable_help_tip" const val SP_SMS_TEMPLATE = "sms_template"
const val SP_PURE_CLIENT_MODE = "enable_pure_client_mode"
const val SP_ENABLE_HELP_TIP = "enable_help_tip"
const val SP_ENABLE_CACTUS = "enable_cactus" const val SP_PURE_CLIENT_MODE = "enable_pure_client_mode"
const val CACTUS_TIMER = "cactus_timer"
const val CACTUS_LAST_TIMER = "cactus_last_timer" const val SP_ENABLE_CACTUS = "enable_cactus"
const val CACTUS_DATE = "cactus_date" const val CACTUS_TIMER = "cactus_timer"
const val CACTUS_END_DATE = "cactus_end_date" const val CACTUS_LAST_TIMER = "cactus_last_timer"
const val CACTUS_DATE = "cactus_date"
//OkHttp 请求超时时间 const val CACTUS_END_DATE = "cactus_end_date"
const val REQUEST_TIMEOUT_SECONDS = 5
//OkHttp 请求超时时间
//规则相关 const val REQUEST_TIMEOUT_SECONDS = 5
const val STATUS_ON = 1
const val STATUS_OFF = 0 //规则相关
const val FILED_TRANSPOND_ALL = "transpond_all" const val STATUS_ON = 1
const val FILED_PHONE_NUM = "phone_num" const val STATUS_OFF = 0
const val FILED_PACKAGE_NAME = "package_name" const val FILED_TRANSPOND_ALL = "transpond_all"
const val FILED_MSG_CONTENT = "msg_content" const val FILED_PHONE_NUM = "phone_num"
const val FILED_INFORM_CONTENT = "inform_content" const val FILED_PACKAGE_NAME = "package_name"
const val FILED_MULTI_MATCH = "multi_match" const val FILED_MSG_CONTENT = "msg_content"
const val CHECK_IS = "is" const val FILED_INFORM_CONTENT = "inform_content"
const val CHECK_CONTAIN = "contain" const val FILED_MULTI_MATCH = "multi_match"
const val CHECK_NOT_CONTAIN = "notcontain" const val CHECK_IS = "is"
const val CHECK_START_WITH = "startwith" const val CHECK_CONTAIN = "contain"
const val CHECK_END_WITH = "endwith" const val CHECK_NOT_CONTAIN = "notcontain"
const val CHECK_NOT_IS = "notis" const val CHECK_START_WITH = "startwith"
const val CHECK_REGEX = "regex" const val CHECK_END_WITH = "endwith"
const val CHECK_SIM_SLOT_ALL = "ALL" const val CHECK_NOT_IS = "notis"
const val CHECK_SIM_SLOT_1 = "SIM1" const val CHECK_REGEX = "regex"
const val CHECK_SIM_SLOT_2 = "SIM2" const val CHECK_SIM_SLOT_ALL = "ALL"
val TYPE_MAP = object : HashMap<String, String>() { const val CHECK_SIM_SLOT_1 = "SIM1"
init { const val CHECK_SIM_SLOT_2 = "SIM2"
put("sms", getString(R.string.rule_sms)) val TYPE_MAP = object : HashMap<String, String>() {
put("call", getString(R.string.rule_call)) init {
put("app", getString(R.string.rule_app)) put("sms", getString(R.string.rule_sms))
} put("call", getString(R.string.rule_call))
} put("app", getString(R.string.rule_app))
val FILED_MAP = object : HashMap<String, String>() { }
init { }
put("transpond_all", getString(R.string.rule_transpond_all)) val FILED_MAP = object : HashMap<String, String>() {
put("phone_num", getString(R.string.rule_phone_num)) init {
put("msg_content", getString(R.string.rule_msg_content)) put("transpond_all", getString(R.string.rule_transpond_all))
put("multi_match", getString(R.string.rule_multi_match)) put("phone_num", getString(R.string.rule_phone_num))
put("package_name", getString(R.string.rule_package_name)) put("msg_content", getString(R.string.rule_msg_content))
put("inform_content", getString(R.string.rule_inform_content)) put("multi_match", getString(R.string.rule_multi_match))
} put("package_name", getString(R.string.rule_package_name))
} put("inform_content", getString(R.string.rule_inform_content))
val CHECK_MAP = object : HashMap<String, String>() { }
init { }
put("is", getString(R.string.rule_is)) val CHECK_MAP = object : HashMap<String, String>() {
put("notis", getString(R.string.rule_notis)) init {
put("contain", getString(R.string.rule_contain)) put("is", getString(R.string.rule_is))
put("startwith", getString(R.string.rule_startwith)) put("notis", getString(R.string.rule_notis))
put("endwith", getString(R.string.rule_endwith)) put("contain", getString(R.string.rule_contain))
put("notcontain", getString(R.string.rule_notcontain)) put("startwith", getString(R.string.rule_startwith))
put("regex", getString(R.string.rule_regex)) put("endwith", getString(R.string.rule_endwith))
} put("notcontain", getString(R.string.rule_notcontain))
} put("regex", getString(R.string.rule_regex))
val SIM_SLOT_MAP = object : HashMap<String, String>() { }
init { }
put("ALL", getString(R.string.rule_all)) val SIM_SLOT_MAP = object : HashMap<String, String>() {
put("SIM1", "SIM1") init {
put("SIM2", "SIM2") put("ALL", getString(R.string.rule_all))
} put("SIM1", "SIM1")
} put("SIM2", "SIM2")
val FORWARD_STATUS_MAP = object : HashMap<Int, String>() { }
init { }
put(0, getString(R.string.failed)) val FORWARD_STATUS_MAP = object : HashMap<Int, String>() {
put(1, getString(R.string.processing)) init {
put(2, getString(R.string.success)) put(0, getString(R.string.failed))
} put(1, getString(R.string.processing))
} put(2, getString(R.string.success))
val BARK_LEVEL_MAP = mapOf( }
"active" to getString(R.string.bark_level_active), }
"timeSensitive" to getString(R.string.bark_level_timeSensitive), val BARK_LEVEL_MAP = mapOf(
"passive" to getString(R.string.bark_level_passive) "active" to getString(R.string.bark_level_active),
) "timeSensitive" to getString(R.string.bark_level_timeSensitive),
"passive" to getString(R.string.bark_level_passive)
//发送通道 )
const val TYPE_DINGTALK_GROUP_ROBOT = 0
const val TYPE_EMAIL = 1 //发送通道
const val TYPE_BARK = 2 const val TYPE_DINGTALK_GROUP_ROBOT = 0
const val TYPE_WEBHOOK = 3 const val TYPE_EMAIL = 1
const val TYPE_WEWORK_ROBOT = 4 const val TYPE_BARK = 2
const val TYPE_WEWORK_AGENT = 5 const val TYPE_WEBHOOK = 3
const val TYPE_SERVERCHAN = 6 const val TYPE_WEWORK_ROBOT = 4
const val TYPE_TELEGRAM = 7 const val TYPE_WEWORK_AGENT = 5
const val TYPE_SMS = 8 const val TYPE_SERVERCHAN = 6
const val TYPE_FEISHU = 9 const val TYPE_TELEGRAM = 7
const val TYPE_PUSHPLUS = 10 const val TYPE_SMS = 8
const val TYPE_GOTIFY = 11 const val TYPE_FEISHU = 9
const val TYPE_DINGTALK_INNER_ROBOT = 12 const val TYPE_PUSHPLUS = 10
const val TYPE_FEISHU_APP = 13 const val TYPE_GOTIFY = 11
var SENDER_FRAGMENT_LIST = listOf( const val TYPE_DINGTALK_INNER_ROBOT = 12
PageInfo( const val TYPE_FEISHU_APP = 13
getString(R.string.dingtalk_robot), var SENDER_FRAGMENT_LIST = listOf(
"com.idormy.sms.forwarder.fragment.senders.DingtalkGroupRobotFragment", PageInfo(
"{\"\":\"\"}", getString(R.string.dingtalk_robot),
CoreAnim.slide, "com.idormy.sms.forwarder.fragment.senders.DingtalkGroupRobotFragment",
R.drawable.icon_dingtalk "{\"\":\"\"}",
), CoreAnim.slide,
PageInfo( R.drawable.icon_dingtalk
getString(R.string.email), ),
"com.idormy.sms.forwarder.fragment.senders.EmailFragment", PageInfo(
"{\"\":\"\"}", getString(R.string.email),
CoreAnim.slide, "com.idormy.sms.forwarder.fragment.senders.EmailFragment",
R.drawable.icon_email "{\"\":\"\"}",
), CoreAnim.slide,
PageInfo( R.drawable.icon_email
getString(R.string.bark), ),
"com.idormy.sms.forwarder.fragment.senders.BarkFragment", PageInfo(
"{\"\":\"\"}", getString(R.string.bark),
CoreAnim.slide, "com.idormy.sms.forwarder.fragment.senders.BarkFragment",
R.drawable.icon_bark "{\"\":\"\"}",
), CoreAnim.slide,
PageInfo( R.drawable.icon_bark
getString(R.string.webhook), ),
"com.idormy.sms.forwarder.fragment.senders.WebhookFragment", PageInfo(
"{\"\":\"\"}", getString(R.string.webhook),
CoreAnim.slide, "com.idormy.sms.forwarder.fragment.senders.WebhookFragment",
R.drawable.icon_webhook "{\"\":\"\"}",
), CoreAnim.slide,
PageInfo( R.drawable.icon_webhook
getString(R.string.wework_robot), ),
"com.idormy.sms.forwarder.fragment.senders.WeworkRobotFragment", PageInfo(
"{\"\":\"\"}", getString(R.string.wework_robot),
CoreAnim.slide, "com.idormy.sms.forwarder.fragment.senders.WeworkRobotFragment",
R.drawable.icon_wework_robot "{\"\":\"\"}",
), CoreAnim.slide,
PageInfo( R.drawable.icon_wework_robot
getString(R.string.wework_agent), ),
"com.idormy.sms.forwarder.fragment.senders.WeworkAgentFragment", PageInfo(
"{\"\":\"\"}", getString(R.string.wework_agent),
CoreAnim.slide, "com.idormy.sms.forwarder.fragment.senders.WeworkAgentFragment",
R.drawable.icon_wework_agent "{\"\":\"\"}",
), CoreAnim.slide,
PageInfo( R.drawable.icon_wework_agent
getString(R.string.server_chan), ),
"com.idormy.sms.forwarder.fragment.senders.ServerchanFragment", PageInfo(
"{\"\":\"\"}", getString(R.string.server_chan),
CoreAnim.slide, "com.idormy.sms.forwarder.fragment.senders.ServerchanFragment",
R.drawable.icon_serverchan "{\"\":\"\"}",
), CoreAnim.slide,
PageInfo( R.drawable.icon_serverchan
getString(R.string.telegram), ),
"com.idormy.sms.forwarder.fragment.senders.TelegramFragment", PageInfo(
"{\"\":\"\"}", getString(R.string.telegram),
CoreAnim.slide, "com.idormy.sms.forwarder.fragment.senders.TelegramFragment",
R.drawable.icon_telegram "{\"\":\"\"}",
), CoreAnim.slide,
PageInfo( R.drawable.icon_telegram
getString(R.string.sms_menu), ),
"com.idormy.sms.forwarder.fragment.senders.SmsFragment", PageInfo(
"{\"\":\"\"}", getString(R.string.sms_menu),
CoreAnim.slide, "com.idormy.sms.forwarder.fragment.senders.SmsFragment",
R.drawable.icon_sms "{\"\":\"\"}",
), CoreAnim.slide,
PageInfo( R.drawable.icon_sms
getString(R.string.feishu), ),
"com.idormy.sms.forwarder.fragment.senders.FeishuFragment", PageInfo(
"{\"\":\"\"}", getString(R.string.feishu),
CoreAnim.slide, "com.idormy.sms.forwarder.fragment.senders.FeishuFragment",
R.drawable.icon_feishu "{\"\":\"\"}",
), CoreAnim.slide,
PageInfo( R.drawable.icon_feishu
getString(R.string.pushplus), ),
"com.idormy.sms.forwarder.fragment.senders.PushplusFragment", PageInfo(
"{\"\":\"\"}", getString(R.string.pushplus),
CoreAnim.slide, "com.idormy.sms.forwarder.fragment.senders.PushplusFragment",
R.drawable.icon_pushplus "{\"\":\"\"}",
), CoreAnim.slide,
PageInfo( R.drawable.icon_pushplus
getString(R.string.gotify), ),
"com.idormy.sms.forwarder.fragment.senders.GotifyFragment", PageInfo(
"{\"\":\"\"}", getString(R.string.gotify),
CoreAnim.slide, "com.idormy.sms.forwarder.fragment.senders.GotifyFragment",
R.drawable.icon_gotify "{\"\":\"\"}",
), CoreAnim.slide,
PageInfo( R.drawable.icon_gotify
getString(R.string.dingtalk_inner_robot), ),
"com.idormy.sms.forwarder.fragment.senders.DingtalkInnerRobotFragment", PageInfo(
"{\"\":\"\"}", getString(R.string.dingtalk_inner_robot),
CoreAnim.slide, "com.idormy.sms.forwarder.fragment.senders.DingtalkInnerRobotFragment",
R.drawable.icon_dingtalk_inner "{\"\":\"\"}",
), CoreAnim.slide,
PageInfo( R.drawable.icon_dingtalk_inner
getString(R.string.feishu_app), ),
"com.idormy.sms.forwarder.fragment.senders.FeishuAppFragment", PageInfo(
"{\"\":\"\"}", getString(R.string.feishu_app),
CoreAnim.slide, "com.idormy.sms.forwarder.fragment.senders.FeishuAppFragment",
R.drawable.icon_feishu_app "{\"\":\"\"}",
), CoreAnim.slide,
) R.drawable.icon_feishu_app
),
//前台服务 )
const val FRONT_NOTIFY_ID = 0x1010
const val FRONT_CHANNEL_ID = "com.idormy.sms.forwarder" //前台服务
const val FRONT_CHANNEL_NAME = "SmsForwarder Foreground Service" const val FRONT_NOTIFY_ID = 0x1010
const val FRONT_CHANNEL_ID = "com.idormy.sms.forwarder"
//Frp内网穿透 const val FRONT_CHANNEL_NAME = "SmsForwarder Foreground Service"
const val FRPC_LIB_DOWNLOAD_URL = "https://xupdate.ppps.cn/uploads/%s/%s/libgojni.so"
const val FRPC_LIB_VERSION = "0.44.0" //Frp内网穿透
const val EVENT_FRPC_UPDATE_CONFIG = "EVENT_FRPC_UPDATE_CONFIG" const val FRPC_LIB_DOWNLOAD_URL = "https://xupdate.ppps.cn/uploads/%s/%s/libgojni.so"
const val EVENT_FRPC_DELETE_CONFIG = "EVENT_FRPC_DELETE_CONFIG" const val FRPC_LIB_VERSION = "0.44.0"
const val EVENT_FRPC_RUNNING_ERROR = "EVENT_FRPC_RUNNING_ERROR" const val EVENT_FRPC_UPDATE_CONFIG = "EVENT_FRPC_UPDATE_CONFIG"
const val EVENT_FRPC_RUNNING_SUCCESS = "EVENT_FRPC_RUNNING_SUCCESS" const val EVENT_FRPC_DELETE_CONFIG = "EVENT_FRPC_DELETE_CONFIG"
const val INTENT_FRPC_EDIT_FILE = "INTENT_FRPC_EDIT_FILE" const val EVENT_FRPC_RUNNING_ERROR = "EVENT_FRPC_RUNNING_ERROR"
const val INTENT_FRPC_APPLY_FILE = "INTENT_FRPC_APPLY_FILE" const val EVENT_FRPC_RUNNING_SUCCESS = "EVENT_FRPC_RUNNING_SUCCESS"
const val INTENT_FRPC_EDIT_FILE = "INTENT_FRPC_EDIT_FILE"
//来电监听 const val INTENT_FRPC_APPLY_FILE = "INTENT_FRPC_APPLY_FILE"
const val ACTION_CALL_IN = "android.intent.action.PHONE_STATE"
const val ACTION_CALL_OUT = "android.intent.action.NEW_OUTGOING_CALL" //来电监听
const val EXTRA_PHONE_NUMBER = "android.intent.extra.PHONE_NUMBER" const val ACTION_CALL_IN = "android.intent.action.PHONE_STATE"
const val ACTION_CALL_OUT = "android.intent.action.NEW_OUTGOING_CALL"
//Markdown 查看页面 const val EXTRA_PHONE_NUMBER = "android.intent.extra.PHONE_NUMBER"
const val KEY_TITLE = "key_title"
const val KEY_URL = "key_url" //Markdown 查看页面
const val KEY_TITLE = "key_title"
//主页监听时间 const val KEY_URL = "key_url"
const val EVENT_UPDATE_LOGS_TYPE = "key_logs_type"
const val EVENT_UPDATE_RULE_TYPE = "key_status" //主页监听时间
const val EVENT_UPDATE_NOTIFY = "key_notify" const val EVENT_UPDATE_LOGS_TYPE = "key_logs_type"
const val EVENT_UPDATE_RULE_TYPE = "key_status"
const val KEY_SENDER_ID = "key_sender_id" const val EVENT_UPDATE_NOTIFY = "key_notify"
const val KEY_SENDER_TYPE = "key_sender_type"
const val KEY_SENDER_CLONE = "key_sender_clone" const val KEY_SENDER_ID = "key_sender_id"
const val KEY_SENDER_TEST = "key_sender_test" const val KEY_SENDER_TYPE = "key_sender_type"
const val KEY_SENDER_CLONE = "key_sender_clone"
const val KEY_RULE_ID = "key_rule_id" const val KEY_SENDER_TEST = "key_sender_test"
const val KEY_RULE_TYPE = "key_rule_type"
const val KEY_RULE_CLONE = "key_rule_clone" const val KEY_RULE_ID = "key_rule_id"
const val KEY_RULE_TYPE = "key_rule_type"
const val EVENT_KEY_SIM_SLOT = "EVENT_KEY_SIM_SLOT" const val KEY_RULE_CLONE = "key_rule_clone"
const val EVENT_KEY_PHONE_NUMBERS = "EVENT_KEY_PHONE_NUMBERS"
const val EVENT_KEY_SIM_SLOT = "EVENT_KEY_SIM_SLOT"
//在线升级URL const val EVENT_KEY_PHONE_NUMBERS = "EVENT_KEY_PHONE_NUMBERS"
const val KEY_UPDATE_URL = "https://xupdate.ppps.cn/update/checkVersion"
//在线升级URL
//HttpServer相关 const val KEY_UPDATE_URL = "https://xupdate.ppps.cn/update/checkVersion"
const val ENABLE_HTTP_SERVER = "enable_http_server"
const val HTTP_SERVER_PORT = 5000 //HttpServer相关
const val HTTP_SERVER_TIME_OUT = 10 const val ENABLE_HTTP_SERVER = "enable_http_server"
const val HTTP_SERVER_NOTIFY_ID = 0x1011 const val HTTP_SERVER_PORT = 5000
const val HTTP_SERVER_CHANNEL_ID = "http_server_notification_channel" const val HTTP_SERVER_TIME_OUT = 10
const val HTTP_SERVER_CHANNEL_NAME = "Http-Server Service" const val HTTP_SERVER_NOTIFY_ID = 0x1011
const val START_ACTION = "start" const val HTTP_SERVER_CHANNEL_ID = "http_server_notification_channel"
const val STOP_ACTION = "stop" const val HTTP_SERVER_CHANNEL_NAME = "Http-Server Service"
const val HTTP_SUCCESS_CODE: Int = 200 const val START_ACTION = "start"
const val HTTP_FAILURE_CODE: Int = 500 const val STOP_ACTION = "stop"
const val SP_ENABLE_SERVER = "enable_server" const val HTTP_SUCCESS_CODE: Int = 200
const val SP_ENABLE_SERVER_AUTORUN = "enable_server_autorun" const val HTTP_FAILURE_CODE: Int = 500
const val SP_SERVER_SAFETY_MEASURES = "server_safety_measures" const val SP_ENABLE_SERVER = "enable_server"
const val SP_SERVER_SIGN_KEY = "server_sign_key" const val SP_ENABLE_SERVER_AUTORUN = "enable_server_autorun"
const val SP_SERVER_TIME_TOLERANCE = "server_time_tolerance" const val SP_SERVER_SAFETY_MEASURES = "server_safety_measures"
const val SP_SERVER_SM4_KEY = "server_sm4_key" const val SP_SERVER_SIGN_KEY = "server_sign_key"
const val SP_SERVER_PUBLIC_KEY = "server_public_key" const val SP_SERVER_TIME_TOLERANCE = "server_time_tolerance"
const val SP_SERVER_PRIVATE_KEY = "server_private_key" const val SP_SERVER_SM4_KEY = "server_sm4_key"
const val SP_SERVER_WEB_PATH = "server_web_path" const val SP_SERVER_PUBLIC_KEY = "server_public_key"
const val SP_ENABLE_API_CLONE = "enable_api_clone" const val SP_SERVER_PRIVATE_KEY = "server_private_key"
const val SP_ENABLE_API_SMS_SEND = "enable_api_sms_send" const val SP_SERVER_WEB_PATH = "server_web_path"
const val SP_ENABLE_API_SMS_QUERY = "enable_api_sms_query" const val SP_ENABLE_API_CLONE = "enable_api_clone"
const val SP_ENABLE_API_CALL_QUERY = "enable_api_call_query" const val SP_ENABLE_API_SMS_SEND = "enable_api_sms_send"
const val SP_ENABLE_API_CONTACT_QUERY = "enable_api_contact_query" const val SP_ENABLE_API_SMS_QUERY = "enable_api_sms_query"
const val SP_ENABLE_API_BATTERY_QUERY = "enable_api_battery_query" const val SP_ENABLE_API_CALL_QUERY = "enable_api_call_query"
const val SP_ENABLE_API_WOL = "enable_api_wol" const val SP_ENABLE_API_CONTACT_QUERY = "enable_api_contact_query"
const val SP_WOL_HISTORY = "wol_history" const val SP_ENABLE_API_BATTERY_QUERY = "enable_api_battery_query"
const val SP_SERVER_ADDRESS = "server_address" const val SP_ENABLE_API_WOL = "enable_api_wol"
const val SP_SERVER_HISTORY = "server_history" const val SP_WOL_HISTORY = "wol_history"
const val SP_SERVER_CONFIG = "server_config" const val SP_SERVER_ADDRESS = "server_address"
const val SP_CLIENT_SAFETY_MEASURES = "client_safety_measures" const val SP_SERVER_HISTORY = "server_history"
const val SP_CLIENT_SIGN_KEY = "client_sign_key" const val SP_SERVER_CONFIG = "server_config"
const val SP_CLIENT_SAFETY_MEASURES = "client_safety_measures"
var CLIENT_FRAGMENT_LIST = listOf( const val SP_CLIENT_SIGN_KEY = "client_sign_key"
PageInfo(
getString(R.string.api_clone), var CLIENT_FRAGMENT_LIST = listOf(
"com.idormy.sms.forwarder.fragment.client.CloneFragment", PageInfo(
"{\"\":\"\"}", getString(R.string.api_clone),
CoreAnim.slide, "com.idormy.sms.forwarder.fragment.client.CloneFragment",
R.drawable.icon_api_clone "{\"\":\"\"}",
), CoreAnim.slide,
PageInfo( R.drawable.icon_api_clone
getString(R.string.api_sms_send), ),
"com.idormy.sms.forwarder.fragment.client.SmsSendFragment", PageInfo(
"{\"\":\"\"}", getString(R.string.api_sms_send),
CoreAnim.slide, "com.idormy.sms.forwarder.fragment.client.SmsSendFragment",
R.drawable.icon_api_sms_send "{\"\":\"\"}",
), CoreAnim.slide,
PageInfo( R.drawable.icon_api_sms_send
getString(R.string.api_sms_query), ),
"com.idormy.sms.forwarder.fragment.client.SmsQueryFragment", PageInfo(
"{\"\":\"\"}", getString(R.string.api_sms_query),
CoreAnim.slide, "com.idormy.sms.forwarder.fragment.client.SmsQueryFragment",
R.drawable.icon_api_sms_query "{\"\":\"\"}",
), CoreAnim.slide,
PageInfo( R.drawable.icon_api_sms_query
getString(R.string.api_call_query), ),
"com.idormy.sms.forwarder.fragment.client.CallQueryFragment", PageInfo(
"{\"\":\"\"}", getString(R.string.api_call_query),
CoreAnim.slide, "com.idormy.sms.forwarder.fragment.client.CallQueryFragment",
R.drawable.icon_api_call_query "{\"\":\"\"}",
), CoreAnim.slide,
PageInfo( R.drawable.icon_api_call_query
getString(R.string.api_contact_query), ),
"com.idormy.sms.forwarder.fragment.client.ContactQueryFragment", PageInfo(
"{\"\":\"\"}", getString(R.string.api_contact_query),
CoreAnim.slide, "com.idormy.sms.forwarder.fragment.client.ContactQueryFragment",
R.drawable.icon_api_contact_query "{\"\":\"\"}",
), CoreAnim.slide,
PageInfo( R.drawable.icon_api_contact_query
getString(R.string.api_battery_query), ),
"com.idormy.sms.forwarder.fragment.client.BatteryQueryFragment", PageInfo(
"{\"\":\"\"}", getString(R.string.api_battery_query),
CoreAnim.slide, "com.idormy.sms.forwarder.fragment.client.BatteryQueryFragment",
R.drawable.icon_api_battery_query "{\"\":\"\"}",
), CoreAnim.slide,
PageInfo( R.drawable.icon_api_battery_query
getString(R.string.api_wol), ),
"com.idormy.sms.forwarder.fragment.client.WolSendFragment", PageInfo(
"{\"\":\"\"}", getString(R.string.api_wol),
CoreAnim.slide, "com.idormy.sms.forwarder.fragment.client.WolSendFragment",
R.drawable.icon_api_wol "{\"\":\"\"}",
), CoreAnim.slide,
R.drawable.icon_api_wol
),
) )

@ -114,6 +114,12 @@ class SettingUtils private constructor() {
//设备名称 //设备名称
var extraDeviceMark: String by SharedPreference(SP_EXTRA_DEVICE_MARK, "") var extraDeviceMark: String by SharedPreference(SP_EXTRA_DEVICE_MARK, "")
//SM1主键
var subidSim1: Int by SharedPreference(SP_SUBID_SIM1, 0)
//SM2主键
var subidSim2: Int by SharedPreference(SP_SUBID_SIM2, 0)
//SM1备注 //SM1备注
var extraSim1: String by SharedPreference(SP_EXTRA_SIM1, "") var extraSim1: String by SharedPreference(SP_EXTRA_SIM1, "")

@ -1,74 +1,74 @@
package com.idormy.sms.forwarder.utils.sender package com.idormy.sms.forwarder.utils.sender
import android.Manifest import android.Manifest
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.util.Log import android.util.Log
import androidx.core.app.ActivityCompat import androidx.core.app.ActivityCompat
import com.idormy.sms.forwarder.App import com.idormy.sms.forwarder.App
import com.idormy.sms.forwarder.R import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.database.entity.Rule 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.setting.SmsSetting import com.idormy.sms.forwarder.entity.setting.SmsSetting
import com.idormy.sms.forwarder.utils.PhoneUtils import com.idormy.sms.forwarder.utils.PhoneUtils
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.xuexiang.xui.utils.ResUtils import com.xuexiang.xui.utils.ResUtils
import com.xuexiang.xutil.XUtil import com.xuexiang.xutil.XUtil
import com.xuexiang.xutil.net.NetworkUtils import com.xuexiang.xutil.net.NetworkUtils
@Suppress("PrivatePropertyName", "UNUSED_PARAMETER", "unused") @Suppress("PrivatePropertyName", "UNUSED_PARAMETER", "unused")
class SmsUtils { class SmsUtils {
companion object { companion object {
private val TAG: String = SmsUtils::class.java.simpleName private val TAG: String = SmsUtils::class.java.simpleName
fun sendMsg( fun sendMsg(
setting: SmsSetting, setting: SmsSetting,
msgInfo: MsgInfo, msgInfo: MsgInfo,
rule: Rule?, rule: Rule?,
logId: Long?, logId: Long?,
) { ) {
//仅当无网络时启用 && 判断是否真实有网络 //仅当无网络时启用 && 判断是否真实有网络
if (setting.onlyNoNetwork == true && NetworkUtils.isHaveInternet() && NetworkUtils.isAvailableByPing()) { if (setting.onlyNoNetwork == true && NetworkUtils.isHaveInternet() && NetworkUtils.isAvailableByPing()) {
SendUtils.updateLogs(logId, 0, ResUtils.getString(R.string.OnlyNoNetwork)) SendUtils.updateLogs(logId, 0, ResUtils.getString(R.string.OnlyNoNetwork))
return return
} }
if (ActivityCompat.checkSelfPermission(XUtil.getContext(), Manifest.permission.SEND_SMS) != PackageManager.PERMISSION_GRANTED) { if (ActivityCompat.checkSelfPermission(XUtil.getContext(), Manifest.permission.SEND_SMS) != PackageManager.PERMISSION_GRANTED) {
SendUtils.updateLogs(logId, 0, ResUtils.getString(R.string.no_sms_sending_permission)) SendUtils.updateLogs(logId, 0, ResUtils.getString(R.string.no_sms_sending_permission))
return return
} }
val content: String = if (rule != null) { val content: String = if (rule != null) {
msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace) msgInfo.getContentForSend(rule.smsTemplate, rule.regexReplace)
} else { } else {
msgInfo.getContentForSend(SettingUtils.smsTemplate.toString()) msgInfo.getContentForSend(SettingUtils.smsTemplate)
} }
//【注意】判断卡槽配置0=原进原出、1=卡槽1、2=卡槽2 //【注意】判断卡槽配置0=原进原出、1=卡槽1、2=卡槽2
val simSlotIndex = if (setting.simSlot == 0) msgInfo.simSlot else setting.simSlot - 1 val simSlotIndex = if (setting.simSlot == 0) msgInfo.simSlot else setting.simSlot - 1
//获取卡槽信息 //获取卡槽信息
if (App.SimInfoList.isEmpty()) { if (App.SimInfoList.isEmpty()) {
App.SimInfoList = PhoneUtils.getSimMultiInfo() App.SimInfoList = PhoneUtils.getSimMultiInfo()
} }
Log.d(TAG, App.SimInfoList.toString()) Log.d(TAG, App.SimInfoList.toString())
//替换 {{来源号码}} 标签 //替换 {{来源号码}} 标签
val mobiles = setting.mobiles.replace(ResUtils.getString(R.string.tag_from), msgInfo.from) val mobiles = setting.mobiles.replace(ResUtils.getString(R.string.tag_from), msgInfo.from)
//TODO取不到卡槽信息时采用默认卡槽发送 //TODO取不到卡槽信息时采用默认卡槽发送
val mSubscriptionId: Int = App.SimInfoList[simSlotIndex]?.mSubscriptionId ?: -1 val mSubscriptionId: Int = App.SimInfoList[simSlotIndex]?.mSubscriptionId ?: -1
val res: String? = PhoneUtils.sendSms(mSubscriptionId, mobiles, content) val res: String? = PhoneUtils.sendSms(mSubscriptionId, mobiles, content)
if (res == null) { if (res == null) {
SendUtils.updateLogs(logId, 2, ResUtils.getString(R.string.request_succeeded)) SendUtils.updateLogs(logId, 2, ResUtils.getString(R.string.request_succeeded))
} else { } else {
SendUtils.updateLogs(logId, 0, res) SendUtils.updateLogs(logId, 0, res)
} }
} }
fun sendMsg(setting: SmsSetting, msgInfo: MsgInfo) { fun sendMsg(setting: SmsSetting, msgInfo: MsgInfo) {
sendMsg(setting, msgInfo, null, null) sendMsg(setting, msgInfo, null, null)
} }
} }
} }

@ -83,7 +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, msgInfo.type, msgInfo.from, msgInfo.content, rule.rule.id, msgInfo.simInfo 0, msgInfo.type, msgInfo.from, msgInfo.content, rule.rule.id, msgInfo.simInfo, msgInfo.subId
) )
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)

File diff suppressed because it is too large Load Diff

@ -334,9 +334,12 @@
<!--SettingActivity--> <!--SettingActivity-->
<string name="notify_content">Notify Content</string> <string name="notify_content">Notify Content</string>
<string name="device_name">Device Name</string> <string name="device_name">Device Name</string>
<string name="sim1_remark" tools:ignore="Typos">SIM1 Label</string> <string name="sim_sub_id">SIM1 SubId</string>
<string name="sim2_remark" tools:ignore="Typos">SIM2 Label</string> <string name="sim1_remark" tools:ignore="Typos">SIM1 SubId/Label</string>
<string name="sim2_remark" tools:ignore="Typos">SIM2 SubId/Label</string>
<string name="carrier_mobile" tools:ignore="Typos">Label of SIM,\neg. AT&amp;T_88888888</string> <string name="carrier_mobile" tools:ignore="Typos">Label of SIM,\neg. AT&amp;T_88888888</string>
<string name="tip_number_only_error_message">Number must be greater than 0!</string>
<string name="regexp_number_only">^[1-9]?\\d+$</string>
<string name="low_power_alarm_threshold">Low Power Alarm</string> <string name="low_power_alarm_threshold">Low Power Alarm</string>
<string name="low_power_alarm_threshold_tips">Value range: 099.\nLeft blank or 0 is disabled</string> <string name="low_power_alarm_threshold_tips">Value range: 099.\nLeft blank or 0 is disabled</string>
<string name="retry_interval">Retry Interval</string> <string name="retry_interval">Retry Interval</string>
@ -543,6 +546,7 @@
<string name="tag_app_name">{{APP_NAME}}</string> <string name="tag_app_name">{{APP_NAME}}</string>
<string name="tag_msg">{{MSG}}</string> <string name="tag_msg">{{MSG}}</string>
<string name="tag_card_slot">{{CARD_SLOT}}</string> <string name="tag_card_slot">{{CARD_SLOT}}</string>
<string name="tag_card_subid">{{CARD_SUBID}}</string>
<string name="tag_receive_time">{{RECEIVE_TIME}}</string> <string name="tag_receive_time">{{RECEIVE_TIME}}</string>
<string name="tag_device_name">{{DEVICE_NAME}}</string> <string name="tag_device_name">{{DEVICE_NAME}}</string>
<string name="tag_app_version">{{APP_VERSION}}</string> <string name="tag_app_version">{{APP_VERSION}}</string>

@ -335,9 +335,12 @@
<!--SettingActivity--> <!--SettingActivity-->
<string name="notify_content">通知文案</string> <string name="notify_content">通知文案</string>
<string name="device_name">设备名称</string> <string name="device_name">设备名称</string>
<string name="sim1_remark" tools:ignore="Typos">SIM1备注</string> <string name="sim_sub_id">卡槽主键</string>
<string name="sim2_remark" tools:ignore="Typos">SIM2备注</string> <string name="sim1_remark" tools:ignore="Typos">SIM1主键/备注</string>
<string name="carrier_mobile">运营商_手机号</string> <string name="sim2_remark" tools:ignore="Typos">SIM2主键/备注</string>
<string name="carrier_mobile">序号/运营商_手机号</string>
<string name="tip_number_only_error_message">数字必须大于0!</string>
<string name="regexp_number_only">^[1-9]?\\d+$</string>
<string name="low_power_alarm_threshold">安全电量范围(%)</string> <string name="low_power_alarm_threshold">安全电量范围(%)</string>
<string name="low_power_alarm_threshold_tips">超出安全范围将发出预警</string> <string name="low_power_alarm_threshold_tips">超出安全范围将发出预警</string>
<string name="retry_interval">请求重试机制</string> <string name="retry_interval">请求重试机制</string>
@ -544,6 +547,7 @@
<string name="tag_app_name">{{APP名称}}</string> <string name="tag_app_name">{{APP名称}}</string>
<string name="tag_msg">{{通知内容}}</string> <string name="tag_msg">{{通知内容}}</string>
<string name="tag_card_slot">{{卡槽信息}}</string> <string name="tag_card_slot">{{卡槽信息}}</string>
<string name="tag_card_subid">{{卡槽主键}}</string>
<string name="tag_receive_time">{{接收时间}}</string> <string name="tag_receive_time">{{接收时间}}</string>
<string name="tag_device_name">{{设备名称}}</string> <string name="tag_device_name">{{设备名称}}</string>
<string name="tag_app_version">{{当前应用版本号}}</string> <string name="tag_app_version">{{当前应用版本号}}</string>

Loading…
Cancel
Save