mirror of
https://github.com/SimpleMobileTools/Simple-SMS-Messenger.git
synced 2025-06-05 21:49:22 +02:00
Added additional types for txt or xml and moved import logic to Importer
This commit is contained in:
@@ -28,6 +28,7 @@ import kotlin.system.exitProcess
|
|||||||
class SettingsActivity : SimpleActivity() {
|
class SettingsActivity : SimpleActivity() {
|
||||||
private var blockedNumbersAtPause = -1
|
private var blockedNumbersAtPause = -1
|
||||||
private val messagesFileType = "application/json"
|
private val messagesFileType = "application/json"
|
||||||
|
private val messageImportFileType = "application/json, application/xml, text/plain"
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
isMaterialActivity = true
|
isMaterialActivity = true
|
||||||
@@ -83,7 +84,13 @@ class SettingsActivity : SimpleActivity() {
|
|||||||
private val getContent = registerForActivityResult(ActivityResultContracts.GetContent()) { uri ->
|
private val getContent = registerForActivityResult(ActivityResultContracts.GetContent()) { uri ->
|
||||||
if (uri != null) {
|
if (uri != null) {
|
||||||
toast(R.string.importing)
|
toast(R.string.importing)
|
||||||
importMessages(uri)
|
MessagesImporter(this).importMessages(uri) { deserializedList ->
|
||||||
|
if (deserializedList.isEmpty()) {
|
||||||
|
toast(R.string.no_entries_for_importing)
|
||||||
|
} else {
|
||||||
|
ImportMessagesDialog(this, deserializedList)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,7 +111,7 @@ class SettingsActivity : SimpleActivity() {
|
|||||||
|
|
||||||
private fun setupMessagesImport() {
|
private fun setupMessagesImport() {
|
||||||
settings_import_messages_holder.setOnClickListener {
|
settings_import_messages_holder.setOnClickListener {
|
||||||
getContent.launch(messagesFileType)
|
getContent.launch(messageImportFileType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,27 +138,6 @@ class SettingsActivity : SimpleActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun importMessages(uri: Uri) {
|
|
||||||
try {
|
|
||||||
val jsonString = contentResolver.openInputStream(uri)!!.use { inputStream ->
|
|
||||||
inputStream.bufferedReader().readText()
|
|
||||||
}
|
|
||||||
|
|
||||||
val deserializedList = Json.decodeFromString<List<MessagesBackup>>(jsonString)
|
|
||||||
if (deserializedList.isEmpty()) {
|
|
||||||
toast(R.string.no_entries_for_importing)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ImportMessagesDialog(this, deserializedList)
|
|
||||||
} catch (e: SerializationException) {
|
|
||||||
toast(R.string.invalid_file_format)
|
|
||||||
} catch (e: IllegalArgumentException) {
|
|
||||||
toast(R.string.invalid_file_format)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
showErrorToast(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
super.onPause()
|
super.onPause()
|
||||||
blockedNumbersAtPause = getBlockedNumbers().hashCode()
|
blockedNumbersAtPause = getBlockedNumbers().hashCode()
|
||||||
|
@@ -48,7 +48,7 @@ class ImportMessagesDialog(
|
|||||||
config.importSms = view.import_sms_checkbox.isChecked
|
config.importSms = view.import_sms_checkbox.isChecked
|
||||||
config.importMms = view.import_mms_checkbox.isChecked
|
config.importMms = view.import_mms_checkbox.isChecked
|
||||||
ensureBackgroundThread {
|
ensureBackgroundThread {
|
||||||
MessagesImporter(activity).importMessages(messages) {
|
MessagesImporter(activity).restoreMessages(messages) {
|
||||||
handleParseResult(it)
|
handleParseResult(it)
|
||||||
alertDialog.dismiss()
|
alertDialog.dismiss()
|
||||||
}
|
}
|
||||||
|
@@ -1,20 +1,68 @@
|
|||||||
package com.simplemobiletools.smsmessenger.helpers
|
package com.simplemobiletools.smsmessenger.helpers
|
||||||
|
|
||||||
import android.content.Context
|
import android.net.Uri
|
||||||
|
import android.util.Xml
|
||||||
import com.simplemobiletools.commons.extensions.showErrorToast
|
import com.simplemobiletools.commons.extensions.showErrorToast
|
||||||
|
import com.simplemobiletools.commons.extensions.toast
|
||||||
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
||||||
|
import com.simplemobiletools.smsmessenger.R
|
||||||
|
import com.simplemobiletools.smsmessenger.activities.SimpleActivity
|
||||||
|
import com.simplemobiletools.smsmessenger.dialogs.ImportMessagesDialog
|
||||||
import com.simplemobiletools.smsmessenger.extensions.config
|
import com.simplemobiletools.smsmessenger.extensions.config
|
||||||
import com.simplemobiletools.smsmessenger.models.*
|
import com.simplemobiletools.smsmessenger.models.*
|
||||||
|
import kotlinx.serialization.SerializationException
|
||||||
|
import kotlinx.serialization.decodeFromString
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import org.xmlpull.v1.XmlPullParser
|
||||||
|
import java.io.InputStream
|
||||||
|
|
||||||
|
|
||||||
class MessagesImporter(private val context: Context) {
|
class MessagesImporter(private val activity: SimpleActivity) {
|
||||||
|
|
||||||
private val messageWriter = MessagesWriter(context)
|
private val messageWriter = MessagesWriter(activity)
|
||||||
private val config = context.config
|
private val config = activity.config
|
||||||
private var messagesImported = 0
|
private var messagesImported = 0
|
||||||
private var messagesFailed = 0
|
private var messagesFailed = 0
|
||||||
|
|
||||||
fun importMessages(messagesBackup: List<MessagesBackup>, callback: (result: ImportResult) -> Unit) {
|
fun importMessages(uri: Uri) {
|
||||||
|
try {
|
||||||
|
val fileType = activity.contentResolver.getType(uri).orEmpty()
|
||||||
|
|
||||||
|
val isXml = isXmlMimeType(fileType) || (uri.path?.endsWith("txt") == true && isFileXml(uri))
|
||||||
|
|
||||||
|
if (isXml) {
|
||||||
|
getInputStreamFromUri(uri)!!.importXml()
|
||||||
|
} else {
|
||||||
|
importJson(uri)
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (e: Exception) {
|
||||||
|
activity.showErrorToast(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun importJson(uri: Uri) {
|
||||||
|
try {
|
||||||
|
val jsonString = activity.contentResolver.openInputStream(uri)!!.use { inputStream ->
|
||||||
|
inputStream.bufferedReader().readText()
|
||||||
|
}
|
||||||
|
|
||||||
|
val deserializedList = Json.decodeFromString<List<MessagesBackup>>(jsonString)
|
||||||
|
if (deserializedList.isEmpty()) {
|
||||||
|
activity.toast(R.string.no_entries_for_importing)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ImportMessagesDialog(activity, deserializedList)
|
||||||
|
} catch (e: SerializationException) {
|
||||||
|
activity.toast(R.string.invalid_file_format)
|
||||||
|
} catch (e: IllegalArgumentException) {
|
||||||
|
activity.toast(R.string.invalid_file_format)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
activity.showErrorToast(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun restoreMessages(messagesBackup: List<MessagesBackup>, callback: (ImportResult) -> Unit) {
|
||||||
ensureBackgroundThread {
|
ensureBackgroundThread {
|
||||||
try {
|
try {
|
||||||
messagesBackup.forEach { message ->
|
messagesBackup.forEach { message ->
|
||||||
@@ -23,17 +71,16 @@ class MessagesImporter(private val context: Context) {
|
|||||||
messageWriter.writeSmsMessage(message as SmsBackup)
|
messageWriter.writeSmsMessage(message as SmsBackup)
|
||||||
} else if (message.backupType == BackupType.MMS && config.importMms) {
|
} else if (message.backupType == BackupType.MMS && config.importMms) {
|
||||||
messageWriter.writeMmsMessage(message as MmsBackup)
|
messageWriter.writeMmsMessage(message as MmsBackup)
|
||||||
}
|
} else return@forEach
|
||||||
else return@forEach
|
|
||||||
messagesImported++
|
messagesImported++
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
context.showErrorToast(e)
|
activity.showErrorToast(e)
|
||||||
messagesFailed++
|
messagesFailed++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
refreshMessages()
|
refreshMessages()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
context.showErrorToast(e)
|
activity.showErrorToast(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
callback.invoke(
|
callback.invoke(
|
||||||
@@ -46,4 +93,96 @@ class MessagesImporter(private val context: Context) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun InputStream.importXml() {
|
||||||
|
bufferedReader().use { reader ->
|
||||||
|
val xmlParser = Xml.newPullParser().apply {
|
||||||
|
setInput(reader)
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlParser.nextTag()
|
||||||
|
xmlParser.require(XmlPullParser.START_TAG, null, "smses")
|
||||||
|
|
||||||
|
var depth = 1
|
||||||
|
while (depth != 0) {
|
||||||
|
when (xmlParser.next()) {
|
||||||
|
XmlPullParser.END_TAG -> depth--
|
||||||
|
XmlPullParser.START_TAG -> depth++
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xmlParser.eventType != XmlPullParser.START_TAG) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (xmlParser.name == "sms") {
|
||||||
|
if (config.importSms) {
|
||||||
|
val message = xmlParser.readSms()
|
||||||
|
messageWriter.writeSmsMessage(message)
|
||||||
|
messagesImported++
|
||||||
|
} else {
|
||||||
|
xmlParser.skip()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
xmlParser.skip()
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
activity.showErrorToast(e)
|
||||||
|
messagesFailed++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
refreshMessages()
|
||||||
|
}
|
||||||
|
// TODO: Add result to xml import
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun XmlPullParser.readSms(): SmsBackup {
|
||||||
|
require(XmlPullParser.START_TAG, null, "sms")
|
||||||
|
|
||||||
|
return SmsBackup(
|
||||||
|
subscriptionId = 0,
|
||||||
|
address = getAttributeValue(null, "address"),
|
||||||
|
body = getAttributeValue(null, "body"),
|
||||||
|
date = getAttributeValue(null, "date").toLong(),
|
||||||
|
dateSent = getAttributeValue(null, "date").toLong(),
|
||||||
|
locked = getAttributeValue(null, "locked").toInt(),
|
||||||
|
protocol = getAttributeValue(null, "protocol"),
|
||||||
|
read = getAttributeValue(null, "read").toInt(),
|
||||||
|
status = getAttributeValue(null, "status").toInt(),
|
||||||
|
type = getAttributeValue(null, "type").toInt(),
|
||||||
|
serviceCenter = getAttributeValue(null, "service_center")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun XmlPullParser.skip() {
|
||||||
|
if (eventType != XmlPullParser.START_TAG) {
|
||||||
|
throw IllegalStateException()
|
||||||
|
}
|
||||||
|
var depth = 1
|
||||||
|
while (depth != 0) {
|
||||||
|
when (next()) {
|
||||||
|
XmlPullParser.END_TAG -> depth--
|
||||||
|
XmlPullParser.START_TAG -> depth++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getInputStreamFromUri(uri: Uri): InputStream? {
|
||||||
|
return try {
|
||||||
|
activity.contentResolver.openInputStream(uri)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isFileXml(uri: Uri): Boolean {
|
||||||
|
val inputStream = getInputStreamFromUri(uri)
|
||||||
|
return inputStream?.bufferedReader()?.use { reader ->
|
||||||
|
reader.readLine()?.startsWith("<?xml") ?: false
|
||||||
|
} ?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isXmlMimeType(mimeType: String): Boolean {
|
||||||
|
return mimeType.equals("application/xml", ignoreCase = true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user