新增:SIM卡槽状态监控(包名:66666666#355

This commit is contained in:
pppscn 2023-11-21 17:18:56 +08:00
parent 5f64d9462e
commit 5741cdfe96
9 changed files with 215 additions and 27 deletions

View File

@ -264,6 +264,15 @@
<action android:name="android.intent.action.NEW_OUTGOING_CALL" /> <action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter> </intent-filter>
</receiver> </receiver>
<receiver
android:name=".receiver.SimStateReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.SIM_STATE_CHANGED" />
</intent-filter>
</receiver>
</application> </application>
</manifest> </manifest>

View File

@ -157,6 +157,8 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
editAddExtraSim1(binding!!.etExtraSim1) editAddExtraSim1(binding!!.etExtraSim1)
//SIM2备注 //SIM2备注
editAddExtraSim2(binding!!.etExtraSim2) editAddExtraSim2(binding!!.etExtraSim2)
//SIM卡槽状态监控
switchSimStateReceiver(binding!!.sbSimStateReceiver)
//通知内容 //通知内容
editNotifyContent(binding!!.etNotifyContent) editNotifyContent(binding!!.etNotifyContent)
@ -212,10 +214,12 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
it.show() it.show()
} }
} }
R.id.btn_extra_device_mark -> { R.id.btn_extra_device_mark -> {
binding!!.etExtraDeviceMark.setText(PhoneUtils.getDeviceName()) binding!!.etExtraDeviceMark.setText(PhoneUtils.getDeviceName())
return return
} }
R.id.btn_extra_sim1 -> { R.id.btn_extra_sim1 -> {
App.SimInfoList = PhoneUtils.getSimMultiInfo() App.SimInfoList = PhoneUtils.getSimMultiInfo()
if (App.SimInfoList.isEmpty()) { if (App.SimInfoList.isEmpty()) {
@ -239,6 +243,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
binding!!.etExtraSim1.setText(simInfo?.mCarrierName.toString() + "_" + simInfo?.mNumber.toString()) binding!!.etExtraSim1.setText(simInfo?.mCarrierName.toString() + "_" + simInfo?.mNumber.toString())
return return
} }
R.id.btn_extra_sim2 -> { R.id.btn_extra_sim2 -> {
App.SimInfoList = PhoneUtils.getSimMultiInfo() App.SimInfoList = PhoneUtils.getSimMultiInfo()
if (App.SimInfoList.isEmpty()) { if (App.SimInfoList.isEmpty()) {
@ -262,32 +267,38 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
binding!!.etExtraSim2.setText(simInfo?.mCarrierName.toString() + "_" + simInfo?.mNumber.toString()) binding!!.etExtraSim2.setText(simInfo?.mCarrierName.toString() + "_" + simInfo?.mNumber.toString())
return return
} }
R.id.bt_insert_sender -> { R.id.bt_insert_sender -> {
CommonUtils.insertOrReplaceText2Cursor(etSmsTemplate, getString(R.string.tag_from)) CommonUtils.insertOrReplaceText2Cursor(etSmsTemplate, getString(R.string.tag_from))
return return
} }
R.id.bt_insert_content -> { R.id.bt_insert_content -> {
CommonUtils.insertOrReplaceText2Cursor(etSmsTemplate, getString(R.string.tag_sms)) CommonUtils.insertOrReplaceText2Cursor(etSmsTemplate, getString(R.string.tag_sms))
return return
} }
R.id.bt_insert_extra -> { R.id.bt_insert_extra -> {
CommonUtils.insertOrReplaceText2Cursor( CommonUtils.insertOrReplaceText2Cursor(
etSmsTemplate, getString(R.string.tag_card_slot) etSmsTemplate, getString(R.string.tag_card_slot)
) )
return return
} }
R.id.bt_insert_time -> { R.id.bt_insert_time -> {
CommonUtils.insertOrReplaceText2Cursor( CommonUtils.insertOrReplaceText2Cursor(
etSmsTemplate, getString(R.string.tag_receive_time) etSmsTemplate, 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, getString(R.string.tag_device_name) etSmsTemplate, getString(R.string.tag_device_name)
) )
return return
} }
else -> {} else -> {}
} }
} }
@ -881,6 +892,25 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
}) })
} }
//SIM卡槽状态监控
@SuppressLint("UseSwitchCompatOrMaterialCode")
fun switchSimStateReceiver(sbSimStateReceiver: SwitchButton) {
sbSimStateReceiver.isChecked = SettingUtils.enableSimStateReceiver
sbSimStateReceiver.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean ->
App.SimInfoList = PhoneUtils.getSimMultiInfo()
if (isChecked && App.SimInfoList.isEmpty()) {
XToastUtils.error(R.string.tip_can_not_get_sim_infos)
XXPermissions.startPermissionActivity(
requireContext(), "android.permission.READ_PHONE_STATE"
)
SettingUtils.enableSimStateReceiver = false
sbSimStateReceiver.isChecked = false
return@setOnCheckedChangeListener
}
SettingUtils.enableSimStateReceiver = isChecked
}
}
//设置通知内容 //设置通知内容
private fun editNotifyContent(etNotifyContent: EditText) { private fun editNotifyContent(etNotifyContent: EditText) {
etNotifyContent.setText(SettingUtils.notifyContent) etNotifyContent.setText(SettingUtils.notifyContent)

View File

@ -14,7 +14,7 @@ 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" || receiveAction == "android.intent.action.LOCKED_BOOT_COMPLETED") { if (receiveAction == Intent.ACTION_BOOT_COMPLETED || receiveAction == Intent.ACTION_LOCKED_BOOT_COMPLETED) {
try { try {
Log.d(TAG, "强制重启APP一次") Log.d(TAG, "强制重启APP一次")
val intent1 = Intent(context, SplashActivity::class.java) val intent1 = Intent(context, SplashActivity::class.java)

View File

@ -3,35 +3,128 @@ 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.telephony.TelephonyManager
import android.util.Log import android.util.Log
import com.idormy.sms.forwarder.App import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager
import androidx.work.workDataOf
import com.google.gson.Gson
import com.idormy.sms.forwarder.R
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.Worker
import com.idormy.sms.forwarder.workers.SendWorker
import com.xuexiang.xutil.resource.ResUtils.getString
import java.util.Date
import com.idormy.sms.forwarder.App
import android.os.Handler
import com.idormy.sms.forwarder.utils.SettingUtils
@Suppress("PrivatePropertyName")
class SimStateReceiver : BroadcastReceiver() { class SimStateReceiver : BroadcastReceiver() {
/**
* 更换SIM卡如果不杀后台并重启则发送出的卡槽信息仍然是刚启动应用时读取的SIM卡 private var TAG = "SimStateReceiver"
* 增加这个Receiver接收SIM卡插拔状态广播自动更新缓存
*/
override fun onReceive(context: Context, intent: Intent) { override fun onReceive(context: Context, intent: Intent) {
val receiveAction = intent.action //纯客户端模式
Log.d(TAG, "onReceive intent $receiveAction") if (SettingUtils.enablePureClientMode) return
if (ACTION_SIM_STATE_CHANGED == receiveAction) {
//SIM状态的额外信息 //SIM卡槽状态监控开关
val state = intent.extras!!.getString(EXTRA_SIM_STATE) if (!SettingUtils.enableSimStateReceiver) return
Log.d(TAG, state!!)
//只需要最后一个SIM加载完毕的 LOADED 状态 val action = intent.action
if (SIM_STATE_LOADED == state) { if (action == Intent.ACTION_BOOT_COMPLETED) {
//刷新SimInfoList // 在这里处理开机启动时的逻辑
App.SimInfoList = PhoneUtils.getSimMultiInfo() // 例如:注册监听 SIM 变化
Log.d(TAG, App.SimInfoList.toString()) registerSimStateListener(context)
} else if (action == "android.intent.action.SIM_STATE_CHANGED") {
// 处理 SIM 卡状态变化的逻辑
val telephonyManager = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
// 获取当前 SIM 卡状态
when (telephonyManager.simState) {
TelephonyManager.SIM_STATE_ABSENT -> {
Log.d(TAG, "SIM 卡被移除")
// 处理 SIM 卡被移除的情况
}
TelephonyManager.SIM_STATE_READY -> {
Log.d(TAG, "SIM 卡已准备就绪延迟2秒再获取信息")
val handler = Handler()
handler.postDelayed({
// 获取 SIM 卡信息
App.SimInfoList = PhoneUtils.getSimMultiInfo()
Log.d(TAG, App.SimInfoList.toString())
val msg = StringBuilder()
App.SimInfoList.forEach {
msg.append("[SIM-").append(it.key + 1).append("]\n")
msg.append(getString(R.string.carrier_name)).append(": ").append(it.value.mCarrierName).append("\n")
//msg.append(getString(R.string.icc_id)).append(": ").append(it.value.mIccId).append("\n")
msg.append(getString(R.string.sim_slot_index)).append(": ").append(it.value.mSimSlotIndex).append("\n")
msg.append(getString(R.string.number)).append(": ").append(it.value.mNumber).append("\n")
msg.append(getString(R.string.country_iso)).append(": ").append(it.value.mCountryIso).append("\n")
msg.append(getString(R.string.subscription_id)).append(": ").append(it.value.mSubscriptionId).append("\n")
}
sendMessage(context, msg.toString().trimEnd())
}, 2000)
}
TelephonyManager.SIM_STATE_CARD_IO_ERROR -> {
Log.d(TAG, "SIM 卡读取失败")
}
TelephonyManager.SIM_STATE_CARD_RESTRICTED -> {
Log.d(TAG, "SIM 卡受限")
}
TelephonyManager.SIM_STATE_NETWORK_LOCKED -> {
Log.d(TAG, "SIM 卡网络锁定")
}
TelephonyManager.SIM_STATE_NOT_READY -> {
Log.d(TAG, "SIM 卡未准备好")
}
TelephonyManager.SIM_STATE_PERM_DISABLED -> {
Log.d(TAG, "SIM 卡被禁用")
}
TelephonyManager.SIM_STATE_PIN_REQUIRED -> {
Log.d(TAG, "SIM 卡需要 PIN 解锁")
}
TelephonyManager.SIM_STATE_PUK_REQUIRED -> {
Log.d(TAG, "SIM 卡需要 PUK 解锁")
}
TelephonyManager.SIM_STATE_UNKNOWN -> {
Log.d(TAG, "SIM 卡状态未知")
}
} }
} }
} }
companion object { private fun registerSimStateListener(context: Context) {
private const val TAG = "SimStateReceiver" // 在此处注册 SIM 变化监听器
const val ACTION_SIM_STATE_CHANGED = "android.intent.action.SIM_STATE_CHANGED" // 可以使用 TelephonyManager 或 SubscriptionManager 进行注册监听
private const val EXTRA_SIM_STATE = "ss" }
private const val SIM_STATE_LOADED = "LOADED"
//发送信息
private fun sendMessage(context: Context, msg: String) {
Log.i(TAG, msg)
try {
val msgInfo = MsgInfo("app", "66666666", msg, Date(), getString(R.string.sim_state_monitor), -1)
val request = OneTimeWorkRequestBuilder<SendWorker>().setInputData(
workDataOf(
Worker.sendMsgInfo to Gson().toJson(msgInfo),
)
).build()
WorkManager.getInstance(context).enqueue(request)
} catch (e: Exception) {
Log.e(TAG, "getLog e:" + e.message)
}
} }
} }

View File

@ -80,6 +80,7 @@ const val SP_SUBID_SIM1 = "subid_sim1"
const val SP_SUBID_SIM2 = "subid_sim2" const val SP_SUBID_SIM2 = "subid_sim2"
const val SP_EXTRA_SIM1 = "extra_sim1" const val SP_EXTRA_SIM1 = "extra_sim1"
const val SP_EXTRA_SIM2 = "extra_sim2" const val SP_EXTRA_SIM2 = "extra_sim2"
const val SP_SIM_STATE_RECEIVER = "enable_sim_state_receiver"
const val SP_ENABLE_SMS_TEMPLATE = "enable_sms_template" const val SP_ENABLE_SMS_TEMPLATE = "enable_sms_template"
const val SP_SMS_TEMPLATE = "sms_template" const val SP_SMS_TEMPLATE = "sms_template"

View File

@ -130,18 +130,21 @@ class SettingUtils private constructor() {
//设备名称 //设备名称
var extraDeviceMark: String by SharedPreference(SP_EXTRA_DEVICE_MARK, "") var extraDeviceMark: String by SharedPreference(SP_EXTRA_DEVICE_MARK, "")
//SM1主键 //SIM1主键
var subidSim1: Int by SharedPreference(SP_SUBID_SIM1, 0) var subidSim1: Int by SharedPreference(SP_SUBID_SIM1, 0)
//SM2主键 //SIM2主键
var subidSim2: Int by SharedPreference(SP_SUBID_SIM2, 0) var subidSim2: Int by SharedPreference(SP_SUBID_SIM2, 0)
//SM1备注 //SIM1备注
var extraSim1: String by SharedPreference(SP_EXTRA_SIM1, "") var extraSim1: String by SharedPreference(SP_EXTRA_SIM1, "")
//SM2备注 //SIM2备注
var extraSim2: String by SharedPreference(SP_EXTRA_SIM2, "") var extraSim2: String by SharedPreference(SP_EXTRA_SIM2, "")
//SIM卡槽状态监控
var enableSimStateReceiver: Boolean by SharedPreference(SP_SIM_STATE_RECEIVER, false)
//是否启用自定义模板 //是否启用自定义模板
var enableSmsTemplate: Boolean by SharedPreference(SP_ENABLE_SMS_TEMPLATE, false) var enableSmsTemplate: Boolean by SharedPreference(SP_ENABLE_SMS_TEMPLATE, false)

View File

@ -1475,6 +1475,40 @@
</LinearLayout> </LinearLayout>
<LinearLayout
style="@style/settingBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/sim_state_monitor"
android:textStyle="bold"
tools:ignore="RelativeOverlap" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/sim_state_monitor_tips"
android:textSize="9sp"
tools:ignore="SmallSp" />
</LinearLayout>
<com.xuexiang.xui.widget.button.switchbutton.SwitchButton
android:id="@+id/sb_sim_state_receiver"
style="@style/SwitchButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout <LinearLayout
style="@style/settingBarStyle" style="@style/settingBarStyle"
android:layout_width="match_parent" android:layout_width="match_parent"

View File

@ -558,6 +558,8 @@
<string name="active_request_tips">Obtain instructions through passive reception or active polling to operate the machine</string> <string name="active_request_tips">Obtain instructions through passive reception or active polling to operate the machine</string>
<string name="httpserver">Local HttpServer</string> <string name="httpserver">Local HttpServer</string>
<string name="httpserver_tips">Available under WiFi network, after startup, other machines in the LAN can directly call the local interface</string> <string name="httpserver_tips">Available under WiFi network, after startup, other machines in the LAN can directly call the local interface</string>
<string name="sim_state_monitor">SIM State Monitor</string>
<string name="sim_state_monitor_tips">[Note] You need to manually create APP forwarding rules, package name: 66666666</string>
<string name="network_state_monitor">Network State Monitor</string> <string name="network_state_monitor">Network State Monitor</string>
<string name="network_state_monitor_tips">[Note] You need to manually create APP forwarding rules, package name: 77777777</string> <string name="network_state_monitor_tips">[Note] You need to manually create APP forwarding rules, package name: 77777777</string>
<string name="network_state_change_remind">Network State Change Remind</string> <string name="network_state_change_remind">Network State Change Remind</string>
@ -1048,4 +1050,11 @@
<string name="operator_name">Operator Name</string> <string name="operator_name">Operator Name</string>
<string name="host_address">Host Address</string> <string name="host_address">Host Address</string>
<string name="loading_app_list">Loading app list async...</string> <string name="loading_app_list">Loading app list async...</string>
<string name="carrier_name">Carrier Name</string>
<string name="icc_id">ICC ID</string>
<string name="sim_slot_index">Sim Slot Index</string>
<string name="number">Number</string>
<string name="country_iso">Country</string>
<string name="subscription_id">Subscription ID</string>
</resources> </resources>

View File

@ -559,6 +559,8 @@
<string name="active_request_tips">通过 被动接收 或者 主动轮询 获取指令,从而操作本机</string> <string name="active_request_tips">通过 被动接收 或者 主动轮询 获取指令,从而操作本机</string>
<string name="httpserver">被动接收本地 HttpServer</string> <string name="httpserver">被动接收本地 HttpServer</string>
<string name="httpserver_tips">WiFi网络下可用启动后局域网内其他机器可直接调用本机接口</string> <string name="httpserver_tips">WiFi网络下可用启动后局域网内其他机器可直接调用本机接口</string>
<string name="sim_state_monitor">SIM卡槽状态监控</string>
<string name="sim_state_monitor_tips">需要手动创建APP转发规则包名66666666</string>
<string name="network_state_monitor">网络状态监控</string> <string name="network_state_monitor">网络状态监控</string>
<string name="network_state_monitor_tips">需要手动创建APP转发规则包名77777777</string> <string name="network_state_monitor_tips">需要手动创建APP转发规则包名77777777</string>
<string name="network_state_change_remind">网络状态改变提醒</string> <string name="network_state_change_remind">网络状态改变提醒</string>
@ -703,7 +705,7 @@
<string name="no">No</string> <string name="no">No</string>
<string name="unknown">---</string> <string name="unknown">---</string>
<string name="refresh">刷新</string> <string name="refresh">刷新</string>
<string name="tip_can_not_get_sim_infos">请确认应用权限【获取手机信息】为【始终允许】或手动填写</string> <string name="tip_can_not_get_sim_infos">无法获取卡槽信息,请确认应用权限【获取手机信息】为【始终允许】</string>
<string name="tip_can_not_get_sim_info">未获取到卡槽%s中的SIM卡信息</string> <string name="tip_can_not_get_sim_info">未获取到卡槽%s中的SIM卡信息</string>
<string name="add">添加</string> <string name="add">添加</string>
<string name="check_update">检查更新</string> <string name="check_update">检查更新</string>
@ -1049,4 +1051,11 @@
<string name="operator_name">运营商</string> <string name="operator_name">运营商</string>
<string name="host_address">本地IP</string> <string name="host_address">本地IP</string>
<string name="loading_app_list">正在异步加载应用列表...</string> <string name="loading_app_list">正在异步加载应用列表...</string>
<string name="carrier_name">运营商名</string>
<string name="icc_id">ICC ID</string>
<string name="sim_slot_index">卡槽索引</string>
<string name="number">手机号码</string>
<string name="country_iso">国家代码</string>
<string name="subscription_id">订阅标识</string>
</resources> </resources>