mirror of
https://github.com/SimpleMobileTools/Simple-SMS-Messenger.git
synced 2025-06-05 21:49:22 +02:00
@@ -1,6 +1,14 @@
|
||||
Changelog
|
||||
==========
|
||||
|
||||
Version 5.8.0 *(2021-01-02)*
|
||||
----------------------------
|
||||
|
||||
* Improved delivery reports, show a notification at failed messages
|
||||
* Allow resending failed messages with tapping them
|
||||
* Added multiple dual-SIM related improvements
|
||||
* Many other UX, stability, performance and translation improvements
|
||||
|
||||
Version 5.7.0 *(2020-12-30)*
|
||||
----------------------------
|
||||
|
||||
|
@@ -16,8 +16,8 @@ android {
|
||||
applicationId "com.simplemobiletools.smsmessenger"
|
||||
minSdkVersion 22
|
||||
targetSdkVersion 30
|
||||
versionCode 23
|
||||
versionName "5.7.0"
|
||||
versionCode 25
|
||||
versionName "5.8.0"
|
||||
setProperty("archivesBaseName", "sms-messenger")
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.simplemobiletools:commons:5.32.19'
|
||||
implementation 'com.simplemobiletools:commons:5.32.20'
|
||||
implementation 'org.greenrobot:eventbus:3.2.0'
|
||||
implementation 'com.klinkerapps:android-smsmms:5.2.6'
|
||||
implementation 'com.github.tibbi:IndicatorFastScroll:08f512858a'
|
||||
|
@@ -121,6 +121,10 @@
|
||||
|
||||
<service android:name="com.android.mms.transaction.TransactionService" />
|
||||
|
||||
<receiver android:name=".receivers.SmsStatusSentReceiver" />
|
||||
|
||||
<receiver android:name=".receivers.SmsStatusDeliveredReceiver" />
|
||||
|
||||
<receiver
|
||||
android:name=".receivers.SmsReceiver"
|
||||
android:permission="android.permission.BROADCAST_SMS">
|
||||
@@ -149,11 +153,6 @@
|
||||
android:exported="true"
|
||||
android:taskAffinity="com.klinker.android.messaging.MMS_RECEIVED" />
|
||||
|
||||
<receiver
|
||||
android:name=".receivers.SmsSentReceiver"
|
||||
android:exported="true"
|
||||
android:taskAffinity="${applicationId}.SMS_SENT" />
|
||||
|
||||
<receiver
|
||||
android:name=".receivers.MarkAsReadReceiver"
|
||||
android:enabled="true"
|
||||
|
@@ -8,6 +8,7 @@ import android.graphics.drawable.Drawable
|
||||
import android.media.MediaMetadataRetriever
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.provider.Telephony
|
||||
import android.telephony.SubscriptionManager
|
||||
import android.text.TextUtils
|
||||
@@ -39,6 +40,9 @@ import com.simplemobiletools.smsmessenger.adapters.ThreadAdapter
|
||||
import com.simplemobiletools.smsmessenger.extensions.*
|
||||
import com.simplemobiletools.smsmessenger.helpers.*
|
||||
import com.simplemobiletools.smsmessenger.models.*
|
||||
import com.simplemobiletools.smsmessenger.receivers.SmsStatusDeliveredReceiver
|
||||
import com.simplemobiletools.smsmessenger.receivers.SmsStatusSentReceiver
|
||||
import kotlinx.android.synthetic.main.activity_main.*
|
||||
import kotlinx.android.synthetic.main.activity_thread.*
|
||||
import kotlinx.android.synthetic.main.item_attachment.view.*
|
||||
import kotlinx.android.synthetic.main.item_selected_contact.view.*
|
||||
@@ -53,6 +57,7 @@ class ThreadActivity : SimpleActivity() {
|
||||
private var threadId = 0L
|
||||
private var currentSIMCardIndex = 0
|
||||
private var isActivityVisible = false
|
||||
private var refreshedSinceSent = false
|
||||
private var threadItems = ArrayList<ThreadItem>()
|
||||
private var bus: EventBus? = null
|
||||
private var participants = ArrayList<SimpleContact>()
|
||||
@@ -219,8 +224,18 @@ class ThreadActivity : SimpleActivity() {
|
||||
invalidateOptionsMenu()
|
||||
|
||||
runOnUiThread {
|
||||
val adapter = ThreadAdapter(this, threadItems, thread_messages_list, thread_messages_fastscroller) {}
|
||||
thread_messages_list.adapter = adapter
|
||||
val currAdapter = thread_messages_list.adapter
|
||||
if (currAdapter == null) {
|
||||
ThreadAdapter(this, threadItems, thread_messages_list, thread_messages_fastscroller) {
|
||||
(it as? ThreadError)?.apply {
|
||||
thread_type_message.setText(it.messageText)
|
||||
}
|
||||
}.apply {
|
||||
thread_messages_list.adapter = this
|
||||
}
|
||||
} else {
|
||||
(currAdapter as ThreadAdapter).updateMessages(threadItems)
|
||||
}
|
||||
}
|
||||
|
||||
SimpleContactsHelper(this).getAvailableContacts(false) { contacts ->
|
||||
@@ -509,7 +524,11 @@ class ThreadActivity : SimpleActivity() {
|
||||
items.add(message)
|
||||
|
||||
if (message.type == Telephony.Sms.MESSAGE_TYPE_FAILED) {
|
||||
items.add(ThreadError(message.id))
|
||||
items.add(ThreadError(message.id, message.body))
|
||||
}
|
||||
|
||||
if (message.type == Telephony.Sms.MESSAGE_TYPE_OUTBOX) {
|
||||
items.add(ThreadSending(message.id))
|
||||
}
|
||||
|
||||
if (!message.read) {
|
||||
@@ -637,12 +656,24 @@ class ThreadActivity : SimpleActivity() {
|
||||
}
|
||||
|
||||
try {
|
||||
transaction.sendNewMessage(message, threadId)
|
||||
val smsSentIntent = Intent(this, SmsStatusSentReceiver::class.java)
|
||||
val deliveredIntent = Intent(this, SmsStatusDeliveredReceiver::class.java)
|
||||
|
||||
transaction.setExplicitBroadcastForSentSms(smsSentIntent)
|
||||
transaction.setExplicitBroadcastForDeliveredSms(deliveredIntent)
|
||||
|
||||
refreshedSinceSent = false
|
||||
transaction.sendNewMessage(message, threadId)
|
||||
thread_type_message.setText("")
|
||||
attachmentUris.clear()
|
||||
thread_attachments_holder.beGone()
|
||||
thread_attachments_wrapper.removeAllViews()
|
||||
|
||||
Handler().postDelayed({
|
||||
if (!refreshedSinceSent) {
|
||||
refreshMessages()
|
||||
}
|
||||
}, 2000)
|
||||
} catch (e: Exception) {
|
||||
showErrorToast(e)
|
||||
} catch (e: Error) {
|
||||
@@ -704,8 +735,10 @@ class ThreadActivity : SimpleActivity() {
|
||||
showSelectedContacts()
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
@Subscribe(threadMode = ThreadMode.ASYNC)
|
||||
fun refreshMessages(event: Events.RefreshMessages) {
|
||||
refreshedSinceSent = true
|
||||
if (isActivityVisible) {
|
||||
notificationManager.cancel(threadId.hashCode())
|
||||
}
|
||||
@@ -713,8 +746,17 @@ class ThreadActivity : SimpleActivity() {
|
||||
val lastMaxId = messages.maxByOrNull { it.id }?.id ?: 0L
|
||||
messages = getMessages(threadId)
|
||||
|
||||
messages.filter { !it.isReceivedMessage() && it.id > lastMaxId }.forEach {
|
||||
messagesDB.insertOrIgnore(it)
|
||||
messages.filter { !it.isReceivedMessage() && it.id > lastMaxId }.forEach { latestMessage ->
|
||||
// subscriptionIds seem to be not filled out at sending with multiple SIM cards, so fill it manually
|
||||
if (SubscriptionManager.from(this).activeSubscriptionInfoList?.size ?: 0 > 1) {
|
||||
val SIMId = availableSIMCards.getOrNull(currentSIMCardIndex)?.subscriptionId
|
||||
if (SIMId != null) {
|
||||
updateMessageSubscriptionId(latestMessage.id, SIMId)
|
||||
latestMessage.subscriptionId = SIMId
|
||||
}
|
||||
}
|
||||
|
||||
messagesDB.insertOrIgnore(latestMessage)
|
||||
}
|
||||
|
||||
setupAdapter()
|
||||
|
@@ -56,6 +56,7 @@ class ConversationsAdapter(activity: SimpleActivity, var conversations: ArrayLis
|
||||
R.id.cab_dial_number -> dialNumber()
|
||||
R.id.cab_copy_number -> copyNumberToClipboard()
|
||||
R.id.cab_delete -> askConfirmDelete()
|
||||
R.id.cab_select_all -> selectAll()
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -39,6 +39,7 @@ import kotlinx.android.synthetic.main.item_received_unknown_attachment.view.*
|
||||
import kotlinx.android.synthetic.main.item_sent_unknown_attachment.view.*
|
||||
import kotlinx.android.synthetic.main.item_thread_date_time.view.*
|
||||
import kotlinx.android.synthetic.main.item_thread_error.view.*
|
||||
import kotlinx.android.synthetic.main.item_thread_sending.view.*
|
||||
import kotlinx.android.synthetic.main.item_thread_success.view.*
|
||||
|
||||
class ThreadAdapter(activity: SimpleActivity, var messages: ArrayList<ThreadItem>, recyclerView: MyRecyclerView, fastScroller: FastScroller,
|
||||
@@ -74,6 +75,7 @@ class ThreadAdapter(activity: SimpleActivity, var messages: ArrayList<ThreadItem
|
||||
R.id.cab_share -> shareText()
|
||||
R.id.cab_select_text -> selectText()
|
||||
R.id.cab_delete -> askConfirmDelete()
|
||||
R.id.cab_select_all -> selectAll()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,6 +97,7 @@ class ThreadAdapter(activity: SimpleActivity, var messages: ArrayList<ThreadItem
|
||||
THREAD_RECEIVED_MESSAGE -> R.layout.item_received_message
|
||||
THREAD_SENT_MESSAGE_ERROR -> R.layout.item_thread_error
|
||||
THREAD_SENT_MESSAGE_SUCCESS -> R.layout.item_thread_success
|
||||
THREAD_SENT_MESSAGE_SENDING -> R.layout.item_thread_sending
|
||||
else -> R.layout.item_sent_message
|
||||
}
|
||||
return createViewHolder(layout, parent)
|
||||
@@ -102,11 +105,14 @@ class ThreadAdapter(activity: SimpleActivity, var messages: ArrayList<ThreadItem
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val item = messages[position]
|
||||
holder.bindView(item, true, item is Message) { itemView, layoutPosition ->
|
||||
val isClickable = item is ThreadError || item is Message
|
||||
val isLongClickable = item is Message
|
||||
holder.bindView(item, isClickable, isLongClickable) { itemView, layoutPosition ->
|
||||
when (item) {
|
||||
is ThreadDateTime -> setupDateTime(itemView, item)
|
||||
is ThreadSuccess -> setupThreadSuccess(itemView)
|
||||
is ThreadError -> setupThreadError(itemView)
|
||||
is ThreadSending -> setupThreadSending(itemView)
|
||||
else -> setupView(itemView, item as Message)
|
||||
}
|
||||
}
|
||||
@@ -122,6 +128,7 @@ class ThreadAdapter(activity: SimpleActivity, var messages: ArrayList<ThreadItem
|
||||
(messages[position] as? Message)?.isReceivedMessage() == true -> THREAD_RECEIVED_MESSAGE
|
||||
item is ThreadError -> THREAD_SENT_MESSAGE_ERROR
|
||||
item is ThreadSuccess -> THREAD_SENT_MESSAGE_SUCCESS
|
||||
item is ThreadSending -> THREAD_SENT_MESSAGE_SENDING
|
||||
else -> THREAD_SENT_MESSAGE
|
||||
}
|
||||
}
|
||||
@@ -190,10 +197,13 @@ class ThreadAdapter(activity: SimpleActivity, var messages: ArrayList<ThreadItem
|
||||
|
||||
private fun isThreadDateTime(position: Int) = messages.getOrNull(position) is ThreadDateTime
|
||||
|
||||
override fun onViewRecycled(holder: ViewHolder) {
|
||||
super.onViewRecycled(holder)
|
||||
if (!activity.isDestroyed && !activity.isFinishing && holder.itemView.thread_message_sender_photo != null) {
|
||||
Glide.with(activity).clear(holder.itemView.thread_message_sender_photo)
|
||||
fun updateMessages(newMessages: ArrayList<ThreadItem>) {
|
||||
val oldHashCode = messages.hashCode()
|
||||
val newHashCode = newMessages.hashCode()
|
||||
if (newHashCode != oldHashCode) {
|
||||
messages = newMessages
|
||||
notifyDataSetChanged()
|
||||
recyclerView.scrollToPosition(messages.size - 1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,7 +266,9 @@ class ThreadAdapter(activity: SimpleActivity, var messages: ArrayList<ThreadItem
|
||||
}
|
||||
|
||||
builder.into(imageView.attachment_image)
|
||||
imageView.attachment_image.setOnClickListener { launchViewIntent(uri, mimetype, attachment.filename) }
|
||||
imageView.attachment_image.setOnClickListener {
|
||||
launchViewIntent(uri, mimetype, attachment.filename)
|
||||
}
|
||||
} else {
|
||||
if (message.isReceivedMessage()) {
|
||||
val attachmentView = layoutInflater.inflate(R.layout.item_received_unknown_attachment, null).apply {
|
||||
@@ -265,7 +277,9 @@ class ThreadAdapter(activity: SimpleActivity, var messages: ArrayList<ThreadItem
|
||||
thread_received_attachment_label.text = attachment.filename
|
||||
}
|
||||
setTextColor(textColor)
|
||||
setOnClickListener { launchViewIntent(uri, mimetype, attachment.filename) }
|
||||
setOnClickListener {
|
||||
launchViewIntent(uri, mimetype, attachment.filename)
|
||||
}
|
||||
}
|
||||
}
|
||||
thread_mesage_attachments_holder.addView(attachmentView)
|
||||
@@ -278,7 +292,9 @@ class ThreadAdapter(activity: SimpleActivity, var messages: ArrayList<ThreadItem
|
||||
if (attachment.filename.isNotEmpty()) {
|
||||
thread_sent_attachment_label.text = attachment.filename
|
||||
}
|
||||
setOnClickListener { launchViewIntent(uri, mimetype, attachment.filename) }
|
||||
setOnClickListener {
|
||||
launchViewIntent(uri, mimetype, attachment.filename)
|
||||
}
|
||||
}
|
||||
}
|
||||
thread_mesage_attachments_holder.addView(attachmentView)
|
||||
@@ -333,6 +349,20 @@ class ThreadAdapter(activity: SimpleActivity, var messages: ArrayList<ThreadItem
|
||||
}
|
||||
|
||||
private fun setupThreadError(view: View) {
|
||||
view.thread_error.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize)
|
||||
view.thread_error.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize - 4)
|
||||
}
|
||||
|
||||
private fun setupThreadSending(view: View) {
|
||||
view.thread_sending.apply {
|
||||
setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize)
|
||||
setTextColor(textColor)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewRecycled(holder: ViewHolder) {
|
||||
super.onViewRecycled(holder)
|
||||
if (!activity.isDestroyed && !activity.isFinishing && holder.itemView.thread_message_sender_photo != null) {
|
||||
Glide.with(activity).clear(holder.itemView.thread_message_sender_photo)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -8,6 +8,7 @@ import android.app.PendingIntent
|
||||
import android.content.ContentValues
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.database.Cursor
|
||||
import android.graphics.Bitmap
|
||||
import android.media.AudioAttributes
|
||||
import android.media.AudioManager
|
||||
@@ -320,6 +321,28 @@ fun Context.getThreadSnippet(threadId: Long): String {
|
||||
return snippet
|
||||
}
|
||||
|
||||
fun Context.getMessageRecipientAddress(messageId: Long): String {
|
||||
val uri = Sms.CONTENT_URI
|
||||
val projection = arrayOf(
|
||||
Sms.ADDRESS
|
||||
)
|
||||
|
||||
val selection = "${Sms._ID} = ?"
|
||||
val selectionArgs = arrayOf(messageId.toString())
|
||||
|
||||
try {
|
||||
val cursor = contentResolver.query(uri, projection, selection, selectionArgs, null)
|
||||
cursor?.use {
|
||||
if (cursor.moveToFirst()) {
|
||||
return cursor.getStringValue(Sms.ADDRESS)
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
fun Context.getThreadParticipants(threadId: Long, contactsMap: HashMap<Int, SimpleContact>?): ArrayList<SimpleContact> {
|
||||
val uri = Uri.parse("${MmsSms.CONTENT_CONVERSATIONS_URI}?simple=true")
|
||||
val projection = arrayOf(
|
||||
@@ -554,6 +577,26 @@ fun Context.markThreadMessagesUnread(threadId: Long) {
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.updateMessageType(id: Long, status: Int) {
|
||||
val uri = Sms.CONTENT_URI
|
||||
val contentValues = ContentValues().apply {
|
||||
put(Sms.TYPE, status)
|
||||
}
|
||||
val selection = "${Sms._ID} = ?"
|
||||
val selectionArgs = arrayOf(id.toString())
|
||||
contentResolver.update(uri, contentValues, selection, selectionArgs)
|
||||
}
|
||||
|
||||
fun Context.updateMessageSubscriptionId(messageId: Long, subscriptionId: Int) {
|
||||
val uri = Sms.CONTENT_URI
|
||||
val contentValues = ContentValues().apply {
|
||||
put(Sms.SUBSCRIPTION_ID, subscriptionId)
|
||||
}
|
||||
val selection = "${Sms._ID} = ?"
|
||||
val selectionArgs = arrayOf(messageId.toString())
|
||||
contentResolver.update(uri, contentValues, selection, selectionArgs)
|
||||
}
|
||||
|
||||
fun Context.updateUnreadCountBadge(conversations: List<Conversation>) {
|
||||
val unreadCount = conversations.count { !it.read }
|
||||
if (unreadCount == 0) {
|
||||
@@ -592,16 +635,21 @@ fun Context.getThreadId(addresses: Set<String>): Long {
|
||||
fun Context.showReceivedMessageNotification(address: String, body: String, threadId: Long, bitmap: Bitmap?) {
|
||||
val privateCursor = getMyContactsCursor()?.loadInBackground()
|
||||
ensureBackgroundThread {
|
||||
val senderName = getNameFromAddress(address, privateCursor)
|
||||
|
||||
Handler(Looper.getMainLooper()).post {
|
||||
showMessageNotification(address, body, threadId, bitmap, senderName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.getNameFromAddress(address: String, privateCursor: Cursor?): String {
|
||||
var sender = getNameAndPhotoFromPhoneNumber(address).name
|
||||
if (address == sender) {
|
||||
val privateContacts = MyContactsContentProvider.getSimpleContacts(this, privateCursor)
|
||||
sender = privateContacts.firstOrNull { it.doesContainPhoneNumber(address) }?.name ?: address
|
||||
}
|
||||
|
||||
Handler(Looper.getMainLooper()).post {
|
||||
showMessageNotification(address, body, threadId, bitmap, sender)
|
||||
}
|
||||
}
|
||||
return sender
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
|
@@ -23,6 +23,7 @@ const val THREAD_RECEIVED_MESSAGE = 2
|
||||
const val THREAD_SENT_MESSAGE = 3
|
||||
const val THREAD_SENT_MESSAGE_ERROR = 4
|
||||
const val THREAD_SENT_MESSAGE_SUCCESS = 5
|
||||
const val THREAD_SENT_MESSAGE_SENDING = 6
|
||||
|
||||
fun refreshMessages() {
|
||||
EventBus.getDefault().post(Events.RefreshMessages())
|
||||
|
@@ -29,6 +29,9 @@ interface MessagesDao {
|
||||
@Query("UPDATE messages SET read = 1 WHERE thread_id = :threadId")
|
||||
fun markThreadRead(threadId: Long)
|
||||
|
||||
@Query("UPDATE messages SET type = :type WHERE id = :id")
|
||||
fun updateType(id: Long, type: Int): Int
|
||||
|
||||
@Query("DELETE FROM messages WHERE id = :id")
|
||||
fun delete(id: Long)
|
||||
|
||||
|
@@ -19,7 +19,7 @@ data class Message(
|
||||
@ColumnInfo(name = "attachment") val attachment: MessageAttachment?,
|
||||
@ColumnInfo(name = "sender_name") var senderName: String,
|
||||
@ColumnInfo(name = "sender_photo_uri") val senderPhotoUri: String,
|
||||
@ColumnInfo(name = "subscription_id") val subscriptionId: Int) : ThreadItem() {
|
||||
@ColumnInfo(name = "subscription_id") var subscriptionId: Int) : ThreadItem() {
|
||||
|
||||
fun isReceivedMessage() = type == Telephony.Sms.MESSAGE_TYPE_INBOX
|
||||
}
|
||||
|
@@ -1,3 +1,3 @@
|
||||
package com.simplemobiletools.smsmessenger.models
|
||||
|
||||
data class ThreadError(val messageID: Long) : ThreadItem()
|
||||
data class ThreadError(val messageId: Long, val messageText: String) : ThreadItem()
|
||||
|
@@ -0,0 +1,3 @@
|
||||
package com.simplemobiletools.smsmessenger.models
|
||||
|
||||
data class ThreadSending(val messageId: Long) : ThreadItem()
|
@@ -44,7 +44,8 @@ class SmsReceiver : BroadcastReceiver() {
|
||||
context.updateUnreadCountBadge(context.conversationsDB.getUnreadConversations())
|
||||
|
||||
val participant = SimpleContact(0, 0, address, "", arrayListOf(address), ArrayList(), ArrayList())
|
||||
val message = Message(newMessageId, body, type, arrayListOf(participant), (date / 1000).toInt(), false, threadId, false, null, address, "", subscriptionId)
|
||||
val message = Message(newMessageId, body, type, arrayListOf(participant), (date / 1000).toInt(), false, threadId,
|
||||
false, null, address, "", subscriptionId)
|
||||
context.messagesDB.insertOrUpdate(message)
|
||||
}
|
||||
|
||||
|
@@ -1,12 +0,0 @@
|
||||
package com.simplemobiletools.smsmessenger.receivers
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import com.klinker.android.send_message.SentReceiver
|
||||
import com.simplemobiletools.smsmessenger.helpers.refreshMessages
|
||||
|
||||
class SmsSentReceiver : SentReceiver() {
|
||||
override fun onMessageStatusUpdated(context: Context, intent: Intent, receiverResultCode: Int) {
|
||||
refreshMessages()
|
||||
}
|
||||
}
|
@@ -0,0 +1,37 @@
|
||||
package com.simplemobiletools.smsmessenger.receivers
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.provider.Telephony
|
||||
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
||||
import com.simplemobiletools.smsmessenger.extensions.messagesDB
|
||||
import com.simplemobiletools.smsmessenger.extensions.updateMessageType
|
||||
import com.simplemobiletools.smsmessenger.helpers.refreshMessages
|
||||
|
||||
class SmsStatusDeliveredReceiver : BroadcastReceiver() {
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
if (intent.extras?.containsKey("message_uri") == true) {
|
||||
val uri = Uri.parse(intent.getStringExtra("message_uri"))
|
||||
val messageId = uri?.lastPathSegment?.toLong() ?: 0L
|
||||
ensureBackgroundThread {
|
||||
val type = Telephony.Sms.MESSAGE_TYPE_SENT
|
||||
context.updateMessageType(messageId, type)
|
||||
val updated = context.messagesDB.updateType(messageId, type)
|
||||
if (updated == 0) {
|
||||
Handler(Looper.getMainLooper()).postDelayed({
|
||||
ensureBackgroundThread {
|
||||
context.messagesDB.updateType(messageId, type)
|
||||
}
|
||||
}, 2000)
|
||||
}
|
||||
|
||||
refreshMessages()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,109 @@
|
||||
package com.simplemobiletools.smsmessenger.receivers
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Notification
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.app.PendingIntent
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.media.AudioAttributes
|
||||
import android.media.AudioManager
|
||||
import android.media.RingtoneManager
|
||||
import android.net.Uri
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.provider.Telephony
|
||||
import androidx.core.app.NotificationCompat
|
||||
import com.simplemobiletools.commons.extensions.getMyContactsCursor
|
||||
import com.simplemobiletools.commons.helpers.SimpleContactsHelper
|
||||
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
||||
import com.simplemobiletools.commons.helpers.isOreoPlus
|
||||
import com.simplemobiletools.smsmessenger.R
|
||||
import com.simplemobiletools.smsmessenger.activities.ThreadActivity
|
||||
import com.simplemobiletools.smsmessenger.extensions.*
|
||||
import com.simplemobiletools.smsmessenger.helpers.NOTIFICATION_CHANNEL
|
||||
import com.simplemobiletools.smsmessenger.helpers.THREAD_ID
|
||||
import com.simplemobiletools.smsmessenger.helpers.refreshMessages
|
||||
|
||||
class SmsStatusSentReceiver : BroadcastReceiver() {
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
if (intent.extras?.containsKey("message_uri") == true) {
|
||||
val uri = Uri.parse(intent.getStringExtra("message_uri"))
|
||||
val messageId = uri?.lastPathSegment?.toLong() ?: 0L
|
||||
ensureBackgroundThread {
|
||||
val type = if (intent.extras!!.containsKey("errorCode")) {
|
||||
showSendingFailedNotification(context, messageId)
|
||||
Telephony.Sms.MESSAGE_TYPE_FAILED
|
||||
} else {
|
||||
Telephony.Sms.MESSAGE_TYPE_OUTBOX
|
||||
}
|
||||
context.updateMessageType(messageId, type)
|
||||
context.messagesDB.updateType(messageId, type)
|
||||
refreshMessages()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showSendingFailedNotification(context: Context, messageId: Long) {
|
||||
Handler(Looper.getMainLooper()).post {
|
||||
val privateCursor = context.getMyContactsCursor()?.loadInBackground()
|
||||
ensureBackgroundThread {
|
||||
val address = context.getMessageRecipientAddress(messageId)
|
||||
val threadId = context.getThreadId(address)
|
||||
val senderName = context.getNameFromAddress(address, privateCursor)
|
||||
showNotification(context, senderName, threadId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
private fun showNotification(context: Context, recipientName: String, threadId: Long) {
|
||||
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
val soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
|
||||
if (isOreoPlus()) {
|
||||
val audioAttributes = AudioAttributes.Builder()
|
||||
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
|
||||
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
|
||||
.setLegacyStreamType(AudioManager.STREAM_NOTIFICATION)
|
||||
.build()
|
||||
|
||||
val name = context.getString(R.string.message_not_sent_short)
|
||||
val importance = NotificationManager.IMPORTANCE_HIGH
|
||||
NotificationChannel(NOTIFICATION_CHANNEL, name, importance).apply {
|
||||
setBypassDnd(false)
|
||||
enableLights(true)
|
||||
setSound(soundUri, audioAttributes)
|
||||
enableVibration(true)
|
||||
notificationManager.createNotificationChannel(this)
|
||||
}
|
||||
}
|
||||
|
||||
val intent = Intent(context, ThreadActivity::class.java).apply {
|
||||
putExtra(THREAD_ID, threadId)
|
||||
}
|
||||
|
||||
val pendingIntent = PendingIntent.getActivity(context, threadId.hashCode(), intent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
val summaryText = String.format(context.getString(R.string.message_sending_error), recipientName)
|
||||
|
||||
val largeIcon = SimpleContactsHelper(context).getContactLetterIcon(recipientName)
|
||||
val builder = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL)
|
||||
.setContentTitle(context.getString(R.string.message_not_sent_short))
|
||||
.setContentText(summaryText)
|
||||
.setColor(context.config.primaryColor)
|
||||
.setSmallIcon(R.drawable.ic_messenger)
|
||||
.setLargeIcon(largeIcon)
|
||||
.setStyle(NotificationCompat.BigTextStyle().bigText(summaryText))
|
||||
.setContentIntent(pendingIntent)
|
||||
.setPriority(NotificationCompat.PRIORITY_MAX)
|
||||
.setDefaults(Notification.DEFAULT_LIGHTS)
|
||||
.setCategory(Notification.CATEGORY_MESSAGE)
|
||||
.setAutoCancel(true)
|
||||
.setSound(soundUri, AudioManager.STREAM_NOTIFICATION)
|
||||
.setChannelId(NOTIFICATION_CHANNEL)
|
||||
|
||||
notificationManager.notify(threadId.hashCode(), builder.build())
|
||||
}
|
||||
}
|
@@ -42,7 +42,7 @@
|
||||
android:id="@+id/no_contacts_placeholder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/message_divider_two"
|
||||
android:layout_below="@+id/suggestions_scrollview"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginTop="@dimen/bigger_margin"
|
||||
android:alpha="0.8"
|
||||
|
@@ -6,6 +6,6 @@
|
||||
android:gravity="end"
|
||||
android:paddingStart="@dimen/activity_margin"
|
||||
android:paddingEnd="@dimen/activity_margin"
|
||||
android:text="@string/message_not_sent"
|
||||
android:text="@string/message_not_sent_touch_retry"
|
||||
android:textColor="@color/theme_dark_red_primary_color"
|
||||
android:textSize="@dimen/normal_text_size" />
|
||||
|
10
app/src/main/res/layout/item_thread_sending.xml
Normal file
10
app/src/main/res/layout/item_thread_sending.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/thread_sending"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="end"
|
||||
android:paddingStart="@dimen/activity_margin"
|
||||
android:paddingEnd="@dimen/activity_margin"
|
||||
android:text="@string/sending"
|
||||
android:textSize="@dimen/normal_text_size" />
|
@@ -25,4 +25,8 @@
|
||||
android:id="@+id/cab_copy_number"
|
||||
android:title="@string/copy_number_to_clipboard"
|
||||
app:showAsAction="never" />
|
||||
<item
|
||||
android:id="@+id/cab_select_all"
|
||||
android:title="@string/select_all"
|
||||
app:showAsAction="never" />
|
||||
</menu>
|
||||
|
@@ -20,4 +20,8 @@
|
||||
android:icon="@drawable/ic_delete_vector"
|
||||
android:title="@string/delete"
|
||||
app:showAsAction="ifRoom" />
|
||||
<item
|
||||
android:id="@+id/cab_select_all"
|
||||
android:title="@string/select_all"
|
||||
app:showAsAction="never" />
|
||||
</menu>
|
||||
|
@@ -2,7 +2,9 @@
|
||||
<string name="app_name">Schlichter SMS Messenger</string>
|
||||
<string name="app_launcher_name">SMS Messenger</string>
|
||||
<string name="type_a_message">Schreibe eine Nachricht…</string>
|
||||
<string name="message_not_sent">Nachricht wurde nicht gesendet.</string>
|
||||
<string name="message_not_sent_short">Message not sent</string>
|
||||
<string name="message_not_sent_touch_retry">Not sent. Touch to retry.</string>
|
||||
<string name="message_sending_error">Your message to \'%s\' has not been sent</string>
|
||||
<string name="add_person">Person hinzufügen</string>
|
||||
<string name="attachment">Anhang</string>
|
||||
<string name="no_conversations_found">Keine gespeicherten Chats gefunden</string>
|
||||
|
@@ -2,7 +2,9 @@
|
||||
<string name="app_name">Απλός SMS Messenger</string>
|
||||
<string name="app_launcher_name">SMS Messenger</string>
|
||||
<string name="type_a_message">Πληκτρολογήστε ένα μήνυμα…</string>
|
||||
<string name="message_not_sent">Το μήνυμα δεν έχει σταλεί.</string>
|
||||
<string name="message_not_sent_short">Message not sent</string>
|
||||
<string name="message_not_sent_touch_retry">Not sent. Touch to retry.</string>
|
||||
<string name="message_sending_error">Your message to \'%s\' has not been sent</string>
|
||||
<string name="add_person">Προσθήκη ατόμου</string>
|
||||
<string name="attachment">Συνημμένο</string>
|
||||
<string name="no_conversations_found">Δεν βρέθηκαν αποθηκευμένες συνομιλίες</string>
|
||||
|
@@ -2,7 +2,9 @@
|
||||
<string name="app_name">Mensajería SMS Simple</string>
|
||||
<string name="app_launcher_name">Mensajería SMS</string>
|
||||
<string name="type_a_message">Escribe un mensaje…</string>
|
||||
<string name="message_not_sent">El mensaje no se ha enviado.</string>
|
||||
<string name="message_not_sent_short">Message not sent</string>
|
||||
<string name="message_not_sent_touch_retry">Not sent. Touch to retry.</string>
|
||||
<string name="message_sending_error">Your message to \'%s\' has not been sent</string>
|
||||
<string name="add_person">Añadir persona</string>
|
||||
<string name="attachment">Archivo adjunto</string>
|
||||
<string name="no_conversations_found">No se han encontrado conversaciones</string>
|
||||
|
@@ -2,7 +2,9 @@
|
||||
<string name="app_name">Simple SMS Messenger</string>
|
||||
<string name="app_launcher_name">SMS Messenger</string>
|
||||
<string name="type_a_message">Écrivez un message…</string>
|
||||
<string name="message_not_sent">Le message n\'a pas été envoyé.</string>
|
||||
<string name="message_not_sent_short">Message not sent</string>
|
||||
<string name="message_not_sent_touch_retry">Not sent. Touch to retry.</string>
|
||||
<string name="message_sending_error">Your message to \'%s\' has not been sent</string>
|
||||
<string name="add_person">Ajouter une personne</string>
|
||||
<string name="attachment">Pièce jointe</string>
|
||||
<string name="no_conversations_found">Aucune conversation enregistrée n\'a été trouvée</string>
|
||||
|
@@ -2,7 +2,9 @@
|
||||
<string name="app_name">Simple SMS Messenger</string>
|
||||
<string name="app_launcher_name">SMS Messenger</string>
|
||||
<string name="type_a_message">Ketik pesan…</string>
|
||||
<string name="message_not_sent">Pesan belum terkirim.</string>
|
||||
<string name="message_not_sent_short">Message not sent</string>
|
||||
<string name="message_not_sent_touch_retry">Not sent. Touch to retry.</string>
|
||||
<string name="message_sending_error">Your message to \'%s\' has not been sent</string>
|
||||
<string name="add_person">Tambahkan Orang</string>
|
||||
<string name="attachment">Lampiran</string>
|
||||
<string name="no_conversations_found">Tidak ada percakapan tersimpan yang ditemukan</string>
|
||||
|
@@ -2,7 +2,9 @@
|
||||
<string name="app_name">Simple ショートメール</string>
|
||||
<string name="app_launcher_name">ショートメール</string>
|
||||
<string name="type_a_message">メッセージを入力してください…</string>
|
||||
<string name="message_not_sent">送信されませんでした。</string>
|
||||
<string name="message_not_sent_short">Message not sent</string>
|
||||
<string name="message_not_sent_touch_retry">Not sent. Touch to retry.</string>
|
||||
<string name="message_sending_error">Your message to \'%s\' has not been sent</string>
|
||||
<string name="add_person">宛先を追加</string>
|
||||
<string name="attachment">添付</string>
|
||||
<string name="no_conversations_found">保存された会話はありません</string>
|
||||
|
@@ -2,7 +2,9 @@
|
||||
<string name="app_name">Paprastas SMS Siuntiklis</string>
|
||||
<string name="app_launcher_name">SMS Siuntiklis</string>
|
||||
<string name="type_a_message">Rašykite žinutę…</string>
|
||||
<string name="message_not_sent">Žinutė neišsiųsta.</string>
|
||||
<string name="message_not_sent_short">Message not sent</string>
|
||||
<string name="message_not_sent_touch_retry">Not sent. Touch to retry.</string>
|
||||
<string name="message_sending_error">Your message to \'%s\' has not been sent</string>
|
||||
<string name="add_person">Pridėti žmogų</string>
|
||||
<string name="attachment">Priedas</string>
|
||||
<string name="no_conversations_found">Nebuvo rasta išsaugotų pokalbių</string>
|
||||
|
@@ -2,7 +2,9 @@
|
||||
<string name="app_name">Simple SMS Messenger</string>
|
||||
<string name="app_launcher_name">SMS മെസഞ്ചർ</string>
|
||||
<string name="type_a_message">മെസ്സേജ് ടൈപ്പ് ചെയ്യുക</string>
|
||||
<string name="message_not_sent">മെസ്സേജ് അയച്ചിട്ടില്ല.</string>
|
||||
<string name="message_not_sent_short">Message not sent</string>
|
||||
<string name="message_not_sent_touch_retry">Not sent. Touch to retry.</string>
|
||||
<string name="message_sending_error">Your message to \'%s\' has not been sent</string>
|
||||
<string name="add_person">വ്യക്തിയെ ചേർക്കുക</string>
|
||||
<string name="attachment">അറ്റാച്ചുമെന്റ്</string>
|
||||
<string name="no_conversations_found">സ്റ്റോർ ചെയ്ത സംഭാഷണങ്ങളൊന്നും കണ്ടെത്തിയില്ല</string>
|
||||
|
@@ -2,7 +2,9 @@
|
||||
<string name="app_name">Eenvoudig Berichtenbeheer (SMS)</string>
|
||||
<string name="app_launcher_name">Berichten</string>
|
||||
<string name="type_a_message">Typ een bericht…</string>
|
||||
<string name="message_not_sent">Bericht niet verzonden.</string>
|
||||
<string name="message_not_sent_short">Message not sent</string>
|
||||
<string name="message_not_sent_touch_retry">Not sent. Touch to retry.</string>
|
||||
<string name="message_sending_error">Your message to \'%s\' has not been sent</string>
|
||||
<string name="add_person">Persoon toevoegen</string>
|
||||
<string name="attachment">Bijlage</string>
|
||||
<string name="no_conversations_found">Geen opgeslagen berichten gevonden</string>
|
||||
@@ -10,9 +12,9 @@
|
||||
<string name="reply">Beantwoorden</string>
|
||||
<string name="show_character_counter">Teller voor het aantal tekens weergeven</string>
|
||||
<string name="loading_messages">Berichten laden…</string>
|
||||
<string name="no_reply_support">Sender doesn\'t support replies</string>
|
||||
<string name="draft">Draft</string>
|
||||
<string name="sending">Sending…</string>
|
||||
<string name="no_reply_support">Afzender ondersteunt geen antwoorden</string>
|
||||
<string name="draft">Concept</string>
|
||||
<string name="sending">Versturen…</string>
|
||||
|
||||
<!-- New conversation -->
|
||||
<string name="new_conversation">Nieuw gesprek</string>
|
||||
|
@@ -2,7 +2,9 @@
|
||||
<string name="app_name">Simple SMS Messenger</string>
|
||||
<string name="app_launcher_name">SMS Messenger</string>
|
||||
<string name="type_a_message">Escrever uma mensagem…</string>
|
||||
<string name="message_not_sent">Mensagem não enviada</string>
|
||||
<string name="message_not_sent_short">Message not sent</string>
|
||||
<string name="message_not_sent_touch_retry">Not sent. Touch to retry.</string>
|
||||
<string name="message_sending_error">Your message to \'%s\' has not been sent</string>
|
||||
<string name="add_person">Adicionar pessoa</string>
|
||||
<string name="attachment">Anexo</string>
|
||||
<string name="no_conversations_found">Não foram encontradas conversas</string>
|
||||
|
@@ -2,7 +2,9 @@
|
||||
<string name="app_name">Simple SMS Messenger</string>
|
||||
<string name="app_launcher_name">Сообщения</string>
|
||||
<string name="type_a_message">Введите сообщение…</string>
|
||||
<string name="message_not_sent">Сообщение не отправлено.</string>
|
||||
<string name="message_not_sent_short">Message not sent</string>
|
||||
<string name="message_not_sent_touch_retry">Not sent. Touch to retry.</string>
|
||||
<string name="message_sending_error">Your message to \'%s\' has not been sent</string>
|
||||
<string name="add_person">Добавить участника</string>
|
||||
<string name="attachment">Вложение</string>
|
||||
<string name="no_conversations_found">Нет сохранённых переписок</string>
|
||||
|
@@ -2,7 +2,9 @@
|
||||
<string name="app_name">Jednoduché SMS správy</string>
|
||||
<string name="app_launcher_name">SMS správy</string>
|
||||
<string name="type_a_message">Zadajte správu…</string>
|
||||
<string name="message_not_sent">Správa nebola odoslaná.</string>
|
||||
<string name="message_not_sent_short">Správa nebola odoslaná</string>
|
||||
<string name="message_not_sent_touch_retry">Správa neodoslaná. Dotykom to skúste znova.</string>
|
||||
<string name="message_sending_error">Vaša správa pre \'%s\' nebola odoslaná</string>
|
||||
<string name="add_person">Pridať osobu</string>
|
||||
<string name="attachment">Príloha</string>
|
||||
<string name="no_conversations_found">Nenašli sa žiadne uložené konverzácie</string>
|
||||
|
@@ -2,7 +2,9 @@
|
||||
<string name="app_name">Basit SMS Messenger</string>
|
||||
<string name="app_launcher_name">SMS Messenger</string>
|
||||
<string name="type_a_message">Bir mesaj yazın…</string>
|
||||
<string name="message_not_sent">Mesaj gönderilmedi.</string>
|
||||
<string name="message_not_sent_short">Message not sent</string>
|
||||
<string name="message_not_sent_touch_retry">Not sent. Touch to retry.</string>
|
||||
<string name="message_sending_error">Your message to \'%s\' has not been sent</string>
|
||||
<string name="add_person">Kişi Ekle</string>
|
||||
<string name="attachment">Ek</string>
|
||||
<string name="no_conversations_found">Kaydedilmiş görüşme bulunamadı</string>
|
||||
|
@@ -2,7 +2,9 @@
|
||||
<string name="app_name">Simple SMS Messenger</string>
|
||||
<string name="app_launcher_name">Повідомлення</string>
|
||||
<string name="type_a_message">Введіть повідомлення…</string>
|
||||
<string name="message_not_sent">Повідомлення не надіслано. </string>
|
||||
<string name="message_not_sent_short">Message not sent</string>
|
||||
<string name="message_not_sent_touch_retry">Not sent. Touch to retry.</string>
|
||||
<string name="message_sending_error">Your message to \'%s\' has not been sent</string>
|
||||
<string name="add_person">Додати учасник а</string>
|
||||
<string name="attachment">Вкладення</string>
|
||||
<string name="no_conversations_found">Немає збережених листувань</string>
|
||||
|
@@ -2,7 +2,9 @@
|
||||
<string name="app_name">简易短信</string>
|
||||
<string name="app_launcher_name">短信</string>
|
||||
<string name="type_a_message">输入一个消息…</string>
|
||||
<string name="message_not_sent">消息尚未发送。</string>
|
||||
<string name="message_not_sent_short">Message not sent</string>
|
||||
<string name="message_not_sent_touch_retry">Not sent. Touch to retry.</string>
|
||||
<string name="message_sending_error">Your message to \'%s\' has not been sent</string>
|
||||
<string name="add_person">添加人</string>
|
||||
<string name="attachment">附件</string>
|
||||
<string name="no_conversations_found">未找到保存的对话</string>
|
||||
|
@@ -2,7 +2,9 @@
|
||||
<string name="app_name">Simple SMS Messenger</string>
|
||||
<string name="app_launcher_name">SMS Messenger</string>
|
||||
<string name="type_a_message">Type a message…</string>
|
||||
<string name="message_not_sent">Message has not been sent.</string>
|
||||
<string name="message_not_sent_short">Message not sent</string>
|
||||
<string name="message_not_sent_touch_retry">Not sent. Touch to retry.</string>
|
||||
<string name="message_sending_error">Your message to \'%s\' has not been sent</string>
|
||||
<string name="add_person">Add Person</string>
|
||||
<string name="attachment">Attachment</string>
|
||||
<string name="no_conversations_found">No stored conversations have been found</string>
|
||||
|
4
fastlane/metadata/android/en-US/changelogs/25.txt
Normal file
4
fastlane/metadata/android/en-US/changelogs/25.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
* Improved delivery reports, show a notification at failed messages
|
||||
* Allow resending failed messages with tapping them
|
||||
* Added multiple dual-SIM related improvements
|
||||
* Many other UX, stability, performance and translation improvements
|
Reference in New Issue
Block a user