新增:彩信转发功能(TODO:解析彩信) #351

This commit is contained in:
pppscn 2023-11-24 17:18:27 +08:00
parent e9bfb9eca4
commit 4c3fcf45f6
4 changed files with 66 additions and 65 deletions

View File

@ -256,6 +256,11 @@
<!--短信广播--> <!--短信广播-->
<action android:name="android.provider.Telephony.SMS_RECEIVED" /> <action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter> </intent-filter>
<intent-filter android:priority="2147483647">
<action android:name="android.provider.Telephony.WAP_PUSH_RECEIVED" />
<action android:name="android.provider.Telephony.WAP_PUSH_DELIVER" />
<data android:mimeType="application/vnd.wap.mms-message" />
</intent-filter>
</receiver> </receiver>
<receiver <receiver
android:name=".receiver.CallReceiver" android:name=".receiver.CallReceiver"

View File

@ -16,7 +16,6 @@ import com.idormy.sms.forwarder.utils.Worker
import com.idormy.sms.forwarder.workers.SendWorker import com.idormy.sms.forwarder.workers.SendWorker
import com.xuexiang.xrouter.utils.TextUtils import com.xuexiang.xrouter.utils.TextUtils
import com.xuexiang.xui.utils.ResUtils.getString import com.xuexiang.xui.utils.ResUtils.getString
import com.xuexiang.xutil.resource.ResUtils
import java.util.* import java.util.*
@Suppress("DEPRECATION") @Suppress("DEPRECATION")

View File

@ -9,16 +9,15 @@ 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.R import com.idormy.sms.forwarder.R
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.Worker 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.Date import java.util.Date
import com.idormy.sms.forwarder.App
import android.os.Handler
import com.idormy.sms.forwarder.utils.SettingUtils
@Suppress("PrivatePropertyName") @Suppress("PrivatePropertyName")
class SimStateReceiver : BroadcastReceiver() { class SimStateReceiver : BroadcastReceiver() {

View File

@ -17,13 +17,15 @@ import com.idormy.sms.forwarder.utils.SmsCommandUtils
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 com.xuexiang.xrouter.utils.TextUtils import com.xuexiang.xrouter.utils.TextUtils
import java.util.* import java.util.Date
//短信广播 //短信广播
@Suppress("PrivatePropertyName") @Suppress("PrivatePropertyName")
class SmsReceiver : BroadcastReceiver() { class SmsReceiver : BroadcastReceiver() {
private var TAG = "SmsReceiver" private var TAG = "SmsReceiver"
private var from = ""
private var msg = ""
override fun onReceive(context: Context, intent: Intent) { override fun onReceive(context: Context, intent: Intent) {
try { try {
@ -37,35 +39,32 @@ class SmsReceiver : BroadcastReceiver() {
&& intent.action != Telephony.Sms.Intents.WAP_PUSH_DELIVER_ACTION && intent.action != Telephony.Sms.Intents.WAP_PUSH_DELIVER_ACTION
) return ) return
var from = ""
var message = ""
if (intent.action == Telephony.Sms.Intents.WAP_PUSH_RECEIVED_ACTION || intent.action == Telephony.Sms.Intents.WAP_PUSH_DELIVER_ACTION) { if (intent.action == Telephony.Sms.Intents.WAP_PUSH_RECEIVED_ACTION || intent.action == Telephony.Sms.Intents.WAP_PUSH_DELIVER_ACTION) {
from = intent.getStringExtra("address") ?: "" val contentType = intent.type
message = intent.getStringExtra("body") ?: "" if (contentType == "application/vnd.wap.mms-message") {
Log.d(TAG, "from = $from, message = $message") val pduType = intent.getStringExtra("transactionId")
if ("mms" == pduType) {
val bundle = intent.extras val data = intent.getByteArrayExtra("data")
bundle?.let { if (data != null) {
for (key in bundle.keySet()) { // 处理收到的 MMS 数据
val obj = bundle.get(key) handleMmsData(context, data)
if (obj is ByteArray) {
val data = String(obj)
// 解析彩信内容
parseMMSContent(data, from)
} }
} }
} }
from = intent.getStringExtra("address") ?: ""
Log.d(TAG, "from = $from, msg = $msg")
} else { } else {
for (smsMessage in Telephony.Sms.Intents.getMessagesFromIntent(intent)) { for (smsMessage in Telephony.Sms.Intents.getMessagesFromIntent(intent)) {
from = smsMessage.displayOriginatingAddress from = smsMessage.displayOriginatingAddress
message += smsMessage.messageBody msg += smsMessage.messageBody
} }
} }
Log.d(TAG, "from = $from, message = $message") Log.d(TAG, "from = $from, msg = $msg")
//短信指令 //短信指令
if (SettingUtils.enableSmsCommand && message.startsWith("smsf#")) { if (SettingUtils.enableSmsCommand && msg.startsWith("smsf#")) {
doSmsCommand(context, from, message) doSmsCommand(context, from, msg)
return return
} }
@ -107,7 +106,7 @@ class SmsReceiver : BroadcastReceiver() {
else -> "" else -> ""
} }
val msgInfo = MsgInfo("sms", from, message, Date(), simInfo, simSlot, subscription) val msgInfo = MsgInfo("sms", from, msg, Date(), simInfo, simSlot, subscription)
Log.d(TAG, "msgInfo = $msgInfo") Log.d(TAG, "msgInfo = $msgInfo")
val request = OneTimeWorkRequestBuilder<SendWorker>().setInputData( val request = OneTimeWorkRequestBuilder<SendWorker>().setInputData(
@ -146,55 +145,54 @@ class SmsReceiver : BroadcastReceiver() {
SmsCommandUtils.execute(context, smsCommand) SmsCommandUtils.execute(context, smsCommand)
} }
private fun parseMMSContent(data: String, sender: String?) { private fun handleMmsData(context: Context, data: ByteArray) {
// 在这里实现解析彩信内容的逻辑 try {
Log.d("MMSReceiver", "Received MMS from: $sender, Data: $data") val mmsClass = Class.forName("android.telephony.gsm.SmsMessage")
val method = mmsClass.getDeclaredMethod("createFromPdu", ByteArray::class.java)
val pdus = arrayOf(data)
val messages = mutableListOf<Any>()
val parts = data.split("\n\n") // 假设彩信内容以两个换行符 "\n\n" 分隔不同部分 for (pdu in pdus) {
parts.forEach { part -> val message = method.invoke(null, pdu)
val lines = part.split("\n") message?.let { messages.add(it) }
var contentType: String? = null
var content: String? = null
var contentTransferEncoding: String? = null
lines.forEach { line ->
Log.d(TAG, "Line: $line")
val keyValue = line.split(":")
if (keyValue.size == 2) {
val key = keyValue[0].trim()
val value = keyValue[1].trim()
when (key.toLowerCase()) {
"content-type" -> contentType = value
"content-transfer-encoding" -> contentTransferEncoding = value
}
}
} }
// 处理不同 MIME 类型的内容 // 处理 MMS 中的各个部分
contentType?.let { for (message in messages) {
when { // 获取 MMS 的各个部分
it.startsWith("text") -> { val parts = message.javaClass.getMethod("getParts").invoke(message) as? Array<*>
// 文本内容
content = lines.last() // 假设文本内容在当前部分的最后一行
// 处理文本内容,例如展示在 TextView 中
Log.d(TAG, "Text data: $content")
}
it.startsWith("image") -> { // 遍历 MMS 的各个部分
// 图片内容 parts?.forEach { part ->
// 如果 contentTransferEncoding 表示 base64 编码 // 获取部分的内容类型
if (contentTransferEncoding.equals("base64", true)) { val contentType = part?.javaClass?.getMethod("getContentType")?.invoke(part) as? String
content = lines.last() // 假设图片数据在当前部分的最后一行
// 解码图片数据并展示或保存图片 // 处理文本部分
val decodedImage = android.util.Base64.decode(content, android.util.Base64.DEFAULT) if (contentType?.startsWith("text/plain") == true) {
// 处理解码后的图片数据 val text = part.javaClass.getMethod("getData").invoke(part) as? String
Log.d(TAG, "Image data: $decodedImage") // 处理文本信息
if (text != null) {
Log.d(TAG, "Text: $text")
msg += text
} }
} }
// 可以根据其他 MIME 类型继续添加处理逻辑,比如视频、音频等
// 处理图像部分
if (contentType?.startsWith("image/") == true) {
val imageData = part.javaClass.getMethod("getData").invoke(part) as? ByteArray
// 处理图像信息
if (imageData != null) {
// 在这里你可以保存图像数据或进行其他处理
Log.d(TAG, "Image data received")
}
}
// 其他部分的处理可以根据需要继续扩展
} }
} }
} catch (e: Exception) {
e.printStackTrace()
} }
} }