|
@@ -0,0 +1,222 @@
|
|
|
+package com.hx.utils.application.ui.sms
|
|
|
+
|
|
|
+import android.Manifest.permission.READ_SMS
|
|
|
+import android.Manifest.permission.RECEIVE_SMS
|
|
|
+import android.Manifest.permission.SEND_SMS
|
|
|
+import android.app.DatePickerDialog
|
|
|
+import android.app.TimePickerDialog
|
|
|
+import android.app.role.RoleManager
|
|
|
+import android.content.ContentValues
|
|
|
+import android.content.Intent
|
|
|
+import android.os.Build
|
|
|
+import android.os.Bundle
|
|
|
+import android.provider.Telephony
|
|
|
+import android.view.LayoutInflater
|
|
|
+import android.view.View
|
|
|
+import android.view.ViewGroup
|
|
|
+import androidx.appcompat.app.AppCompatActivity
|
|
|
+import androidx.fragment.app.Fragment
|
|
|
+import androidx.lifecycle.ViewModelProvider
|
|
|
+import com.blankj.utilcode.util.AppUtils
|
|
|
+import com.blankj.utilcode.util.PermissionUtils
|
|
|
+import com.blankj.utilcode.util.TimeUtils
|
|
|
+import com.blankj.utilcode.util.ToastUtils
|
|
|
+import com.hx.utils.application.databinding.FragmentSmsBinding
|
|
|
+import kotlinx.coroutines.DelicateCoroutinesApi
|
|
|
+import kotlinx.coroutines.Dispatchers
|
|
|
+import kotlinx.coroutines.GlobalScope
|
|
|
+import kotlinx.coroutines.delay
|
|
|
+import kotlinx.coroutines.launch
|
|
|
+import java.util.Calendar
|
|
|
+
|
|
|
+class SmsFragment : Fragment() {
|
|
|
+ private var _binding: FragmentSmsBinding? = null
|
|
|
+ private val binding get() = _binding!!
|
|
|
+ private lateinit var smsViewModel: SmsViewModel
|
|
|
+
|
|
|
+ override fun onCreateView(
|
|
|
+ inflater: LayoutInflater,
|
|
|
+ container: ViewGroup?,
|
|
|
+ savedInstanceState: Bundle?
|
|
|
+ ): View {
|
|
|
+ _binding = FragmentSmsBinding.inflate(inflater, container, false)
|
|
|
+ val root: View = binding.root
|
|
|
+ smsViewModel = ViewModelProvider(this)[SmsViewModel::class.java]
|
|
|
+ binding.loading.visibility = View.GONE
|
|
|
+
|
|
|
+ smsViewModel.showTime.observe(viewLifecycleOwner) {
|
|
|
+ binding.time.setText(it)
|
|
|
+ }
|
|
|
+
|
|
|
+ binding.insertMms.setOnClickListener {
|
|
|
+ val smsPackageName = Telephony.Sms.getDefaultSmsPackage(context)
|
|
|
+ val currentPackageName = context?.packageName
|
|
|
+ if (smsPackageName != currentPackageName) {
|
|
|
+ val intent: Intent?
|
|
|
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
|
|
|
+ intent = Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT)
|
|
|
+ intent.putExtra(
|
|
|
+ Telephony.Sms.Intents.EXTRA_PACKAGE_NAME,
|
|
|
+ requireContext().packageName
|
|
|
+ )
|
|
|
+ requireContext().startActivity(intent)
|
|
|
+ } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
|
|
+ openSMSappChooser()
|
|
|
+ }
|
|
|
+ return@setOnClickListener
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ val name = binding.name.text?.toString().orEmpty()
|
|
|
+ val message = binding.message.text?.toString().orEmpty()
|
|
|
+ if (name.isBlank()) {
|
|
|
+ binding.name.error = "Not empty!"
|
|
|
+ return@setOnClickListener
|
|
|
+ }
|
|
|
+
|
|
|
+ if (message.isBlank()) {
|
|
|
+ binding.message.error = "Not empty!"
|
|
|
+ return@setOnClickListener
|
|
|
+ }
|
|
|
+
|
|
|
+ binding.loading.visibility = View.VISIBLE
|
|
|
+ insertSms()
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ binding.selectTime.setOnClickListener {
|
|
|
+ val calendar = Calendar.getInstance()
|
|
|
+ val datePickerDialog = DatePickerDialog(
|
|
|
+ requireActivity(),
|
|
|
+ { _, year, month, dayOfMonth ->
|
|
|
+ showTimePickerDialog(year, month, dayOfMonth)
|
|
|
+ },
|
|
|
+ calendar.get(Calendar.YEAR),
|
|
|
+ calendar.get(Calendar.MONTH),
|
|
|
+ calendar.get(Calendar.DAY_OF_MONTH)
|
|
|
+ )
|
|
|
+ datePickerDialog.show()
|
|
|
+ }
|
|
|
+
|
|
|
+ binding.radioGroup.setOnCheckedChangeListener { _, checkedId ->
|
|
|
+ smsViewModel.read.value = binding.radioButton1.id == checkedId
|
|
|
+ }
|
|
|
+
|
|
|
+ (activity as? AppCompatActivity)?.supportActionBar?.title = arguments?.getString("data")
|
|
|
+ return root
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun onStart() {
|
|
|
+ super.onStart()
|
|
|
+ getPermissions()
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun onDestroyView() {
|
|
|
+ super.onDestroyView()
|
|
|
+ _binding = null
|
|
|
+ }
|
|
|
+
|
|
|
+ fun getPermissions() {
|
|
|
+ val permissions = listOf(SEND_SMS, RECEIVE_SMS, READ_SMS).toTypedArray()
|
|
|
+ PermissionUtils.permission(*permissions)
|
|
|
+ .rationale { _, shouldRequest ->
|
|
|
+ run {
|
|
|
+ shouldRequest.again(true)
|
|
|
+ }
|
|
|
+ }.callback(object : PermissionUtils.FullCallback {
|
|
|
+ override fun onGranted(permissionsGranted: MutableList<String>) {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun onDenied(forever: MutableList<String>, denied: MutableList<String>) {
|
|
|
+ if (forever.isNotEmpty()) {
|
|
|
+ AppUtils.launchAppDetailsSettings()
|
|
|
+ } else {
|
|
|
+ getPermissions()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }).request()
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @OptIn(DelicateCoroutinesApi::class)
|
|
|
+ private fun insertSms() {
|
|
|
+ try {
|
|
|
+ val values = ContentValues().apply {
|
|
|
+ put(Telephony.Sms.ADDRESS, binding.name.text.toString())
|
|
|
+ put(Telephony.Sms.DATE, smsViewModel.time.value)
|
|
|
+ put(Telephony.Sms.DATE_SENT, smsViewModel.time.value?.minus(5000))
|
|
|
+ put(Telephony.Sms.READ, smsViewModel.read.value)
|
|
|
+ put(Telephony.Sms.TYPE, 1)
|
|
|
+ put(Telephony.Sms.BODY, binding.message.text.toString())
|
|
|
+ put(Telephony.Sms.TYPE, Telephony.Sms.MESSAGE_TYPE_INBOX)
|
|
|
+ }
|
|
|
+ context?.contentResolver?.insert(Telephony.Sms.CONTENT_URI, values)
|
|
|
+
|
|
|
+ binding.name.text.clear()
|
|
|
+ binding.message.text.clear()
|
|
|
+ smsViewModel.time.postValue(0)
|
|
|
+ smsViewModel.showTime.postValue("")
|
|
|
+
|
|
|
+ } catch (e: Exception) {
|
|
|
+ e.message?.let {
|
|
|
+ GlobalScope.launch(Dispatchers.Main) {
|
|
|
+ delay(2000)
|
|
|
+ ToastUtils.showLong(it)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } finally {
|
|
|
+ GlobalScope.launch(Dispatchers.Main) {
|
|
|
+ delay(2000)
|
|
|
+ binding.loading.visibility = View.GONE
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private fun showTimePickerDialog(year: Int, month: Int, dayOfMonth: Int) {
|
|
|
+ val calendar = Calendar.getInstance()
|
|
|
+ val timePickerDialog = TimePickerDialog(
|
|
|
+ requireActivity(),
|
|
|
+ { _, h, m ->
|
|
|
+ val selectedCalendar = Calendar.getInstance()
|
|
|
+ selectedCalendar.set(year, month, dayOfMonth, h, m)
|
|
|
+ val selectedTimestamp = selectedCalendar.timeInMillis
|
|
|
+
|
|
|
+ handleSelectedTimestamp(
|
|
|
+ selectedTimestamp,
|
|
|
+ TimeUtils.date2String(TimeUtils.millis2Date(selectedTimestamp))
|
|
|
+ )
|
|
|
+ },
|
|
|
+ calendar.get(Calendar.HOUR_OF_DAY),
|
|
|
+ calendar.get(Calendar.MINUTE),
|
|
|
+ true
|
|
|
+ )
|
|
|
+ timePickerDialog.show()
|
|
|
+ }
|
|
|
+
|
|
|
+ private fun handleSelectedTimestamp(timestamp: Long, showTxt: String) {
|
|
|
+ smsViewModel.time.postValue(timestamp)
|
|
|
+ smsViewModel.showTime.postValue(showTxt)
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private fun openSMSappChooser() {
|
|
|
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
|
|
+ val roleManager = context?.getSystemService(RoleManager::class.java)
|
|
|
+ if (roleManager!!.isRoleAvailable(RoleManager.ROLE_SMS)) {
|
|
|
+ if (!roleManager.isRoleHeld(RoleManager.ROLE_SMS)) {
|
|
|
+ val intent = roleManager.createRequestRoleIntent(RoleManager.ROLE_SMS)
|
|
|
+ startActivityForResult(intent, 1314)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ val intent = Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT)
|
|
|
+ intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, context?.packageName)
|
|
|
+ startActivity(intent)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+}
|