Я создаю приложение для обнаружения сбоев и хочу отправлять SMS-оповещения после обнаружения сбоя. Проблема, с которой я столкнулся, заключается в отправке сообщения. У меня есть номера телефонов, хранящиеся в базе данных SQLite, и я хочу отправлять им SMS-оповещения. Но при обнаружении сбоя logcat показывает ошибку: «FATAL EXCEPTION: main
Process: com.mainapp.app, PID: 13054
java.lang.IllegalArgumentException: Invalid DestinationAddress»
The формат телефонных номеров правильный, например имя контакта: john и номер контакта: 03331234567 (номер в Пакистане), но все равно выдает эту ошибку.
Это файл, который обнаруживает сбои, а также генерирует оповещения и SMS
package com.mainapp.app.modules.home
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.hardware.Sensor
import android.media.RingtoneManager
import android.os.Build
import android.telephony.SmsManager
import android.util.Log
import androidx.core.app.NotificationCompat
import com.mainapp.app.ml.TfliteModel
import com.mainapp.app.modules.contacts.data.database.ContactDatabaseHelper
import org.tensorflow.lite.DataType
import org.tensorflow.lite.support.tensorbuffer.TensorBuffer
class SensorDataProcessor(private val context: Context) {
private val model: TfliteModel = TfliteModel.newInstance(context)
private val contactDatabaseHelper = ContactDatabaseHelper(context)
fun preprocessDataAndDetectCrash(sensorType: Int, sensorValues: FloatArray) {
// Preprocess sensor data
val preprocessedValues = preprocessData(sensorType, sensorValues)
// Perform inference using TensorFlow Lite model
val crashProbability = runInference(preprocessedValues)
// Determine if a crash has occurred based on the inference result
processInferenceResult(crashProbability)
}
private fun preprocessData(sensorType: Int, values: FloatArray): FloatArray {
val preprocessedValues = when (sensorType) {
Sensor.TYPE_ACCELEROMETER -> preprocessAccelerometerData(values)
Sensor.TYPE_GYROSCOPE -> preprocessGyroscopeData(values)
Sensor.TYPE_GRAVITY -> preprocessGravityData(values)
Sensor.TYPE_ORIENTATION -> preprocessOrientationData(values)
Sensor.TYPE_ROTATION_VECTOR -> preprocessRotationVectorData(values)
Sensor.TYPE_LINEAR_ACCELERATION -> preprocessLinearAccelerationData(values)
else -> throw IllegalArgumentException("Unsupported sensor type: $sensorType")
}
return preprocessedValues
}
private fun preprocessAccelerometerData(values: FloatArray): FloatArray {
// Preprocess accelerometer data
// Ensure that the input shape matches [1, 21]
return values.copyOf(21)
}
private fun preprocessGyroscopeData(values: FloatArray): FloatArray {
// Preprocess gyroscope data
// Ensure that the input shape matches [1, 21]
return values.copyOf(21)
}
private fun preprocessGravityData(values: FloatArray): FloatArray {
// Preprocess gravity data
// Ensure that the input shape matches [1, 21]
return values.copyOf(21)
}
private fun preprocessOrientationData(values: FloatArray): FloatArray {
// Preprocess orientation data
// Ensure that the input shape matches [1, 21]
return values.copyOf(21)
}
private fun preprocessRotationVectorData(values: FloatArray): FloatArray {
// Preprocess rotation vector data
// Ensure that the input shape matches [1, 21]
return values.copyOf(21)
}
private fun preprocessLinearAccelerationData(values: FloatArray): FloatArray {
// Preprocess linear acceleration data
// Ensure that the input shape matches [1, 21]
return values.copyOf(21)
}
private fun runInference(inputData: FloatArray): Float {
// Create inputs for the TensorFlow Lite model
val inputFeature0 = TensorBuffer.createFixedSize(intArrayOf(1, inputData.size), DataType.FLOAT32)
inputFeature0.loadArray(inputData)
// Run model inference
val outputs = model.process(inputFeature0)
// Get the output feature (assuming it's a single value)
val outputFeature0 = outputs.outputFeature0AsTensorBuffer
// Extract and return the inference result
return outputFeature0.floatArray[0] // Assuming it's a single output value
}
fun processInferenceResult(crashProbability: Float) {
if (crashProbability > 4.004052544579376544) {
triggerAlarmAndSendSMS()
} else {
Log.d("CrashDetection", "No crash detected. Probability: $crashProbability")
}
}
private fun triggerAlarmAndSendSMS() {
startAlarm(context)
sendSMSAlerts()
}
private fun sendSMSAlerts() {
val contacts = contactDatabaseHelper.getAllContacts()
if (contacts.isNotEmpty()) {
val smsManager = SmsManager.getDefault()
for (contact in contacts) {
val message = "Emergency: A crash has been detected! Please check the user's location."
smsManager.sendTextMessage(contact.number, null, message, null, null)
Log.d("SMSAlert", "SMS sent to ${contact.name}")
}
} else {
Log.d("SMSAlert", "No contacts found in the database.")
}
}
private fun triggerAlarmAndPopup() {
// Start the alarm
startAlarm(context)
// Show notification with action to stop alarm
showNotificationWithAction("Crash Detected")
}
private fun showNotificationWithAction(message: String) {
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val notificationId = 1 // Use a unique ID for the notification
val channelId = "CrashChannel"
val channelName = "Crash Channel"
// Create an intent to stop the alarm
val stopIntent = Intent(context, StopAlertsReceiver::class.java)
stopIntent.action = "STOP_ALERTS_ACTION"
val pendingIntent = PendingIntent.getBroadcast(context, 0, stopIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) // Add FLAG_IMMUTABLE flag
// Create a notification with action button
val notification = NotificationCompat.Builder(context, channelId)
.setContentTitle("Crash Detected")
.setContentText(message)
.setSmallIcon(android.R.drawable.ic_dialog_alert)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setContentIntent(pendingIntent)
.addAction(android.R.drawable.ic_delete, "Stop Alarm", pendingIntent) // Action button to stop alarm
.build()
// Create notification channel if necessary
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_HIGH)
notificationManager.createNotificationChannel(channel)
}
// Show the notification
notificationManager.notify(notificationId, notification)
}
fun stopAlarm(context: Context) {
// Stop alarm sound
val alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM)
val ringtone = RingtoneManager.getRingtone(context, alarmSound)
ringtone.stop()
}
private fun startAlarm(context: Context) {
// Start alarm sound
val alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM)
val ringtone = RingtoneManager.getRingtone(context, alarmSound)
ringtone.play()
}
// Release resources when no longer used
fun close() {
contactDatabaseHelper.close()
}
}
и это класс базы данных
package com.mainapp.app.modules.contacts.data.database
import android.content.Context
import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteOpenHelper
import com.mainapp.app.modules.contacts.data.model.ContactsModel
class ContactDatabaseHelper(context: Context) : SQLiteOpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION) {
override fun onCreate(db: SQLiteDatabase) {
db.execSQL(SQL_CREATE_ENTRIES)
}
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
// Implement database upgrade logic if needed
}
fun getAllContacts(): List {
val contactList = mutableListOf()
val db = this.readableDatabase
val cursor = db.rawQuery("SELECT * FROM $TABLE_NAME", null)
cursor.use {
while (it.moveToNext()) {
val idIndex = it.getColumnIndex(COLUMN_ID)
val nameIndex = it.getColumnIndex(COLUMN_NAME)
val numberIndex = it.getColumnIndex(COLUMN_NUMBER)
// Check if column index is valid before retrieving data
val id = if (idIndex >= 0) it.getLong(idIndex) else 0
val name = if (nameIndex >= 0) it.getString(nameIndex) else ""
val number = if (numberIndex >= 0) it.getString(numberIndex) else ""
val contact = ContactsModel(id, name, number)
contactList.add(contact)
}
}
return contactList
}
companion object {
const val DATABASE_NAME = "contacts.db"
const val DATABASE_VERSION = 1
const val TABLE_NAME = "contacts"
const val COLUMN_ID = "_id"
const val COLUMN_NAME = "name"
const val COLUMN_NUMBER = "number"
private const val SQL_CREATE_ENTRIES = """
CREATE TABLE $TABLE_NAME (
$COLUMN_ID INTEGER PRIMARY KEY,
$COLUMN_NAME TEXT,
$COLUMN_NUMBER TEXT
)
"""
}
}
Подробнее здесь: https://stackoverflow.com/questions/783 ... -in-kotlin
Как отправлять SMS-оповещения на номера телефонов, хранящиеся в базе данных SQLite в Котлине ⇐ Android
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение