package com.example.firstapp
|
|
import android.content.IntentFilter
|
import android.os.Bundle
|
import android.provider.Telephony
|
import android.widget.Toast
|
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.appcompat.app.AppCompatActivity
|
import androidx.core.content.ContextCompat
|
import androidx.navigation.findNavController
|
import androidx.navigation.ui.setupWithNavController
|
import com.example.firstapp.databinding.ActivityMainBinding
|
import com.example.firstapp.receiver.SmsReceiver
|
import android.Manifest
|
import android.content.Context
|
import android.content.Intent
|
import android.net.Uri
|
import android.os.Build
|
import androidx.annotation.RequiresApi
|
import androidx.work.ExistingPeriodicWorkPolicy
|
import androidx.work.PeriodicWorkRequestBuilder
|
import androidx.work.WorkManager
|
import com.example.firstapp.activity.LoginActivity
|
import com.example.firstapp.adapter.MyAdapter
|
import com.example.firstapp.core.Core
|
import com.example.firstapp.database.entity.Code
|
import com.example.firstapp.database.entity.Msg
|
import com.example.firstapp.database.service.RetrofitClient
|
import com.example.firstapp.ui.home.HomeViewModel
|
import com.example.firstapp.utils.Log
|
import com.example.firstapp.workers.KeywordUpdateWorker
|
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.launch
|
import java.text.SimpleDateFormat
|
import java.time.LocalDateTime
|
import java.util.Calendar
|
import java.util.Date
|
import java.util.Locale
|
import java.util.concurrent.TimeUnit
|
import java.time.ZoneId
|
|
class MainActivity : AppCompatActivity() {
|
// 安全防护关键词数组
|
private var securityKeywordsList = emptyList<String>()
|
|
private lateinit var binding: ActivityMainBinding
|
|
private var smsReceiver: SmsReceiver? = null
|
|
private lateinit var adapter: MyAdapter
|
private lateinit var homeViewModel: HomeViewModel
|
|
private val multiplePermissionRequest =
|
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
|
when {
|
permissions.getOrDefault(
|
Manifest.permission.RECEIVE_SMS,
|
false
|
) && permissions.getOrDefault(Manifest.permission.READ_SMS, false) -> {
|
// 两个权限都获得授权
|
registerSmsReceiver()
|
// syncRecentSms()
|
// initializeSecurityKeywords()
|
}
|
|
else -> {
|
// 有权限被拒绝
|
Toast.makeText(
|
this, "需要短信读取和接收权限才能正常使用功能", Toast.LENGTH_SHORT
|
).show()
|
}
|
}
|
}
|
|
private val syncLock = Object()
|
|
@RequiresApi(Build.VERSION_CODES.O)
|
override fun onCreate(savedInstanceState: Bundle?) {
|
super.onCreate(savedInstanceState)
|
|
binding = ActivityMainBinding.inflate(layoutInflater)
|
setContentView(binding.root)
|
setupViews()
|
// binding.btnLogout.setOnClickListener {
|
// logout()
|
// }
|
// 在此位置初始化 homeViewModel
|
// homeViewModel = ViewModelProvider(this).get(HomeViewModel::class.java)
|
//
|
// val navView: BottomNavigationView = binding.navView
|
val navView = binding.navView
|
val navController = findNavController(R.id.nav_host_fragment_activity_main)
|
|
// 只保留底部导航的设置
|
navView.setupWithNavController(navController)
|
|
// 检查权限
|
if (ContextCompat.checkSelfPermission(
|
this, Manifest.permission.RECEIVE_SMS
|
) != android.content.pm.PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(
|
this, Manifest.permission.READ_SMS
|
) != android.content.pm.PackageManager.PERMISSION_GRANTED
|
) {
|
// 同时请求两个权限
|
multiplePermissionRequest.launch(
|
arrayOf(
|
Manifest.permission.RECEIVE_SMS, Manifest.permission.READ_SMS
|
)
|
)
|
} else {
|
// 权限已经授予,继续执行相关操作
|
registerSmsReceiver()
|
syncRecentSms()
|
}
|
// val recyclerView = findViewById<RecyclerView>(R.id.recyclerView)
|
// recyclerView.layoutManager = LinearLayoutManager(this)
|
//
|
// // 初始化适配器
|
// adapter = MyAdapter()
|
// recyclerView.adapter = adapter
|
//
|
// // 观察 LiveData 数据
|
// homeViewModel.codeList.observe(this) { codeList ->
|
// // 如果 codeList 为 null,避免闪退
|
// if (codeList != null) {
|
// adapter.submitList(codeList)
|
// // 滚动到顶部
|
// recyclerView.scrollToPosition(0)
|
// } else {
|
// // 如果数据为空,可以显示空列表或其他处理
|
// Toast.makeText(this, "No data available", Toast.LENGTH_SHORT).show()
|
// }
|
// }
|
|
// // 注册广播接收器来监听数据更新
|
// val filter = IntentFilter("com.example.firstapp.DATA_UPDATED")
|
// registerReceiver(object : BroadcastReceiver() {
|
// override fun onReceive(context: Context, intent: Intent) {
|
// // 数据已更新,刷新 LiveData
|
// homeViewModel.loadData()
|
// }
|
// }, filter)
|
|
}
|
|
private fun registerSmsReceiver() {
|
// 应用启动时执行 registerSmsReceiver()
|
// 创建 SmsReceiver 实例
|
// 注册广播接收器,开始监听短信
|
// 等待新短信到达
|
// 新短信到达时,系统发送广播
|
// SmsReceiver 的 onReceive 方法被调用
|
// 处理短信内容
|
// 发送数据更新广播
|
// MainActivity 接收到更新广播
|
// 更新 UI
|
Log.d("SMS_DEBUG", "MainActivity收到数据更新广播")
|
smsReceiver = SmsReceiver()
|
val filter = IntentFilter(Telephony.Sms.Intents.SMS_RECEIVED_ACTION)
|
registerReceiver(smsReceiver, filter)
|
}
|
|
private fun setupKeywordUpdate() {
|
val updateRequest = PeriodicWorkRequestBuilder<KeywordUpdateWorker>(
|
1, TimeUnit.HOURS, // 每小时更新一次
|
15, TimeUnit.MINUTES // 灵活时间窗口
|
).build()
|
|
WorkManager.getInstance(this).enqueueUniquePeriodicWork(
|
"keyword_update", ExistingPeriodicWorkPolicy.REPLACE, updateRequest
|
)
|
}
|
|
private fun setupViews() {
|
// 获取并显示当前登录的手机号
|
val phone =
|
getSharedPreferences("user_info", Context.MODE_PRIVATE).getString("phone", "") ?: ""
|
|
// binding.apply {
|
// tvPhone.text = "当前登录手机号:$phone"
|
// }
|
}
|
|
private fun logout() {
|
// 清除登录信息
|
getSharedPreferences("user_info", Context.MODE_PRIVATE).edit().clear().apply()
|
|
// 跳转回登录页
|
startActivity(Intent(this, LoginActivity::class.java))
|
finish()
|
}
|
|
// 初始化禁用词
|
@RequiresApi(Build.VERSION_CODES.O)
|
private fun initializeSecurityKeywords() {
|
CoroutineScope(Dispatchers.IO).launch {
|
try {
|
val response = RetrofitClient.apiService.getSecurityList()
|
if (response.code == 200) {
|
securityKeywordsList = response.data.map { it.keyword }
|
android.util.Log.d(
|
"MainActivity", "securityKeywordsList: $securityKeywordsList"
|
)
|
// 确保在主线程中调用 syncRecentSms
|
runOnUiThread {
|
syncRecentSms()
|
}
|
} else {
|
android.util.Log.e(
|
"MainActivity", "Failed to get security list: ${response.code}"
|
)
|
}
|
} catch (e: Exception) {
|
android.util.Log.e("MainActivity", "Error fetching security list", e)
|
}
|
}
|
}
|
|
@RequiresApi(Build.VERSION_CODES.O)
|
private fun syncRecentSms() {
|
try {
|
val calendar = Calendar.getInstance()
|
calendar.add(Calendar.DAY_OF_YEAR, -3)
|
val threeDaysAgo = calendar.timeInMillis
|
|
val cursor = contentResolver.query(
|
Uri.parse("content://sms/inbox"),
|
arrayOf("address", "body", "date"),
|
"date >= ?",
|
arrayOf(threeDaysAgo.toString()),
|
"date DESC"
|
)
|
|
cursor?.use {
|
while (cursor.moveToNext()) {
|
val messageBody = cursor.getString(cursor.getColumnIndexOrThrow("body"))
|
val datetime = cursor.getLong(cursor.getColumnIndexOrThrow("date"))
|
|
// 转换为 Date 对象
|
val date = Date(datetime)
|
val sdf = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
|
val dateString = sdf.format(date)
|
|
// 保存原始短信
|
val msg = Msg(0, "1111", "111111", messageBody, 1, "111", 1, 1)
|
val msgId = Core.msg.insert(msg)
|
|
// 禁用关键词拦截
|
if (securityKeywordsList.any { it in messageBody }) {
|
android.util.Log.d("MainActivity", "历史短信含有禁用关键词,跳过处理")
|
continue
|
}
|
|
// 使用协程处理API调用和数据库操作
|
CoroutineScope(Dispatchers.IO).launch {
|
try {
|
// API调用移到synchronized块外
|
val response = RetrofitClient.apiService.processSms(mapOf("content" to messageBody))
|
|
// 数据库操作放在synchronized块内
|
synchronized(syncLock) {
|
if (response.status == "success") {
|
when (response.data.category) {
|
"快递" -> {
|
val existingCode = Core.code.queryByTypeAndCodeAndDate(
|
response.data.category,
|
response.data.details.pickupCode ?: "",
|
dateString
|
)
|
|
if (existingCode == null) {
|
val code = Code(
|
id = 0,
|
category = response.data.category,
|
categoryId = 1,
|
typeId = 1,
|
ruleId = 1,
|
msgId = msgId,
|
createTime = dateString,
|
oneLevel = response.data.details.post ?: "",
|
secondLevel = response.data.details.company ?: "",
|
code = response.data.details.pickupCode ?: "",
|
pickup = 0,
|
pickupTime = "",
|
overTime = "",
|
address = response.data.details.address ?: "",
|
remarks = response.data.details.time ?: "",
|
)
|
if(code.oneLevel!="" && code.secondLevel!="" && code.code!="") {
|
Core.code.insert(code)
|
}
|
android.util.Log.d("MainActivity", "历史快递短信已保存: ${response.data.details.pickupCode}")
|
} else {
|
android.util.Log.d("MainActivity", "发现重复快递短信,跳过保存: ${response.data.details.pickupCode}")
|
}
|
}
|
"还款" -> {
|
val existingCode = Core.code.queryByTypeAndCodeAndDate(
|
response.data.category,
|
response.data.details.amount ?: "",
|
dateString
|
)
|
|
if (existingCode == null) {
|
val code = Code(
|
id = 0,
|
category = response.data.category,
|
categoryId = 2,
|
typeId = 1,
|
ruleId = 2,
|
msgId = msgId,
|
createTime = dateString,
|
oneLevel = response.data.details.type ?: "",
|
secondLevel = response.data.details.bank ?: "",
|
code = response.data.details.amount ?: "",
|
pickup = 0,
|
pickupTime = "",
|
overTime = response.data.details.date ?: "",
|
address = response.data.details.address ?: "",
|
remarks = "最小还款金额${response.data.details.min_amount}还款卡号${response.data.details.number}"
|
)
|
if(code.oneLevel!="" && code.secondLevel!="" && code.code!="") {
|
Core.code.insert(code)
|
}
|
android.util.Log.d("MainActivity", "历史还款短信已保存: ${response.data.details.amount}")
|
} else {
|
android.util.Log.d("MainActivity", "发现重复还款短信,跳过保存: ${response.data.details.amount}")
|
}
|
}
|
|
"收入" -> {
|
val existingCode = Core.code.queryByTypeAndCodeAndDate(
|
response.data.category,
|
response.data.details.amount ?: "",
|
dateString
|
)
|
|
if (existingCode == null) {
|
val code = Code(
|
id = 0,
|
category = response.data.category,
|
categoryId = 3, // 3-收入类型
|
typeId = 1, //暂时没有根据type分类
|
ruleId = 2, //1-还款类型
|
msgId = msgId,
|
createTime = dateString,
|
oneLevel = response.data.details.bank ?: "",
|
secondLevel = response.data.details.bank ?: "",
|
code = response.data.details.amount ?: "",
|
pickup = 0, // 0-未取件,1-已取件
|
pickupTime = "", // 取件时间为空
|
overTime = response.data.details.datetime
|
?: "", // 超时时间为空,暂时没有这块处理逻辑
|
address = response.data.details.address ?: "",
|
remarks = "余额" + response.data.details.balance ?: "",
|
)
|
if(code.oneLevel!="" && code.secondLevel!="" && code.code!="") {
|
Core.code.insert(code)
|
}
|
android.util.Log.d("MainActivity", "历史还款短信已保存: ${response.data.details.amount}")
|
} else {
|
android.util.Log.d("MainActivity", "发现重复还款短信,跳过保存: ${response.data.details.amount}")
|
}
|
}
|
}
|
|
// 发送广播通知数据已更新
|
val updateIntent = Intent("com.example.firstapp.DATA_UPDATED")
|
sendBroadcast(updateIntent)
|
}
|
}
|
} catch (e: Exception) {
|
android.util.Log.e("MainActivity", "处理历史短信出错: ${e.message}", e)
|
}
|
}
|
}
|
}
|
} catch (e: Exception) {
|
e.printStackTrace()
|
Toast.makeText(this, "同步短信失败:${e.message}", Toast.LENGTH_SHORT).show()
|
}
|
}
|
}
|